网风's profile网风空间PhotosBlogLists Tools Help

Blog


    July 29

    读写配置文件

    .net Framework 2.0 专门提供了配置文件的操作。 namespace System.Configuration; 1. 创建配置节类 必须创建继承自ConfigurationSection的对象才能进行配置数据读写操作,ConfigurationSection提供了索引器用来获取和设置配置数据,需要注意的是拥有ConfigurationProperty特性的属性才会被存储,并且名称要保持大小写完全一致,如下面的代码中,所有的"id"必须保持一样。 class ConfigSectionData : ConfigurationSection { [ConfigurationProperty("id")] public int Id { get { return (int)this["id"]; } set { this["id"] = value; } } [ConfigurationProperty("time")] public DateTime Time { get { return (DateTime)this["time"]; } set { this["time"] = value; } } } 2. 创建配置文件操作对象 Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ConfigSectionData data = new ConfigSectionData(); data.Id = 1000; data.Time = DateTime.Now; config.Sections.Add("add", data); config.Save(ConfigurationSaveMode.Minimal); 上面的例子是操作 app.config,在根节点(configuration)下写入名称为"add"的配置数据。 需要注意的 VS2005 在IDE模式下会将信息写入 *.vshost.exe.config,并且在程序关闭时覆写该文件,因此您可能看不到您写入的配置数据,只要在资源管理其中执行 *.exe 文件,您就可以在 *.exe.config 文件中看到结果了。 如果我们需要操作非缺省配置文件,可以使用ExeConfigurationFileMap对象。 ExeConfigurationFileMap file = new ExeConfigurationFileMap(); file.ExeConfigFilename = "test.config"; Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None); ConfigSectionData data = new ConfigSectionData(); data.Id = 1000; data.Time = DateTime.Now; config.Sections.Add("add", data); config.Save(ConfigurationSaveMode.Minimal); 如果我们不希望在根节点下写入配置数据,可以使用ConfigurationSectionGroup对象。 ExeConfigurationFileMap file = new ExeConfigurationFileMap(); file.ExeConfigFilename = "test.config"; Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None); ConfigSectionData data = new ConfigSectionData(); data.Id = 1000; data.Time = DateTime.Now; config.SectionGroups.Add("group1", new ConfigurationSectionGroup()); config.SectionGroups["group1"].Sections.Add("add", data); config.Save(ConfigurationSaveMode.Minimal); 下面就是生成的配置文件。 3. 读取配置文件 ExeConfigurationFileMap file = new ExeConfigurationFileMap(); file.ExeConfigFilename = "test.config"; Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None); ConfigSectionData data = config.SectionGroups["group1"].Sections["add"] as ConfigSectionData; //ConfigSectionData data = config.Sections["add"] as ConfigSectionData; // 从根节读取 if (data != null) { Console.WriteLine(data.Id); Console.WriteLine(data.Time); } 4. 写配置文件 在写入 ConfigurationSectionGroup 和 ConfigurationSection 前要判断同名配置是否已经存在,否则会写入失败。另外如果配置文件被其他Configuration对象修改,则保存会失败,并抛出异常。建议采用Singleton模式。 ExeConfigurationFileMap file = new ExeConfigurationFileMap(); file.ExeConfigFilename = "test.config"; Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None); ConfigSectionData data = new ConfigSectionData(); data.Id = 2000; data.Time = DateTime.Now; ConfigurationSectionGroup group1 = config.SectionGroups["group1"]; if (group1 == null) config.SectionGroups.Add("group1", new ConfigurationSectionGroup()); ConfigurationSection data = group1.Sections["add"] as config; if (add == null) config.SectionGroups["group1"].Sections.Add("add", data); else { group1.Sections.Remove("add"); group1.Sections.Add("add", data); // 或者直接修改原配置对象,前提是类型转换要成功。 //ConfigSectionData configData = add as ConfigSectionData; //configData.Id = data.Id; //configData.Time = data.Time; } config.Save(ConfigurationSaveMode.Minimal); 5. 删除配置节 删除ConfigurationSectionGroup config.SectionGroups.Remove("group1"); //config.SectionGroups.Clear(); config.Save(ConfigurationSaveMode.Minimal); 删除ConfigurationSection config.Sections.Remove("add1"); //config.Sections.Clear(); if (config.SectionGroups["group1"] != null) { config.SectionGroups["group1"].Sections.Remove("add2"); //config.SectionGroups["group1"].Sections.Clear(); } config.Save(ConfigurationSaveMode.Minimal); 6. 其他 可以使用 ConfigurationManager.OpenMachineConfiguration() 来操作 Machine.config 文件。或者使用 System.Web.Configuration 名字空间中的 WebConfigurationManager 类来操作 ASP.net 配置文件。 ConfigurationManager还提供了AppSettings、ConnectionStrings、GetSection()等便捷操作。 7. 使用自定义类 2006-4-17 补充,回复 ggy 网友的疑问。引用至 ggy 比如ConfigSectionData里面除了简单类型之外,可不可以有自定义的类可以使用自定义类,不过需要定义一个转换器。 using System; using System.Collections; using System.Collections.Generic; using System.Configuration; using System.Globalization; using System.ComponentModel; // 要写入配置文件的自定义类 class CustomData { public CustomData(string s) { this.s = s; } private string s; public string S { get { return s; } set { s = value; } } } // 自定义的转换器(演示代码省略了类型判断) class CustomConvert : ConfigurationConverterBase { public override bool CanConvertFrom(ITypeDescriptorContext ctx, Type type) { return (type == typeof(string)); } public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type) { return (value as CustomData).S; } public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data) { return new CustomData((string)data);; } } class ConfigSectionData : ConfigurationSection { [ConfigurationProperty("id")] public int Id { get { return (int)this["id"]; } set { this["id"] = value; } } [ConfigurationProperty("time")] public DateTime Time { get { return (DateTime)this["time"]; } set { this["time"] = value; } } [ConfigurationProperty("custom")] [TypeConverter(typeof(CustomConvert))] // 指定转换器 public CustomData Custom { get { return (CustomData)this["custom"]; } set { this["custom"] = value; } } } public class Program { static void Main(string[] args) { Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ConfigSectionData data = new ConfigSectionData(); data.Id = 1000; data.Time = DateTime.Now; data.Custom = new CustomData("abcdefg..."); config.Sections.Add("add", data); config.Save(ConfigurationSaveMode.Minimal); // 读取测试 ConfigSectionData configData = (ConfigSectionData)config.Sections["add"]; Console.WriteLine(configData.Custom.S); } } 保存后的配置文件 更详细的信息可以看 MSDN 中关于 System.Configuration.ConfigurationConverterBase 的说明。

    在.net中使用GDI+来提高gif图片的保存画质

    //本文章有www.blue1000.com翻译,原文地址http://codebetter.com/blogs/brendan.tompkins/archive/2004/01/26/6103.aspx
    //尊重他人劳动成果,转载请注明出处。

    写程序的时候经常用到gdi+,他可以将一幅深色32 bpp图像保存为一个gif文件,过程也比较简单。并且在使用CreateThumnailImage方法保存这个gif图片之前,你还可以调整它的尺寸。
    常用的代码:

    System.Drawing.Bitmap b = new System.Drawing.Bitmap(“c:\\original_image.gif“);
    System.Drawing.Image thmbnail = b.GetThumbnailImage(100,75,null,new IntPtr());
    thmbnail.Save(“c:\\thumnail.gif“, System.Drawing.Imaging.ImageFormat.Gif);

    以上代码可以完成gif文件的绘制和保存工作,但是很快你就会发现问题了:生成的thumnail.gif文件的画质远远低于我们的期望值。
    效果图片:


    如上图所示的低画质粒状图象还需要进行“颜色量子化”处理(palettization)。之所以会出现这种情况,是因为GDI+默认使用256色,而没有考虑图像自身实际的颜色。

    之后,我们尝试着建立自己的“调色板”,可是结果更糟糕:)。一个好的“颜色量子化”算法应该考虑在两个像素颗粒之间填充与这两个像素颜色相近的过渡颜色,提供更多可视颜色空间。
    这就是“Octree“ 算法。“Octree“ 算法允许我们插入自己的算法来量子化我们的图像。

    这里有微软的两片文章,或许对我们有帮助:KB 319061  和 Optimizing Color Quantization for ASP.NET Images (微软Morgan Skinner著)。Morgan Skinner提供了很好的“Octree“ 算法代码,大家可以下载参考使用。

    使用octreequantizer很方便:

    system.drawing.bitmap b = new System.Drawing.Bitmap(“c:\\original_image.gif“);
    System.Drawing.Image thmbnail = b.GetThumbnailImage(100,75,null,new IntPtr());
    OctreeQuantizer quantizer = new OctreeQuantizer ( 255 , 8 ) ;
    using ( Bitmap quantized = quantizer.Quantize ( thmbnail ) )
    {
         quantized.Save(“c:\\thumnail.gif“, System.Drawing.Imaging.ImageFormat.Gif);
    }

    octreequantizer grayquantizer = new GrayscaleQuantizer ( ) ;
    using ( Bitmap quantized = grayquantizer.Quantize ( thmbnail ) )
    {
         quantized.Save(“c:\\thumnail.gif“, System.Drawing.Imaging.ImageFormat.Gif);
    }

    效果图片如下(是不是漂亮多了?):

       

    点击这里下载项目代码,修改namespace就可以在你自己的项目中使用它了。