2011-04-15 54 views
3

我正在从web服务接收数据流并尝试将流的内容保存到文件。该流包含大量xml数据(在一行中)的标准文本行。该文件的大小约为800Mb。c#如何读取正常和xml文本元素的单个文件

问题:当我处理每行的xml部分时,收到内存不足异常。

==start file 
line 1 
line 2 
<?xml version=.....huge line etc</xml> 
line 3 
line4 
<?xml version=.....huge line etc</xml> 
==end file 

当前的代码,你可以看到当它读入巨大的xml行时,它会触发内存。

string readLine; 
using (StreamReader reader = new StreamReader(downloadStream)) 
{ 
    while ((readLine = reader.ReadLine()) != null) 
    { 
     streamWriter.WriteLien(readLine); //writes to file 
    } 
} 

我试图想在哪里使用两者的TextReader /的StreamReader和XmlTextReader的组合来处理每个部分的溶液。当我到达xml部分时,我可以切换到XmlTextReader并使用Read()方法来读取每个节点,从而停止内存峰值。

关于如何做到这一点的任何建议?或者,我可以创建一个能够读取这些行的自定义XmlTextReader?任何指针?

更新

另一个问题是这是我需要阅读这个文件拿过来,打出了两个XML部分分离的xml文件!我将解决方案转换为使用二进制写入器写入文件,然后开始使用二进制读取器重新读取文件。我有文本处理来检测XML部分的开始,特别是哪个XML部分,以便我可以将其映射到正确的文件!然而这会导致问题读二进制文件和做检测...

using (BinaryReader reader = new BinaryReader(savedFileStream)) 
{ 
    while ((streamLine = reader.ReadString()) != null) 
    { 
     if (streamLine.StartsWith("<?xml version=\"1.0\" ?><tag1")) 
     //xml file 1 
     else if (streamLine.StartsWith("<?xml version=\"1.0\" ?><tag2")) 
     //xml file 2 

回答

1

如果您只想将一个流复制到另一个流而不修改数据,则不需要Stream文本或二元助手(StreamReader,StreamWriter,BinaryReader,BinaryWriter等),只需复制流。

internal static class StreamExtensions 
{ 
    public static void CopyTo(this Stream readStream, Stream writeStream) 
    { 
     byte[] buffer = new byte[4096]; 
     int read; 
     while ((read = readStream.Read(buffer, 0, buffer.Length)) > 0) 
      writeStream.Write(buffer, 0, read); 
    } 
} 
2

XML可能包含的所有内容作为一个单行,所以你可能会更好使用二进制读/写器,你可以决定有关读/写大小。

下面一个例子,我们在这里阅读BUFFER_SIZE字节每次迭代:

 Stream s = new MemoryStream(); 
     Stream outputStream = new MemoryStream(); 
     int BUFFER_SIZE = 1024; 
     using (BinaryReader reader = new BinaryReader(s)) 
     { 
      BinaryWriter writer = new BinaryWriter(outputStream); 
      byte[] buffer = new byte[BUFFER_SIZE]; 
      int read = buffer.Length; 
      while(read != 0) 
      { 
       read = reader.Read(buffer, 0, BUFFER_SIZE); 

       writer.Write(buffer, 0, read); 

      } 

      writer.Flush(); 
      writer.Close(); 
     } 

我不知道这是否会导致你的问题编码等,但我认为你将不得不读取该文件为二进制。

+0

我会这样的事情,因为这意味着你保持你消耗的内存量已知最大值。 – 2011-04-15 14:51:15

+0

我遇到的唯一问题是它需要以人们可读的格式 - 要求!我必须重新读取此文件才能进行更多处理! – David 2011-04-15 14:53:57

+0

格式不会改变,因此它将与输入文件一样可以被人类阅读。 – faester 2011-04-15 15:06:32

0

我觉得这是一个内存泄漏

您是否收到了内存溢出异常处理的几行后或在第一行本身?
while循环中没有streamWriter.Flush()。
你不觉得应该有一个?

+0

你能解决它吗?如果是,请分享。 – 2011-04-21 01:12:24