1

我想在不使用 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);

我已经看到不可能将 a 添加byte[]到 RichTextBox。

我的问题是:

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

  • 难道没有更好的方法不必为了将文本附加到 RichTextBox 而创建一个字符串对象吗?

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

4

3 回答 3

2

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

是的。

难道没有更好的方法不必为了将文本附加到 RichTextBox 而创建字符串对象吗?

不,AppendText 需要一个字符串

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

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

不幸的是,这里有相互矛盾的目标。您不希望缓冲区大于 39,999 字节,否则字符串最终会出现在大对象堆中并阻塞它,直到发生第 2 代垃圾回收。但是如果你大大超过这个大小,RTB 会更快乐,如果文件太大以至于你需要一个进度条,那么 RTB 会更快乐。

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

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

于 2013-02-08T08:20:31.917 回答
1

尝试这个:

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

或者

richTextBox.AppendText(File.ReadAllText("file.txt", Encoding.ASCII));
于 2013-02-07T18:50:09.627 回答
0

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

于 2013-02-08T07:48:31.447 回答