在不使用LoadFile的情况下将文件读取到RichTextBox中

本文关键字:读取 文件 RichTextBox 情况下 LoadFile | 更新日期: 2023-09-27 17:58:26

我想在不使用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中更有效吗?

在不使用LoadFile的情况下将文件读取到RichTextBox中

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

是的。

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

否,AppendText需要字符串

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

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

不幸的是,这里有相互冲突的目标。您不希望使缓冲区大于39999字节,或者字符串最终进入大型对象堆并阻塞它,直到发生第2代垃圾收集。但是,如果你大大超过这个大小,RTB会更快乐,比如如果文件太大,你需要一个进度条,那么就需要一个兆字节。

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

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

试试这个:

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

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

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