将大型Json解析为XML(系统内存不足异常)

将大型Json解析为XML(系统内存不足异常),xml,json,vb.net,Xml,Json,Vb.net,JSON文件(非常大)和脚本如下所示 剧本 JSON文件 [{“ID”:“001”,“姓名”:“Den.Y”,“性别”:“M”,年龄:“18”}] 我想将其转换为XML,然后传递到SQL server。但是我发现JSON太大,然后抛出了一个“系统内存不足异常” Dim doc As XmlDocument = CType(JsonConvert.DeserializeXmlNode("{""root"":" + JsonContents + "}", "root"), XmlDocume

JSON文件(非常大)和脚本如下所示

剧本 JSON文件 [{“ID”:“001”,“姓名”:“Den.Y”,“性别”:“M”,年龄:“18”}]


我想将其转换为XML,然后传递到SQL server。但是我发现JSON太大,然后抛出了一个“系统内存不足异常”

 Dim doc As XmlDocument =
 CType(JsonConvert.DeserializeXmlNode("{""root"":" + JsonContents +
 "}", "root"), XmlDocument)
我不知道如何修改脚本,以便在不耗尽内存的情况下转换大型JSON文件,但是小尺寸JSON在这个脚本上工作得很好

我在网上搜索,有些人建议使用XMLReader,但我不知道如何处理它

[解决方案]
谢谢大家的努力。最后,我将这个大JSON文件剪切下来,以防止脚本内存不足。现在它可以很好地处理大型JSON

首先,了解CLR如何处理内存非常重要。CLR使用分代垃圾收集器,在该收集器中,内存在每次收集后都会移动到更高阶的一代。此外,还有一种特殊的生成,称为“大对象堆”(LOH),用于特定大小和更大的对象。您的JSON字符串几乎肯定会在这里结束。重要的是要知道,LOH很少被收集;更糟糕的是,它几乎从未被压实过。这意味着,即使对象已被收集并从内存中删除,进程中为该对象保留的虚拟地址空间仍在使用。。。请记住,默认情况下,您的进程只有2GB的地址空间

另外,我们可以在代码中看到可能导致问题的东西如果(而且“如果”很重要)您正在进行直接的字符串连接,此摘录将最终创建三个复制字符串的对象:

"{""root"":" + JsonContents + "}"
“{”“root”“:“+JsonContents
部分将有一个副本,后面的
+“}”部分将有第二个新副本。谢天谢地,编译器通常会将其重新写入更高效的内容中,最终只会得到一个额外的副本。在这里,让我们不要忘记将这些字节从旧字符串移动到新字符串的所有CPU工作

不过,一到两份额外的拷贝通常不是什么大问题。我通常看到人们在处理使用加倍算法的文档时会遇到麻烦,在这种算法中,每次缓冲区填满时,它都会读取数据流并分配一个新的缓冲区,其大小是旧缓冲区的两倍。Net中的大多数集合类型都是这样工作的。我不熟悉
JSONConvert
类型的内部结构,但是
反序列化xmlnode()
方法可能是这样工作的。如果是这样,您需要找到另一种方法来创建xml文档

不过,我们不必看得太远,就可以找到一个反复创建新字符串对象的过程。看一看

此方法打开一个文件,读取文件的每一行,然后将每一行添加为字符串的元素

哦。这听起来像是一次又一次地将行连接到字符串。如果这确实是导致错误的原因,我希望
File.ReadAllText()
调用在进程中断的地方。但是,可能是我在开头展示的字符串连接创建的额外副本,加上用于
反序列化xmlnode()
调用和
CType()
cast结果的任何内存-请记住:如果CType()实际在做任何工作,那么它们将是两个独立的(大的)物体——是折断骆驼背的稻草

您知道文件将有多大,因此我们可以通过从StreamReader读取并将每一行写入使用创建的
StringBuilder
对象来做得更好。这样,所有中间步骤都足够小,可以避免大对象堆。但我怀疑这还不够,您需要找到一种替代
JSONConvert
类型的方法来创建
XmlDocument
对象


当然,JSON文件可能就是这么大。在这种情况下,您可能需要将其拆分为多个调用,并将其放入数据库中,然后一次从文件中读取一个节。即使在64位系统上,.Net中的单个内存对象也不允许超过2GB(进程可能会变大,但单个对象不能)。

JsonConvert.DeserializeXmlNode
返回XmlDocument时,为什么会有
CType
的可能重复?我希望移除它不会有帮助,但值得一试。另外,您是否可以选择运行为x64而不是x86编译的程序?@ElektroStudios:我试图删除不必要的语句,但问题仍然存在。@AndrewMorton:我删除了CType,问题仍然存在。@在此状态引发System.OutOfMemoryException::Dim JsonXMLDoc作为XmlDocument=JsonConvert.DeserializeXmlNode(“{root:+JsonContents+“}”,“root”)****如果我的JSON文件为55MB,则必须引发System.OutOfMemoryException。如果是33MB,“System.OutOfMemoryException”是幸运的。如果小于5MB,则始终工作正常。请欣赏详细说明!我打破陈述,一步一步地进行。我发现
File.ReadAllText()
工作正常,并成功读取了所有文本,但我发现
System.OutOfMemoryException
是由
JsonConvert.DeserializeXmlNode()
引发的。由于我的JSON文件只有55MB,我不知道为什么它会达到2GB虚拟内存限制,导致它抛出
System.OutOfMemoryException
。还有一件事,由于错误来自
JsonConvert.DeserializeXmlNode()
,我想知道有没有建议在VB.NET中将大型JSON转换为XML?仅仅因为File.ReadAllText()完成时没有抛出错误,并不意味着它没有仔细检查大多数虚拟地址
"{""root"":" + JsonContents + "}"