[英]Exception when reading million characters in JSON file [OutOfMemoryException]
我已經下載了從Azure Blob存儲記錄的JSON文件。 檔案大小為137MB。
從文件上下文菜單中選擇“使用Notepad ++編輯”大約需要1-2秒。 因此,我決定創建一個程序以將JSON轉換器轉換為CSV文件格式。 但似乎,我遇到了某種例外。 當前,對於查看JSON內容,我將在RichTextBox中顯示,因為它可以在決定轉換為CSV之前查看內容。
事件開始加載:-
private async void txtjsonname_DoubleClick(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "JSON Files (*.json)|*.json";
ofd.InitialDirectory = @"C:\";
ofd.Title = "Select single json file to be converted";
ofd.Multiselect = false;
if (ofd.ShowDialog() == DialogResult.OK)
{
rtbstat.Text = null;
txtcsvname.Text = null;
txtjsonname.Text = null;
lblcsvpath.Text = null;
lbljsonpath.Text = null;
rtbjson.Clear();
txtjsonname.Text = Path.GetFileName(ofd.FileName);
lbljsonpath.Text = Path.GetDirectoryName(ofd.FileName);
if (await LoadJSONtoRTB(ofd.FileName))
{
rtbjson.WordWrap = false;
rtbstat.Text = "Load file finished! " + (rtbjson.Lines.Count()).ToString() + " line(s) detected | " + rtbjson.Text.Length.ToString() + " character(s) detected";
txtcsvname.Text = Path.GetFileNameWithoutExtension(ofd.FileName) + ".csv";
}
}
await Task.Delay(1000);
}
我嘗試過並遇到異常的代碼:-
第一種方法:第一個代碼:
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;
}
}
異常:System.Windows.Forms.dll中發生了類型為'System.AccessViolationException'的未處理異常
附加信息:嘗試讀取或寫入受保護的內存。 這通常表明其他內存已損壞。
第二種方法:
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;
}
}
使用上面的代碼,當我放置斷點以查看進度時,它將運行約12分鍾。
12分鍾,讀取長度為600萬。
有什么方法可以顯示文本文件(json / txt),其示例為6400萬個字符的長度,例如notepad ++只需1-2秒即可查看該文件?
我懷疑Notepad ++會將整個文件加載到內存中,該文件等於System.IO.File.ReadAllText
。 同樣,將文件的每一行附加到字符串上也沒有任何好處,最終結果是占用了相同的內存。 使用RichTextBox,您可以做的最好的事情是:
richTextBox1.Text = System.IO.File.ReadAllText(filePath);
無論如何,Notepad ++使用的Scintilla比RichTextBox快。
您可以嘗試使用ScintillaNET ,它是Scintilla的包裝。
您可以使用與RichTextBox相同的方式來設置控件文本:
scintilla1.Text = System.IO.File.ReadAllText(filePath);
您的LoadJSONtoRTB方法異步運行。 因此,您正在嘗試從錯誤的線程更新gui(文本框)。 這種方法將幫助您在正確的線程上運行gui更新:
this.Invoke(new Action(() => { rtbjson.Text += sr.ReadLine(); }));
當然,還有更有效的方法,例如StringBuilder來填充大量文本。 重要的收獲是始終在gui線程上更新gui。 這可以通過運行Form.Invoke來完成
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.