我想在不使用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返回的字符串?
答案 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。然后,您可以阅读文件的每一行并在阅读时显示进度。