在JSON文件中读取百万个字符时出现异常[OutOfMemoryException]

时间:2017-01-20 09:12:24

标签: c# json csv azure

我已经下载了一个从Azure Blob Storage录制的JSON文件。文件大小为137MB。

使用Notepad ++打开时的字符和行属性,如下图所示: enter image description here

当我选择"使用Notepad ++"编辑时,大约需要1-2秒。从文件上下文菜单。因此,我决定创建一个程序,将JSON转换器转换为CSV文件格式。但似乎,我遇到了某种例外。目前,为了查看JSON内容,我将在RichTextBox中显示,因为它可以在我决定转换为CSV之前查看内容。

开始加载的事件: -

private async Task<bool> LoadJSONtoRTB(string path)
    {
        try
        {
            foreach (var line in File.ReadLines(path))
            {
                rtbjson.Text = line;
            }
            await Task.Delay(10);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

我尝试过的代码面临异常: -

第一种方法: 第一个代码:

private async Task<bool> LoadJSONtoRTB(string path)
    {
        try
        {
            using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            using (BufferedStream bs = new BufferedStream(fs))
            using (StreamReader sr = new StreamReader(bs))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    rtbjson.AppendText(line);
                }
            }
            await Task.Delay(10);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }

第二段代码:

private async Task<bool> LoadJSONtoRTB(string path)
{
    try
    {
        StreamReader sr = new StreamReader(@path);
        while (!sr.EndOfStream)
            rtbjson.Text += sr.ReadLine();
        await Task.Delay(10);
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}

enter image description here 例外:类型&#39; System.AccessViolationException&#39;的未处理异常发生在System.Windows.Forms.dll

附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

第二种方法: -

{{1}}

使用上面的代码,当我设置断点以查看进度时,它运行大约12分钟。 enter image description here

12分钟,长度为600万。

是否有任何方法可以显示文本文件(json / txt),其中包含6400万字符长度的示例,如记事本++只需1-2秒即可查看文件?

2 个答案:

答案 0 :(得分:2)

我怀疑Notepad ++将整个文件加载到内存中,等同于System.IO.File.ReadAllText。此外,将文件的每一行附加到字符串没有任何好处,最终结果是占用相同的内存。 使用RichTextBox,您可以做的最好的事情是:

richTextBox1.Text = System.IO.File.ReadAllText(filePath);

无论如何,Notepad ++使用比RichTextBox更快的Scintilla

您可以尝试使用ScintillaNET作为Scintilla的包装器。

您可以像使用RichTextBox一样设置控制文本:

scintilla1.Text = System.IO.File.ReadAllText(filePath);

答案 1 :(得分:1)

您的LoadJSONtoRTB方法异步运行。因此,您尝试从错误的线程更新gui(文本框)。 这种方法将帮助您在正确的线程上运行gui更新:

this.Invoke(new Action(() => { rtbjson.Text += sr.ReadLine(); }));

当然,有更多有效的方法用StringBuilder等大量文本填充控件。 重要的一点就是永远更新gui线程上的gui。 这可以通过运行Form.Invoke

来完成