C# 将文本数据加载到 WPF 控件中

本文关键字:WPF 控件 加载 文本 数据 | 更新日期: 2023-09-27 18:34:44

我正在寻找一种非常快速的方法,将文本内容从 1GB 的文本文件加载到 WPF 控件中(例如ListView(。我想在 2 秒内加载内容。

逐行读取内容需要很长时间,因此我认为将其作为字节读取会更快。到目前为止,我有:

byte[] buffer = new byte[4096];
int bytesRead = 0;
using(FileStream fs = new FileStream("myfile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
    while((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0) {
        Encoding.Unicode.GetString(buffer);
    }
}

有没有办法将字节转换为字符串行并将其添加到列表视图/列表框中?

这是将文件内容加载到 WPF GUI 控件中的最快方法吗?有各种应用程序可以在 1 秒内从 1GB 文件加载文件内容。

编辑:使用多个线程读取文件会有所帮助吗?例如:

var t1 = Task.Factory.StartNew(() =>
{
    //read content/load into GUI...
});

编辑2:我打算按照下面的建议使用分页/分页,但是当我想向下或向上滚动时,必须再次读取文件内容才能到达正在显示的位置。 所以我想使用:

fs.Seek(bytePosition, SeekOrigin.Begin);

但这会比在多个线程中逐行读取更快吗?例:

long fileLength = fs.Length;
long halfFile = (fileLength / 2);
FileStream fs2 = fs;
byte[] buffer2 = new byte[4096];
int bytesRead2 = 0;
var t1 = Task.Factory.StartNew(() =>
{
    while((bytesRead += fs.Read(buffer, 0, buffer.Length)) < (halfFile -1)) {
        Encoding.Unicode.GetString(buffer);
        //convert bytes into string lines...
    }
});
var t2 = Task.Factory.StartNew(() =>
{
    fs2.Seek(halfFile, SeekOrigin.Begin);
    while((bytesRead2 += fs2.Read(buffer2, 0, buffer2.Length)) < (fileLength)) {
        Encoding.Unicode.GetString(buffer2);
        //convert bytes into string lines...
    }
});

C# 将文本数据加载到 WPF 控件中

使用线程不会使其更快(从技术上讲,线程会略有开销,因此加载可能需要稍长的时间(,尽管它可能会使您的应用程序响应更快。 不知道File.ReadAllText()快不快?

不过,您将遇到问题的地方是数据绑定。 如果假设您在从工作线程加载 1GB 文件(无论技术如何(后,您现在将有 1GB 的行将数据绑定到您的ListView/ListBox。 我建议您不要通过ObservableCollection逐行将一行添加到控件中。

相反,请考虑让工作线程将项目批次追加到 UI 线程,它可以将项目追加到批处理中每个项的 ListView/ListBox。

这将减少Invoke的开销,因为它淹没了 UI 消息泵。

由于您想快速阅读,因此建议将 System.IO.File 类用于 WPF 桌面应用程序。

        MyText = File.ReadAllText("myFile.txt", Encoding.Unicode); // If you want to read as is
        string[] lines = File.ReadAllLines("myFile.txt", Encoding.Unicode); // If you want to place each line of text into an array

与数据绑定一起,WPF 应用程序应该能够读取文本文件并将其快速显示在 UI 上。

关于性能,可以参考这个答案。

所以使用 File.ReadAllText(( 而不是 ReadToEnd((,因为它会制作你的代码 更短,更具可读性。它还负责正确处理 资源,因为您可能会忘记使用流阅读器(就像您在 您的代码段(。- 达林·季米特洛夫

此外,还必须考虑将运行应用程序的计算机的规格。

当你说"逐行阅读内容需要很长时间"时,你是什么意思?您实际上是如何阅读内容的?

但是,最重要的是,让我们退后一步,看看将 1 GB 数据加载到 ListView 中的想法。

就个人而言,您应该使用IEnumerable来读取文件,例如:

foreach (string line in File.ReadLines(path))
{
}

但更重要的是,您应该在 UI 中实现分页,并减少可见内容和立即加载的内容。这将大大减少您的资源使用,并确保您拥有可用的 UI。您可以使用 IE无数 方法,例如 Skip()Take() ,它们可以有效地使用您的资源(即不加载未使用的数据(。

你也不需要使用任何额外的线程(除了后台线程 + UI 线程(,但我建议使用 MVVM 和 INotifyPropertyChanged 来完全跳过线程问题。