对于开发C/S系统的编程人员来说,ini文件是不会陌生的,当XML越来越普及的时候,如何把原来的INI文件转换程XML就成为一件棘手的事情。下面我把这方面的代码奉献给大家,如果有什么bug,欢迎批评指正:qieyj@cape.com.cn。
frmMain.cs
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Loki
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class frmMain : System.Windows.Forms.Form
{
public System.Windows.Forms.Button btnConvert;
public System.Windows.Forms.TextBox txtXMLFileName;
public System.Windows.Forms.Label Label2;
public System.Windows.Forms.TextBox txtIniFileName;
public System.Windows.Forms.Button btnClose;
public System.Windows.Forms.Label Label1;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public frmMain()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnConvert = new System.Windows.Forms.Button();
this.txtXMLFileName = new System.Windows.Forms.TextBox();
this.txtIniFileName = new System.Windows.Forms.TextBox();
this.Label1 = new System.Windows.Forms.Label();
this.btnClose = new System.Windows.Forms.Button();
this.Label2 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// btnConvert
//
this.btnConvert.BackColor = System.Drawing.SystemColors.Control;
this.btnConvert.Cursor = System.Windows.Forms.Cursors.Default;
this.btnConvert.Location = new System.Drawing.Point(160, 96);
this.btnConvert.Name = "btnConvert";
this.btnConvert.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.btnConvert.Size = new System.Drawing.Size(105, 25);
this.btnConvert.TabIndex = 4;
this.btnConvert.Text = "&Convert";
this.btnConvert.Click += new System.EventHandler(this.btnConvert_Click);
//
// txtXMLFileName
//
this.txtXMLFileName.AcceptsReturn = true;
this.txtXMLFileName.AutoSize = false;
this.txtXMLFileName.BackColor = System.Drawing.SystemColors.Window;
this.txtXMLFileName.Cursor = System.Windows.Forms.Cursors.IBeam;
this.txtXMLFileName.ForeColor = System.Drawing.SystemColors.WindowText;
this.txtXMLFileName.Location = new System.Drawing.Point(104, 48);
this.txtXMLFileName.MaxLength = 0;
this.txtXMLFileName.Name = "txtXMLFileName";
this.txtXMLFileName.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.txtXMLFileName.Size = new System.Drawing.Size(273, 25);
this.txtXMLFileName.TabIndex = 3;
this.txtXMLFileName.Text = "";
//
// txtIniFileName
//
this.txtIniFileName.AcceptsReturn = true;
this.txtIniFileName.AutoSize = false;
this.txtIniFileName.BackColor = System.Drawing.SystemColors.Window;
this.txtIniFileName.Cursor = System.Windows.Forms.Cursors.IBeam;
this.txtIniFileName.ForeColor = System.Drawing.SystemColors.WindowText;
this.txtIniFileName.Location = new System.Drawing.Point(104, 16);
this.txtIniFileName.MaxLength = 0;
this.txtIniFileName.Name = "txtIniFileName";
this.txtIniFileName.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.txtIniFileName.Size = new System.Drawing.Size(273, 25);
this.txtIniFileName.TabIndex = 1;
this.txtIniFileName.Text = "E:\\Source\\Loki\\INI2XML\\VB.NET\\projINI2XML.NET\\Sample.ini";
//
// Label1
//
this.Label1.AutoSize = true;
this.Label1.BackColor = System.Drawing.SystemColors.Control;
this.Label1.Cursor = System.Windows.Forms.Cursors.Default;
this.Label1.ForeColor = System.Drawing.SystemColors.ControlText;
this.Label1.Location = new System.Drawing.Point(16, 24);
this.Label1.Name = "Label1";
this.Label1.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.Label1.Size = new System.Drawing.Size(68, 13);
this.Label1.TabIndex = 0;
this.Label1.Text = "INI Filename";
//
// btnClose
//
this.btnClose.BackColor = System.Drawing.SystemColors.Control;
this.btnClose.Cursor = System.Windows.Forms.Cursors.Default;
this.btnClose.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.btnClose.Location = new System.Drawing.Point(272, 96);
this.btnClose.Name = "btnClose";
this.btnClose.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.btnClose.Size = new System.Drawing.Size(105, 25);
this.btnClose.TabIndex = 5;
this.btnClose.Text = "Close";
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// Label2
//
this.Label2.AutoSize = true;
this.Label2.BackColor = System.Drawing.SystemColors.Control;
this.Label2.Cursor = System.Windows.Forms.Cursors.Default;
this.Label2.ForeColor = System.Drawing.SystemColors.ControlText;
this.Label2.Location = new System.Drawing.Point(16, 56);
this.Label2.Name = "Label2";
this.Label2.RightToLeft = System.Windows.Forms.RightToLeft.No;
this.Label2.Size = new System.Drawing.Size(77, 13);
this.Label2.TabIndex = 2;
this.Label2.Text = "XML Filename";
//
// frmMain
//
this.AcceptButton = this.btnConvert;
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.CancelButton = this.btnClose;
this.ClientSize = new System.Drawing.Size(392, 141);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.btnConvert,
this.txtXMLFileName,
this.Label2,
this.txtIniFileName,
this.btnClose,
this.Label1});
this.Name = "frmMain";
this.Text = "INI 2 XML";
this.Load += new System.EventHandler(this.frmMain_Load);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new frmMain());
}
private void frmMain_Load(object sender, System.EventArgs e)
{
}
private void btnConvert_Click(object sender, System.EventArgs e)
{
if (INI2XML.Convert( txtIniFileName.Text, txtXMLFileName.Text ))
System.Windows.Forms.MessageBox.Show( "Successfully converted \"" + txtIniFileName.Text + "\" to \"" + txtXMLFileName.Text + "\"", this.Text, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information );
else
System.Windows.Forms.MessageBox.Show( "Problem converting \"" + txtIniFileName.Text + "\" to \"" + txtXMLFileName.Text + "\"", this.Text, System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation );
}
private void btnClose_Click(object sender, System.EventArgs e)
{
this.Close();
}
}
}
INI2XML.cs
using System;
namespace Loki
{
using System.Runtime.InteropServices;
/// <summary>
/// WIN32 API Wrapper class
/// </summary>
public class WIN32Wrapper
{
/// <summary>
/// Get all the section names from an INI file
/// </summary>
[ DllImport("kernel32.dll", EntryPoint="GetPrivateProfileSectionNamesA") ]
public extern static int GetPrivateProfileSectionNames(
[MarshalAs(UnmanagedType.LPArray)] byte[] lpReturnedString,
int nSize,
string lpFileName);
/// <summary>
/// Get all the settings from a section in a INI file
/// </summary>
[ DllImport("kernel32.dll", EntryPoint="GetPrivateProfileSectionA") ]
public extern static int GetPrivateProfileSection(
string lpAppName,
[MarshalAs(UnmanagedType.LPArray)] byte[] lpReturnedString,
int nSize,
string lpFileName);
}
/// <summary>
/// Convert an INI file into an XML file
/// </summary>
public class INI2XML
{
/// <summary>
///
/// </summary>
public INI2XML()
{
}
/// <summary>
/// Initial size of the buffer used when calling the Win32 API functions
/// </summary>
const int INITIAL_BUFFER_SIZE = 1024;
/// <summary>
/// Converts an INI file into an XML file.
/// Output XML file has the following structure...
/// <?xml version="1.0"?>
/// <configuration>
/// <section name="Main">
/// <setting name="Timeout" value="90"/>
/// <setting name="Mode" value="Live"/>
/// </section>
/// </configuration>
/// Example:
/// if (Loki.INI2XML.Convert( txtIniFileName.Text ))
/// System.Console.WriteLine( "Successfully converted \"" + txtIniFileName.Text + "\" to xml" );
/// else
/// System.Console.WriteLine( "Problem converting \"" + txtIniFileName.Text + "\" to xml" );
/// If an exception is raised, it is passed on to the caller.
/// </summary>
/// <param name="strINIFileName">File name of the INI file to convert</param>
/// <returns>True if successfuly, or False if a problem</returns>
public static bool Convert( string strINIFileName )
{
return Convert( strINIFileName, "" );
}
/// <summary>
/// Converts an INI file into an XML file.
/// Output XML file has the following structure...
/// <?xml version="1.0"?>
/// <configuration>
/// <section name="Main">
/// <setting name="Timeout" value="90"/>
/// <setting name="Mode" value="Live"/>
/// </section>
/// </configuration>
/// Example:
/// if (Loki.INI2XML.Convert( txtIniFileName.Text, txtXMLFileName.Text ))
/// System.Console.WriteLine( "Successfully converted \"" + txtIniFileName.Text + "\" to \"" + txtXMLFileName.Text + "\"" );
/// else
/// System.Console.WriteLine( "Problem converting \"" + txtIniFileName.Text + "\" to \"" + txtXMLFileName.Text + "\"" );
/// If an exception is raised, it is passed on to the caller.
/// </summary>
/// <param name="strINIFileName">File name of the INI file to convert</param>
/// <param name="strXMLFileName">File name of the XML file that is created</param>
/// <returns>True if successfuly, or False if a problem</returns>
public static bool Convert( string strINIFileName, string strXMLFileName )
{
char[] charEquals = {'='};
string lpSections;
int nSize;
int nMaxSize;
string strSection;
int intSection;
int intNameValue;
string strName;
string strValue;
string strNameValue;
string lpNameValues;
int intPos;
byte[] str = new byte[1];
System.IO.StreamWriter fileStream;
if ( strXMLFileName.Length == 0 )
{
// set the XML's file name based on the INI file name
intPos = strINIFileName.LastIndexOf( ".ini" );
if ( intPos >= 0 )
{
strXMLFileName = strINIFileName.Substring( 0, intPos ) + ".xml";
}
else
{
strXMLFileName = strINIFileName + ".xml";
}
}
// Get all sections names
// Making sure allocate enough space for data returned
for (nMaxSize = INITIAL_BUFFER_SIZE / 2,
nSize = nMaxSize;
nSize != 0 && nSize >= (nMaxSize-2);
nMaxSize *= 2)
{
str = new byte[nMaxSize];
nSize = WIN32Wrapper.GetPrivateProfileSectionNames( str, nMaxSize, strINIFileName);
}
// convert the byte array into a .NET string
lpSections = System.Text.Encoding.ASCII.GetString( str );
// Create XML File
fileStream = System.IO.File.CreateText( strXMLFileName );
// Write the opening xml
fileStream.WriteLine( "<?xml version=\"1.0\"?><configuration>" );
// Loop through each section
char[] charNull = {'\0'};
for (intSection = 0,
strSection = GetToken(lpSections, charNull, intSection);
strSection.Length > 0;
strSection = GetToken(lpSections, charNull, ++intSection) )
{
// Write a Node for the Section
fileStream.WriteLine( "<section name=\"" + strSection + "\">" );
// Get all values in this section, making sure to allocate enough space
for (nMaxSize = INITIAL_BUFFER_SIZE,
nSize = nMaxSize;
nSize != 0 && nSize >= (nMaxSize-2);
nMaxSize *= 2)
{
str = new Byte[nMaxSize];
nSize = WIN32Wrapper.GetPrivateProfileSection(strSection, str, nMaxSize, strINIFileName);
}
// convert the byte array into a .NET string
lpNameValues = System.Text.Encoding.ASCII.GetString( str );
// Loop through each Name/Value pair
for (intNameValue = 0,
strNameValue = GetToken(lpNameValues, charNull, intNameValue);
strNameValue.Length > 0;
strNameValue = GetToken(lpNameValues, charNull, ++intNameValue) )
{
// Get the name and value from the entire null separated string of name/value pairs
// Also escape out the special characters, (ie. &"<> )
strName = XMLEncode( GetToken( strNameValue, charEquals, 0 ) );
strValue = XMLEncode( strNameValue.Substring( strName.Length + 1 ) );
// Write the XML Name/Value Node to the xml file
fileStream.WriteLine( "<setting name=\"" + strName + "\" value=\"" + strValue + "\"/>");
}
// Close the section node
fileStream.WriteLine( "</section>" );
}
// Thats it
fileStream.WriteLine( "</configuration>" );
fileStream.Close();
return true;
} // Convert
/// <summary>
/// Encodes special characters that XML has problems with, ie.
/// Character Encoded to
/// & &
/// " "
/// < <
/// > > intSection = 0
/// strSection = GetToken(lpSections, charNull, intSection)
/// </summary>
/// <param name="strText">Text that needs encoding</param>
/// <returns>Encoded text</returns>
public static string XMLEncode( string strText)
{
string strTextRet = strText;
strTextRet = strTextRet.Replace( "&", "&" );
strTextRet = strTextRet.Replace( "\"", """);
strTextRet = strTextRet.Replace( "<", "<");
strTextRet = strTextRet.Replace( ">", ">");
return strTextRet;
}
/// <summary>
/// Get a token from a delimited string, eg.
/// intSection = 0
/// strSection = GetToken(lpSections, charNull, intSection)
/// </summary>
/// <param name="strText">Text that is delimited</param>
/// <param name="delimiter">The delimiter, eg. ","</param>
/// <param name="intIndex">The index of the token to return, NB. first token is index 0.</param>
/// <returns>Returns the nth token from a string.</returns>
private static string GetToken( string strText, char[] delimiter, int intIndex )
{
string strTokenRet = "";
string[] strTokens = strText.Split( delimiter );
if ( strTokens.GetUpperBound(0) >= intIndex )
strTokenRet = strTokens[intIndex];
return strTokenRet;
} // GetToken
} // class INI2XML
} // namespace Loki