C#读写XML文件方式多多,最简单的就是查找节点并读写节点的属性或值,而查找节点是特别繁琐的工作。事实上C#提供了xml序列化的技术,利用xml序列化可以方便的读写xml配置文件,先举个列子。
xml文件:
<?xml version="1.0" encoding="utf-8"?>
<SFtpServerConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Server Port="8022" AuthType="3">
<Certificate PublicKeyFile="SftpServer.pfx" Subject="CN=SftpServer" Password="AB699B97AB9610300745554524364199201C0C92BF36EA2A5FC5BE371F41AD93F0C0E32C902283829CF4A9C3657E752BCD1C3B7A9D9C5DAD24C469C0BEFF0C0593C4C07CCCFB12717FD5A88364E93FB478FC8B660E2CEE6D1F67D4B1DC29EB3E2B93AF840544148F2F23FB940644C6CDA5A5B22DDA50F25FB4A86E63A08637FE2F3D97367FD661C12D0A42F6D78A13C187F445249A543D9FD6CE933380E717723A46D678811445A234D0121838A8917C7315CB11132B5CFD31C15B15333F0A53D376AA6FFC2EDC1542B674B6CB53D618427FDCD235F5DB6AFDD2BE29C27F3CEE74C46D97E70D4228A998F01A1F91BC219EA59E5C9EB8DE17E7E60DC9423CCCB5" />
</Server>
<Clients Type="1">
<Certificate PublicKeyFile="SftpClient.pfx" Subject="CN=SftpClient" Password="AB699B97AB9610300745554524364199201C0C92BF36EA2A5FC5BE371F41AD93F0C0E32C902283829CF4A9C3657E752BCD1C3B7A9D9C5DAD24C469C0BEFF0C0593C4C07CCCFB12717FD5A88364E93FB478FC8B660E2CEE6D1F67D4B1DC29EB3E2B93AF840544148F2F23FB940644C6CDA5A5B22DDA50F25FB4A86E63A08637FE2F3D97367FD661C12D0A42F6D78A13C187F445249A543D9FD6CE933380E717723A46D678811445A234D0121838A8917C7315CB11132B5CFD31C15B15333F0A53D376AA6FFC2EDC1542B674B6CB53D618427FDCD235F5DB6AFDD2BE29C27F3CEE74C46D97E70D4228A998F01A1F91BC219EA59E5C9EB8DE17E7E60DC9423CCCB5" />
<Clients>
<ClientConfig Address="192.168.4.107">
<Certificate PublicKeyFile="192.168.4.107.pfx" Subject="CN=192.168.4.107" Password="AB699B97AB9610300745554524364199201C0C92BF36EA2A5FC5BE371F41AD93F0C0E32C902283829CF4A9C3657E752BCD1C3B7A9D9C5DAD24C469C0BEFF0C0593C4C07CCCFB12717FD5A88364E93FB478FC8B660E2CEE6D1F67D4B1DC29EB3E2B93AF840544148F2F23FB940644C6CDA5A5B22DDA50F25FB4A86E63A08637FE2F3D97367FD661C12D0A42F6D78A13C187F445249A543D9FD6CE933380E717723A46D678811445A234D0121838A8917C7315CB11132B5CFD31C15B15333F0A53D376AA6FFC2EDC1542B674B6CB53D618427FDCD235F5DB6AFDD2BE29C27F3CEE74C46D97E70D4228A998F01A1F91BC219EA59E5C9EB8DE17E7E60DC9423CCCB5" />
</ClientConfig>
</Clients>
</Clients>
</SFtpServerConfig>
C#代码:
/// <summary>
/// 工具类,实现配置对象的序列化与反序列化,配置对象是泛化的
/// </summary>
public class XmlConfigUtil
{
public static bool SerializeConfigObject<T>(T objConfig, string configFile, ref string strError)
{
strError = string.Empty;
if (objConfig == null)
{
strError = string.Format("Config object is null");
return false;
}
try
{
XmlTextWriter xmlWriter = new XmlTextWriter(configFile, Encoding.UTF8); //UTF-8 编码
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.Indentation = 4; //设置xml文档格式,有4位缩进
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
xmlSerializer.Serialize(xmlWriter, objConfig);
xmlWriter.Flush();
xmlWriter.Close();
return true;
}
catch (Exception ex)
{
strError = ex.Message;
return false;
}
}
public static bool DeserializeConfigObject<T>(ref T objConfig, string configFile, ref string strError)
{
objConfig = default(T);
strError = string.Empty;
if (!System.IO.File.Exists(configFile))
{
strError = string.Format("Config file not exist.\t{0}", configFile);
return false;
}
try
{
Stream fileStream = new FileStream(configFile, FileMode.Open, FileAccess.Read);
XmlReader xmlReader = new XmlTextReader(fileStream);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
objConfig = (T)xmlSerializer.Deserialize(xmlReader);
xmlReader.Close();
return true;
}
catch (Exception ex)
{
strError = ex.Message;
return false;
}
}
}
/// <summary>
/// SftpServer 配置信息
/// </summary>
[XmlRoot]
public class SFtpServerConfig
{
[XmlElement]
public ServerConfig Server { get; set; }
[XmlElement]
public ClientsConfig Clients { get; set; }
}
/// <summary>
/// Server 端配置信息
/// </summary>
[XmlRoot]
public class ServerConfig
{
/// <summary>
/// Sftp监听端口,Sftp通常是22,VCLogSftp默认8022
/// </summary>
[XmlAttribute]
public int Port { get; set; }
/// <summary>
/// 认证方式
/// 1 密码认证
/// 2 公钥认证
/// 3 密码+公钥认证
/// </summary>
[XmlAttribute]
public int AuthType { get; set; }
/// <summary>
/// 服务器证书信息,必须,客户端可以不验证服务器证书,但服务器必须提供
/// </summary>
[XmlElement]
public CertificateConfig Certificate { get; set; }
}
/// <summary>
/// Client 配置信息
/// </summary>
[XmlRoot]
public class ClientsConfig
{
/// <summary>
/// 客户端证书分发方式
/// 0 共享同一证书
/// 1 各个客户端使用各自证书
/// 仅公钥认证和密码+公钥认证模式下有效
/// </summary>
[XmlAttribute]
public int Type { get; set; }
/// <summary>
/// 客户端共享的证书
/// 仅客户端证书分发方式为0时才有效
/// </summary>
[XmlElement]
public CertificateConfig Certificate { get; set; }
/// <summary>
/// 客户端列表
/// </summary>
[XmlArray, XmlArrayItem("ClientConfig")]
public ClientConfig[] Clients { get; set; }
}
/// <summary>
/// Client 端配置信息
/// 仅客户端证书分发方式为1才有效
/// </summary>
[XmlRoot]
public class ClientConfig
{
/// <summary>
/// 客户端地址
/// </summary>
[XmlAttribute]
public string Address { get; set; }
/// <summary>
/// 客户端证书
/// </summary>
[XmlElement]
public CertificateConfig Certificate { get; set; }
}
/// <summary>
/// 证书配置信息
/// </summary>
[XmlRoot]
public class CertificateConfig
{
/// <summary>
/// 证书文件的文件名
/// </summary>
[XmlAttribute]
public string PublicKeyFile { get; set; }
/// <summary>
/// 证书主题
/// </summary>
[XmlAttribute]
public string Subject { get; set; }
/// <summary>
/// 证书文件的密码
/// </summary>
[XmlAttribute]
public string Password { get; set; }
public override string ToString()
{
return Subject;
}
}
利用xml序列化技术读写xml配置文件,首先需要定义一个与xml文档对应的配置类,一般情况下类的基本数据类型成员定义为类节点的属性,如整形和字符串型,自定义的的类型可以作为子节点,而对于集合类型则定义为数组类型并指定数组成员的类型。
类和成员都应该加上xml特性(XmlRoot、XmlAttribute、XmlElement)
然后调用xml序列化和反序列化实现xml文档的读写
C#代码:
string error = string.Empty;
if (!XmlConfigUtil.DeserializeConfigObject<SFtpServerConfig>(ref mSFtpServerConfig, configPath, ref error))
{
SubDebug("ServerConfig", string.Format("Get Sftp server config fail.\t{0}", error));
return false;
}