- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试从巨大的JSON文件(2GB)转换为xml文件。我在读取巨大的JSON文件时遇到了一些麻烦。
我一直在研究如何读取巨大的JSON文件。
我找到了这个:
Out of memory exception while loading large json file from disk
How to parse huge JSON file as stream in Json.NET?
Parsing large json file in .NET
看来我在重复我的问题,但我遇到了一些麻烦,这些问题并没有解决。
因此,我需要加载巨大的JSON文件,社区提出了如下建议:
MyObject o;
using (StreamReader sr = new StreamReader("foo.json"))
using (JsonTextReader reader = new JsonTextReader(sr))
{
var serializer = new JsonSerializer();
reader.SupportMultipleContent = true;
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
// Deserialize each object from the stream individually and process it
var o = serializer.Deserialize<MyObject>(reader);
//Do something with the object
}
}
}
JsonSerializer serializer = new JsonSerializer();
string hugeJson = "hugJSON.json";
using (FileStream s = File.Open(hugeJson , FileMode.Open))
{
using (StreamReader sr = new StreamReader(s))
{
using (JsonReader reader = new JsonTextReader(sr))
{
reader.SupportMultipleContent = true;
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
var jsonObject = serializer.Deserialize(reader);
string xmlString = "";
XmlDocument doc = JsonConvert.DeserializeXmlNode(jsonObject.ToString(), "json");
using (var stringWriter = new StringWriter())
{
using (var xmlTextWriter = XmlWriter.Create(stringWriter))
{
doc.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
xmlString = stringWriter.GetStringBuilder().ToString();
}
}
}
}
}
}
}
doc.WriteTo(xmlTextWriter)
时,我得到
Exception of type System.OutOfMemoryException was thrown.
BufferedStream
。此类允许我管理大文件,但我还有另一个问题。
byte[]
格式。当我转换为字符串时,json被拆分,由于缺少字符,我无法解析为xml文件
{ foo:[{
foo:something,
foo1:something,
foo2:something
},
{
foo:something,
foo:som
static void Main(string[] args)
{
string json = "";
string pathJson = "foo.json";
//Read file
string temp = "";
using (FileStream fs = new FileStream(pathJson, FileMode.Open))
{
using (BufferedStream bf = new BufferedStream(fs))
{
byte[] array = new byte[70000];
while (bf.Read(array, 0, 70000) != 0)
{
json = Encoding.UTF8.GetString(array);
temp = String.Concat(temp, json);
}
}
}
XmlDocument doc = new XmlDocument();
doc = JsonConvert.DeserializeXmlNode(temp, "json");
using (var stringWriter = new StringWriter())
using (var xmlTextWriter = XmlWriter.Create(stringWriter))
{
doc.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
xmlString = stringWriter.GetStringBuilder().ToString();
}
File.WriteAllText("outputPath", xmlString);
}
[{
'key':[some things],
'data': [some things],
'data1':[A LOT OF ENTRIES],
'data2':[A LOT OF ENTRIES],
'data3':[some things],
'data4':[some things]
}]
最佳答案
.Net中的内存不足异常可能是由以下几个问题引起的:
分配了太多的总内存。
如果可能发生这种情况,请按照here所述检查是否以64位模式运行。如果不是,请按照here所述以64位模式重建并重新测试。
在large object heap上分配过多的对象导致内存碎片。
分配大于.Net object size limit的单个对象。
无法处理非托管内存(此处不适用)。
在您的情况下,您可能试图分配过多的总内存,但肯定要分配三个非常大的对象:内存temp
JSON字符串,内存xmlString
XML字符串和内存stringWriter
。
您可以直接通过JSON文件中的流转换构造一个XDocument
或XmlDocument
,从而大大减少内存占用并完全消除这些对象。然后,使用XDocument.Save()
或XmlDocument.Save()
将文档直接写入XML文件。
为此,您需要分配自己的XmlNodeConverter
,然后使用它构造一个JsonSerializer
并按Deserialize JSON from a file所示进行反序列化。以下方法可以解决问题:
public static partial class JsonExtensions
{
public static XDocument LoadXNode(string pathJson, string deserializeRootElementName)
{
using (var stream = File.OpenRead(pathJson))
return LoadXNode(stream, deserializeRootElementName);
}
public static XDocument LoadXNode(Stream stream, string deserializeRootElementName)
{
// Let caller dispose the underlying streams.
using (var textReader = new StreamReader(stream, Encoding.UTF8, true, 1024, true))
return LoadXNode(textReader, deserializeRootElementName);
}
public static XDocument LoadXNode(TextReader textReader, string deserializeRootElementName)
{
var settings = new JsonSerializerSettings
{
Converters = { new XmlNodeConverter { DeserializeRootElementName = deserializeRootElementName } },
};
using (var jsonReader = new JsonTextReader(textReader) { CloseInput = false })
return JsonSerializer.CreateDefault(settings).Deserialize<XDocument>(jsonReader);
}
public static void StreamJsonToXml(string pathJson, string pathXml, string deserializeRootElementName, SaveOptions saveOptions = SaveOptions.None)
{
var doc = LoadXNode(pathJson, deserializeRootElementName);
doc.Save(pathXml, saveOptions);
}
}
JsonExtensions.StreamJsonToXml(pathJson, outputPath, "json");
XDocument
而不是
XmlDocument
,因为我相信(但没有亲自检查)它使用的内存更少,例如如Ken Lassesen在
Some hard numbers about XmlDocument, XDocument and XmlReader (x86 versus x64)中的报道。
XDocument
或
XmlDocument
的计算机的虚拟内存空间。如果是这样,您将需要采用一种纯流传输解决方案,该解决方案可以在流传输时从JSON即时转换为XML。不幸的是,Json.NET并未立即提供此功能,因此您将需要一个更复杂的解决方案。
XmlNodeConverter.cs
并重写
ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
以直接写入
XmlWriter
而不是
IXmlDocument
。
JsonReaderWriterFactory
返回的阅读器将JSON即时转换为XML,然后将该阅读器直接传递给
XmlWriter.WriteNode(XmlReader)
。
DataContractJsonSerializer
在内部使用此工厂返回的读者和作家,但也可以直接使用。
XDocument
)时要少得多。
using (var stream = File.OpenRead(pathJson))
using (var jsonReader = JsonReaderWriterFactory.CreateJsonReader(stream, XmlDictionaryReaderQuotas.Max))
{
using (var xmlWriter = XmlWriter.Create(outputPath))
{
xmlWriter.WriteNode(jsonReader, true);
}
}
XmlNodeConverter
生成的XML要漂亮得多。例如,给定简单的输入JSON
{"Root":[{
"key":["a"],
"data": [1, 2]
}]}
XmlNodeConverter
将创建以下XML:
<json>
<Root>
<key>a</key>
<data>1</data>
<data>2</data>
</Root>
</json>
JsonReaderWriterFactory
将创建以下内容(为清楚起见,以缩进形式表示):
<root type="object">
<Root type="array">
<item type="object">
<key type="array">
<item type="string">a</item>
</key>
<data type="array">
<item type="number">1</item>
<item type="number">2</item>
</data>
</item>
</Root>
</root>
JsonReaderWriterFactory.CreateJsonWriter().WriteNode(xmlReader, true);
type="object"
或
type="array"
属性避免了该问题。
关于c# - 如何在C#中将巨大的JSON文件转换为xml文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56260418/
我是一名优秀的程序员,十分优秀!