2010-12-11 185 views
1

我正在使用iTextSharp,并需要生成数十万个RTF文档 - 生成的文件在5KB到500KB之间。有没有办法让这个更快? MemoryStream vs FileStream

我在下面列出2种方法 - 原始方法不一定慢,但我想明白为什么要写/从/从文件获取我需要的输出字符串。我看到了另一种使用MemoryStream的方法,但它实际上减慢了速度。我基本上只需要输出的RTF内容,以便我可以在该RTF上运行一些过滤器来清理不必要的格式。带回数据的查询非常迅速。要使用原始方法文件生成1000个文件(实际上是创建2000个文件)需要大约15分钟,与第二种方法相同需要大约25-30分钟。我运行的结果文件平均大约80KB。

第二种方法有什么问题吗?似乎它应该比第一个更快,而不是更慢。

原始的方法:

RtfWriter2.GetInstance(doc, new FileStream(RTFFilePathName, FileMode.Create)); 
doc.Open(); 

    //Add Tables and stuff here 

doc.Close(); //It saves a file here to (RTFPathFileName) 

StreamReader srRTF = new StreamReader(RTFFilePathName); 
string rtfText = srRTF.ReadToEnd(); 
srRTF.Close(); 

    //Do additional things with rtfText before writing to my final file 

的新方法,努力加快速度,但其实这是一半快:

MemoryStream stream = new MemoryStream(); 
    RtfWriter2.GetInstance(doc, stream); 
    doc.Open(); 

    //Add Tables and stuff here 

    doc.Close(); 

    string rtfText = 
    ASCIIEncoding.ASCII.GetString(stream.GetBuffer()); 
    stream.Close(); 


     //Do additional things with rtfText before writing to my final file 

我想我发现这里的第二种方法: iTextSharp - How to generate a RTF document in the ClipBoard instead of a file

+0

你正在处理的文件有多大?如果它不是很大,那么不会有太大的区别。如果它很大,那么你可能不想在内存中处理它,如果它太多降级你的系统。 – phillip 2010-12-11 22:52:07

+0

你好,感谢你的回复。我需要输出约400,000个文件 - 介于5KB和500KB之间。我正在使用iTextSharp从SQL查询生成RTF内容。 – user53885 2010-12-11 22:53:59

+0

重新使用MemoryStream。即分配一次,并将其用于清除其中的内容的所有文件。 – CodesInChaos 2010-12-12 10:08:01

回答

3

您的结果流有多大? MemoryStream在增长时执行大量内存复制操作,因此对于较大的结果,与FileStream相比,通过小块写入数据可能花费更长的时间。

若要验证是否将MemoryStream的初始大小设置为产生的大小周围的某个较大值并重新运行代码。

要修复它,您可以在最初(如果您知道近似输出的话)预先增大内存流量,或者编写自己的数据流,以便在增长时使用不同的方案。同样使用临时文件可能足以满足您的目的。

0

就像Alexei说的那样,它可能是由事实造成的,你每次都在创建MemoryStream,并且每次它随着它的增长不断地重新分配内存。尝试只创建一个流并将其重置为在每次写入之前开始。

此外,我认为stream.GetBuffer()再次返回新的内存,所以尝试使用相同的StreamReader与您的MemoryStream。

而且看起来你的代码很容易被平行化,所以你可以尝试使用Paralel Extesions或者使用TreadPool来运行它。

它似乎有点奇怪,你正在写你的文本作为流中的字节,然后读取这个流作为字节和转换为文本。不可能将文档直接保存为文本?

0

MemoryStream不与文件关联,并且没有文件名的概念。基本上,你不能那样做。

你当然不能在它们之间施放;你只能向下投下 - 不能侧身投射。可视化:

Stream 
     | 

| | FileStream MemoryStream 您可以通过类型检查将MemoryStream简单地转换为Stream,并将Stream转换为MemoryStream;但从来没有一个FileStream到一个MemoryStream。这就像说狗是动物,而大象是动物,所以我们可以把狗给大象。

您可以继承MemoryStream并添加一个Name属性(即您提供的值),但FileStream和YourCustomMemoryStream之间仍然没有共同性,并且FileStream不实现预先存在的接口以获取名称;所以调用者必须分别明确地处理两者,或者使用鸭式输入(可能通过动态或反射)。

另一种选择(可能更简单)可能是:将数据写入临时文件;从那里使用FileStream;然后(稍后)删除该文件。

相关问题