使用 C# 读取大型 XML 文件
Reading large XML files with C#
我想知道如何从桌面读取 XML 文件并将其放入字符串中?
这是我的 XML:
<smallusers>
<user id="1">
<name>John</name>
<motto>I am john, who are you?</motto>
</user>
<user id="2">
<name>Peter</name>
<motto>Hello everyone!</motto>
</user>
</smallusers>
<bigusers>
<user id="3">
<name>Barry</name>
<motto>Earth is awesome</motto>
</user>
</bigusers>
我想存储每个用户,但仍然检测他们的大小,有没有办法做到这一点?
在你贬低这个之前,你可能想检查一下 google 因为我做了研究,但一无所获。
"Before you downrate this, you might want to check google because I
did research, but found nothing"
您没有找到任何内容,因为您不知道要搜索什么,而且您的 XML 无效,您需要将其括在 rootElement
中。然后,您需要做的第一件事就是从桌面读取此文件(如果存在)。
如果您当时愿意,可以检查尺寸并确定这是否是 "too large",即使这并不重要。我非常怀疑您的 XML 文件大小是否超过 5 GB。如果是,那么您需要一个替代方案,.Net 程序中的单个对象都不能超过 2GB,在 64 位机器上您能做的最好是 1,073,741,823。
对于非常大的 XML 文件,任何超过 1.0 GB 的文件,如 Jon Skeet here:
所述,结合 XmlReader 和 LINQ
If your document is particularly huge, you can combine XmlReader and
LINQ to XML by creating an XElement from an XmlReader for each of your
"outer" elements in a streaming manner: this lets you do most of the
conversion work in LINQ to XML, but still only need a small portion of
the document in memory at any one time.
对于小 XML 文件,任何 1.0 GB 或更小的文件都遵循 DOM,如下所示。
话虽如此,您需要了解 Serialization
和 Deserialization
的含义。
Serialize
将对象实例转换为 XML 文档。
Deserialize
将 XML 文档转换为对象实例。
除了XML你还可以使用JSON、二进制等
在您的情况下,可以将 Deserialize
此 XML
文档返回到对象中,以便您在代码中使用。
首先修复 XML 并给它一个 Root。
<?xml version="1.0" encoding="UTF-8"?>
<DataRoot>
<smallusers>
<user id="1">
<name>John</name>
<motto>I am john, who are you?</motto>
</user>
<user id="2">
<name>Peter</name>
<motto>Hello everyone!</motto>
</user>
</smallusers>
<bigusers>
<user id="3">
<name>Barry</name>
<motto>Earth is awesome</motto>
</user>
</bigusers>
</DataRoot>
然后在 C# 中创建根 class,您可以在 Visual Studio 2012+ 中直接生成它,方法是复制您的 XML 并转到 Edit
- Paste Special
,但我喜欢使用:XML to C# Class Generator
以下是为您的 XML 生成 C# 根 Class 后代码的样子,希望它能帮助您更好地理解它。
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
public class Program
{
[XmlRoot(ElementName = "user")]
public class User
{
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "motto")]
public string Motto { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "smallusers")]
public class Smallusers
{
[XmlElement(ElementName = "user")]
public List<User> User { get; set; }
}
[XmlRoot(ElementName = "bigusers")]
public class Bigusers
{
[XmlElement(ElementName = "user")]
public User User { get; set; }
}
[XmlRoot(ElementName = "DataRoot")]
public class DataRoot
{
[XmlElement(ElementName = "smallusers")]
public Smallusers Smallusers { get; set; }
[XmlElement(ElementName = "bigusers")]
public Bigusers Bigusers { get; set; }
}
static void Main(string[] args)
{
string testXMLData = @"<DataRoot><smallusers><user id=""1""><name>John</name><motto>I am john, who are you?</motto></user><user id=""2""><name>Peter</name><motto>Hello everyone!</motto></user></smallusers><bigusers><user id=""3""><name>Barry</name><motto>Earth is awesome</motto></user></bigusers></DataRoot>";
var fileXmlData = File.ReadAllText(@"C:\XMLFile.xml");
var deserializedObject = DeserializeFromXML(fileXmlData);
var serializedToXML = SerializeToXml(deserializedObject);
//I want to store each user, but still detect if their small or big, is there a way to do this?
foreach (var smallUser in deserializedObject.Smallusers.User)
{
//Iterating your collection of Small users?
//Do what you need here with `smalluser`.
var name = smallUser.Name; //Example...
}
Console.WriteLine(serializedToXML);
Console.ReadKey();
}
public static string SerializeToXml(DataRoot DataObject)
{
var xsSubmit = new XmlSerializer(typeof(DataRoot));
using (var sw = new StringWriter())
{
using (var writer = XmlWriter.Create(sw))
{
xsSubmit.Serialize(writer, DataObject);
var data = sw.ToString();
writer.Flush();
writer.Close();
sw.Flush();
sw.Close();
return data;
}
}
}
public static DataRoot DeserializeFromXML(string xml)
{
var xsExpirations = new XmlSerializer(typeof(DataRoot));
DataRoot rootDataObj = null;
using (TextReader reader = new StringReader(xml))
{
rootDataObj = (DataRoot)xsExpirations.Deserialize(reader);
reader.Close();
}
return rootDataObj;
}
}
}
我想知道如何从桌面读取 XML 文件并将其放入字符串中?
这是我的 XML:
<smallusers>
<user id="1">
<name>John</name>
<motto>I am john, who are you?</motto>
</user>
<user id="2">
<name>Peter</name>
<motto>Hello everyone!</motto>
</user>
</smallusers>
<bigusers>
<user id="3">
<name>Barry</name>
<motto>Earth is awesome</motto>
</user>
</bigusers>
我想存储每个用户,但仍然检测他们的大小,有没有办法做到这一点?
在你贬低这个之前,你可能想检查一下 google 因为我做了研究,但一无所获。
"Before you downrate this, you might want to check google because I did research, but found nothing"
您没有找到任何内容,因为您不知道要搜索什么,而且您的 XML 无效,您需要将其括在 rootElement
中。然后,您需要做的第一件事就是从桌面读取此文件(如果存在)。
如果您当时愿意,可以检查尺寸并确定这是否是 "too large",即使这并不重要。我非常怀疑您的 XML 文件大小是否超过 5 GB。如果是,那么您需要一个替代方案,.Net 程序中的单个对象都不能超过 2GB,在 64 位机器上您能做的最好是 1,073,741,823。
对于非常大的 XML 文件,任何超过 1.0 GB 的文件,如 Jon Skeet here:
所述,结合 XmlReader 和 LINQIf your document is particularly huge, you can combine XmlReader and LINQ to XML by creating an XElement from an XmlReader for each of your "outer" elements in a streaming manner: this lets you do most of the conversion work in LINQ to XML, but still only need a small portion of the document in memory at any one time.
对于小 XML 文件,任何 1.0 GB 或更小的文件都遵循 DOM,如下所示。
话虽如此,您需要了解 Serialization
和 Deserialization
的含义。
Serialize
将对象实例转换为 XML 文档。
Deserialize
将 XML 文档转换为对象实例。
除了XML你还可以使用JSON、二进制等
在您的情况下,可以将 Deserialize
此 XML
文档返回到对象中,以便您在代码中使用。
首先修复 XML 并给它一个 Root。
<?xml version="1.0" encoding="UTF-8"?>
<DataRoot>
<smallusers>
<user id="1">
<name>John</name>
<motto>I am john, who are you?</motto>
</user>
<user id="2">
<name>Peter</name>
<motto>Hello everyone!</motto>
</user>
</smallusers>
<bigusers>
<user id="3">
<name>Barry</name>
<motto>Earth is awesome</motto>
</user>
</bigusers>
</DataRoot>
然后在 C# 中创建根 class,您可以在 Visual Studio 2012+ 中直接生成它,方法是复制您的 XML 并转到 Edit
- Paste Special
,但我喜欢使用:XML to C# Class Generator
以下是为您的 XML 生成 C# 根 Class 后代码的样子,希望它能帮助您更好地理解它。
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace ConsoleApplication1
{
public class Program
{
[XmlRoot(ElementName = "user")]
public class User
{
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "motto")]
public string Motto { get; set; }
[XmlAttribute(AttributeName = "id")]
public string Id { get; set; }
}
[XmlRoot(ElementName = "smallusers")]
public class Smallusers
{
[XmlElement(ElementName = "user")]
public List<User> User { get; set; }
}
[XmlRoot(ElementName = "bigusers")]
public class Bigusers
{
[XmlElement(ElementName = "user")]
public User User { get; set; }
}
[XmlRoot(ElementName = "DataRoot")]
public class DataRoot
{
[XmlElement(ElementName = "smallusers")]
public Smallusers Smallusers { get; set; }
[XmlElement(ElementName = "bigusers")]
public Bigusers Bigusers { get; set; }
}
static void Main(string[] args)
{
string testXMLData = @"<DataRoot><smallusers><user id=""1""><name>John</name><motto>I am john, who are you?</motto></user><user id=""2""><name>Peter</name><motto>Hello everyone!</motto></user></smallusers><bigusers><user id=""3""><name>Barry</name><motto>Earth is awesome</motto></user></bigusers></DataRoot>";
var fileXmlData = File.ReadAllText(@"C:\XMLFile.xml");
var deserializedObject = DeserializeFromXML(fileXmlData);
var serializedToXML = SerializeToXml(deserializedObject);
//I want to store each user, but still detect if their small or big, is there a way to do this?
foreach (var smallUser in deserializedObject.Smallusers.User)
{
//Iterating your collection of Small users?
//Do what you need here with `smalluser`.
var name = smallUser.Name; //Example...
}
Console.WriteLine(serializedToXML);
Console.ReadKey();
}
public static string SerializeToXml(DataRoot DataObject)
{
var xsSubmit = new XmlSerializer(typeof(DataRoot));
using (var sw = new StringWriter())
{
using (var writer = XmlWriter.Create(sw))
{
xsSubmit.Serialize(writer, DataObject);
var data = sw.ToString();
writer.Flush();
writer.Close();
sw.Flush();
sw.Close();
return data;
}
}
}
public static DataRoot DeserializeFromXML(string xml)
{
var xsExpirations = new XmlSerializer(typeof(DataRoot));
DataRoot rootDataObj = null;
using (TextReader reader = new StringReader(xml))
{
rootDataObj = (DataRoot)xsExpirations.Deserialize(reader);
reader.Close();
}
return rootDataObj;
}
}
}