C#操作ini文件的问题

原创 2006年06月14日 20:47:00

 

  本来操作ini文件调用windows提供的那几个api是非常简单的事,可是在C#中用来却不见的那么
舒畅,主要是因为API调用后返回的串值上的问题.
  在.net的sdk中提供的示例是用StringBuilder和IntPtr类来获取调用后返回的串值.以下是sdk
中的Buffers示例:
public class LibWrap
{
	// UINT GetSystemDirectory(LPTSTR lpBuffer, UINT uSize)
	[ DllImport( "Kernel32.dll", CharSet=CharSet.Auto )]
	public static extern int GetSystemDirectory( StringBuilder sysDirBuffer, int size );  
	
	// BOOL GetUserName(LPTSTR lpBuffer,LPDWORD nSize);
	[ DllImport( "Advapi32.dll", CharSet=CharSet.Auto )]
	public static extern bool GetUserName( StringBuilder userNameBuffer, ref int size );	
    
	// LPTSTR GetCommandLine();
    [DllImport("Kernel32.dll", CharSet=CharSet.Auto)]
    public static extern IntPtr GetCommandLine();	
}

public class App
{
	public static void Main()
	{
	// call GetSystemDirectory
	StringBuilder sysDirBuffer = new StringBuilder( 256 );
	LibWrap.GetSystemDirectory( sysDirBuffer, sysDirBuffer.Capacity );
	Console.WriteLine( "SysDir: {0}", sysDirBuffer );
	
	// call GetUserName
	StringBuilder userNameBuffer = new StringBuilder( 128 );
	int size = userNameBuffer.Capacity;
	LibWrap.GetUserName( userNameBuffer, ref size );
	Console.WriteLine( "UserName: {0}", userNameBuffer );
	
        IntPtr cmdLineStr = LibWrap.GetCommandLine();
        String commandLine = Marshal.PtrToStringAuto( cmdLineStr );
        Console.WriteLine( "CommandLine: {0}", commandLine );		
	}
}

  表面上以上的例子完全达到了我们的目的.可是当调用的api返回的串是用 ' /0 ' 分隔的n条串时(如下面用
到的GetPrivateProfileSectionNames和GetPrivateProfileSection)以上的方法就只能获取最前面的一条
串了,因为.net中的 Marshal类提供的方法和StringBuilder类的ToString()只是简单的截取 ' /0 ' 前的串数
据,所以后面的数据就给无辜的丢弃了.

  有朋友想到了用byte数组来缓存串数据的方法 -- 分配一个很大的byte数组把数组的指针用托管的方式
封送给API(添加[MarshalAs(UnmanagedType.LPArray)]特性),再用System.Text提供字符编码转换类(
ASCIIEncoding、UTF8Encoding)把byte数组里的串数据转换为String类数据.这种方法虽然实现了我们的伟
大目标,但在串的转换上却损失了不少的性能.

  我个人经过一翻的探索发现一个目前来讲比较好的解决方法. 这个方法的主要思想是:
  1,string类允许我们用char、sbyte类型的数据来填充构造函数,所以我们有办法预先分配一个足够的缓冲
    区来存储我们要的返回串数据;
  2,我们同样可以把string类型的数据的指针用托管的方式封送给API,Ansi的API添加[MarshalAs(
    UnmanagedType.LPStr)]特性,unicode的API添加[MarshalAs(UnmanagedType.LPWStr)]特性.
    注意:如果存在unicode的API最好使用unicode的API,因为.net中的string类存储的unicode字符串且,Ansi
    的API也是调用unicode的API的,所以我们直接调用unicode的API减免了CLR把Ansi字符串转换为unicode
    字符串的步骤,自然性能上也就不同了.

  OK!下面是我实现的ini文件操作类的代码:
/// <summary>
/// ini文件操作类
/// </summary>
public class CIni
{
	#region 段信息的获取
	//读取一个ini 文件中的所有段
	[DllImport("kernel32", EntryPoint = "GetPrivateProfileSectionNamesW", CharSet= CharSet.Unicode )]
        private extern static int getSectionNames(
        [MarshalAs(UnmanagedType.LPWStr )] string szBuffer, int nlen, string filename);

	//读取段里的所有数据
	[DllImport("kernel32",EntryPoint="GetPrivateProfileSectionW", CharSet = CharSet.Unicode)]
        private extern static int getSectionValues(string Section,
        [MarshalAs(UnmanagedType.LPWStr)] string szBuffer, int nlen, string filename);
	#endregion


	#region 键值的获取和设置
	//读取键的整形值
	[DllImport("kernel32",EntryPoint="GetPrivateProfileIntW" , CharSet = CharSet.Unicode)]
	private static extern int getKeyIntValue(string Section,string Key,int nDefault,string FileName);

	//读取字符串键值
	[DllImport("kernel32",EntryPoint="GetPrivateProfileStringW" , CharSet = CharSet.Unicode)]
	private extern static int getKeyValue(string section,string key,int lpDefault,
        [MarshalAs(UnmanagedType.LPWStr)] string szValue, int nlen, string filename);

	//
	//
	//写字符串键值
	[DllImport("kernel32",EntryPoint="WritePrivateProfileStringW" , CharSet = CharSet.Unicode)]
	private static extern bool setKeyValue(string Section,string key,string szValue,string FileName);

	//写段值
	[DllImport("kernel32",EntryPoint ="WritePrivateProfileSectionW" , CharSet = CharSet.Unicode)]
	private static extern bool setSectionValue(string section,string szvalue,string filename);
	#endregion

	private static readonly char []sept={ ' /0 ' };	//分隔字符

	private string m_Path=null;		//ini文件路径

	/// <summary>
	/// ini文件路径
	/// </summary>
	public string Path
	{
		set {m_Path=value;}
		get {return m_Path;}
	}
	
	public CIni(){}
	public CIni(string szPath)
	{
		m_Path=szPath;
	}

	/// <summary>
	/// 读取所有段名
	/// </summary>
	public string []SectionNames
	{
		get
		{	
			string buffer = new string( ' /0 ' ,32768);
			int nlen = getSectionNames(buffer,32768-1,m_Path)-1;
			if (nlen >0 )
			{
			return buffer.Substring(0,nlen).Split(sept);
			}
			return null;
		}
	}	

	/// <summary>
	/// 读取段里的数据到一个字符串数组
	/// </summary>
        /// <param name="section">段名</param>
        /// <param name="bufferSize">读取的数据大小(字节)</param>
	/// <returns>成功则不为null</returns>
        public string[] SectionValues(string section,int bufferSize)
        {
            string buffer = new string( ' /0 ' , bufferSize);
            int nlen = getSectionValues(section, buffer, bufferSize, m_Path) - 1;
            if (nlen > 0)
            {
                return buffer.Substring(0, nlen).Split(sept);
            }
            return null;
        }
        public string[] SectionValues(string section)
        {
            return SectionValues(section, 32768);
        }

	/// <summary>
        /// 从一个段中读取其 键-值 数据
	/// </summary>
	/// <param name="section">段名</param>
	/// <param name="bufferSize">读取的数据大小(字节)</param>
	/// <returns>成功则不为null</returns>
        public Dictionary<string, string> SectionValuesEx(string section, int bufferSize)
	{
            string[] sztmp = SectionValues(section, bufferSize);
		if (sztmp !=null)
		{
		int ArrayLen=sztmp.Length;
		if ( ArrayLen >0)
		{
                    Dictionary<string, string> dtRet = new Dictionary<string, string>();
			for (int i=0;i <ArrayLen;i++)
			{
			int pos1=sztmp[i].IndexOf( ' = ' );
			if (pos1 >1)
			{
				int nlen=sztmp[i].Length;
                            //	取键名,键值
				pos1++;
				if (pos1<nlen)
                             dtRet.Add(sztmp[i].Substring(0, pos1-1), sztmp[i].Substring(pos1, nlen - pos1));
			}
			}
                    return dtRet;
		}
		}
		return null;
	}
        public Dictionary<string, string> SectionValuesEx(string section)
        {
            return SectionValuesEx(section, 32768);
        }

	/// <summary>
	/// 写一个段的数据
	/// </summary>
	/// <param name="section"></param>
	/// <param name="szValue">段的数据(如果为null则删除这个段)</param>
	/// <returns>成功则为true</returns>
	public bool setSectionValue(string section,string szValue)
	{
		return setSectionValue(section,szValue,m_Path);
	}

	/// <summary>
	/// 读整形键值
	/// </summary>
	/// <param name="section"></param>
	/// <param name="key"></param>
	/// <returns>成功则不为-1</returns>
	public int getKeyIntValue(string section,string key)
	{
		return getKeyIntValue(section,key,-1,m_Path);
	}
	
	/// <summary>
	/// 写整形键值
	/// </summary>
	/// <param name="section"></param>
	/// <param name="key"></param>
	/// <param name="dwValue"></param>
	/// <returns>成功则为true</returns>
	public bool setKeyIntValue(string section,string key,int dwValue)
	{
		return setKeyValue(section,key,dwValue.ToString(),m_Path);
	}

	/// <summary>
	/// 读取键值
	/// </summary>
	/// <param name="section"></param>
	/// <param name="key"></param>
	/// <returns>成功则不为null</returns>
	public string getKeyValue(string section,string key)
	{
		string szBuffer=new string ( ' 0 ' ,256);
		int nlen=getKeyValue(section,key,0, szBuffer,256,m_Path);
		return szBuffer.Substring(0,nlen-1);
	}
    
	/// <summary>
	/// 写字符串键值
	/// </summary>
	/// <param name="Section"></param>
	/// <param name="key"></param>
	/// <param name="szValue"></param>
	/// <returns>成功则为true</returns>
	public bool setKeyValue(string Section ,string key,string szValue)
	{
		return setKeyValue(Section,key,szValue,m_Path);
	}
	}//end class CIni

CIni类的使用示例

 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

c# 操作 ini 配置文件

C# ini文件操作

  • 2016-11-16 10:08
  • 99KB
  • 下载

C#INI文件操作类

参考文章:http://www.cnblogs.com/wayfarer/archive/2004/07/16/24783.html using System; using System.Coll...

C#目录和ini文件操作

c#操作ini文件

  • 2011-11-01 09:04
  • 15KB
  • 下载

关于C#操作INI文件的总结

INI文件其实是一种具有特定结构的文本文件,它的构成分为三部分,结构如下: [Section1] key 1 = value2 key 1 = value2 …… [Section2...

C# 关于 ini 配置文件的操作

Ini 配置文件操作 在C#语言中,VS平台并没有给大家提供一个专门用来操作INI配置文件的类。 在本文中主要编写了一个特定的类用来对Ini文件进行操作。 代码: /// ...

C#操作INI配置文件

  • 2011-04-26 16:54
  • 36KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)