在不使用LoadFile的情况下将文件读入RichTextBox

时间:2013-02-07 18:47:16

标签: c#

我想在不使用LoadFile的情况下将文件读入RichTextBox(我可能想要显示进度)。该文件仅包含ASCII字符。

我正在考虑以块的形式阅读文件。

我做了以下(工作正常):

const int READ_BUFFER_SIZE = 4 * 1024;

BinaryReader reader = new BinaryReader(File.Open("file.txt", FileMode.Open));

byte[] buf = new byte[READ_BUFFER_SIZE];
do {
    int ret = reader.Read(buf, 0, READ_BUFFER_SIZE);
    if (ret <= 0) {
        break;
    }

    string text = Encoding.ASCII.GetString(buf);
    richTextBox.AppendText(text);
} while (true);

我担心的是:

string text = Encoding.ASCII.GetString(buf);

我看到无法向RichTextBox添加byte[]

我的问题是:

  • 是否会为每个读取的块分配一个新的字符串对象?

  • 是否有更好的方法不必创建字符串对象只是为了将文本附加到RichTextBox?

  • 或者,从文件中读取行是否更有效(StreamReader.ReadLine)并且只返回RichTextBox返回的字符串?

3 个答案:

答案 0 :(得分:2)

  

是否会为每个读取的块分配一个新的字符串对象?

  

是否有更好的方法不必创建字符串对象只是为了将文本附加到RichTextBox?

不,AppendText需要一个字符串

  

或者,从文件中读取行是否更有效(StreamReader.ReadLine)并且只返回RichTextBox返回的字符串?

不,这相当效率低下。您现在将更频繁地创建一个新的字符串对象。从垃圾收集堆的角度来看哪个没问题,你不会创造更多的垃圾。但它绝对是RichTextBox上的谋杀案,它不断需要重新分配自己的缓冲区。其中包括移动之前阅读的所有文本。你拥有的已经很好,你应该使用更大的READ_BUFFER_SIZE。

不幸的是,这里有相互矛盾的目标。您不希望使缓冲区大于39,999字节或字符串最终在大对象堆中并阻塞它直到发生第2代垃圾收集。但是如果你大大超过这个规模,RTB将会更加快乐,如果文件太大而你需要一个进度条,那就像一兆字节。

如果你想让它真正有效,那么你需要替换RichTextBox.LoadFile()。底层的Windows消息是EM_STREAMIN,它使用回调机制在文本中流式传输。您可以在技术上替换回调以执行RichTextBox中的默认回调, plus 更新进度条。它确实允许摆脱字符串btw。 pinvoke非常不友好,使用参考源作为指导。

首先采用简单路线,增加缓冲区大小。当你的代码比使用File.ReadAllText()慢得多时,只考虑使用pinvoke路由。

答案 1 :(得分:1)

试试这个:

richTextBox.AppendText(File.ReadAllText("file.txt"));

richTextBox.AppendText(File.ReadAllText("file.txt", Encoding.ASCII));

答案 2 :(得分:0)

您可以使用StreamReader。然后,您可以阅读文件的每一行并在阅读时显示进度。