簡體   English   中英

在C#中處理大文件時出現內存不足異常

[英]Out of Memory Exception when handling large files in C#

我有一個C#winforms應用程序,其中我使用OpenFileDialog讓用戶選擇要打開的文本文件。(允許多個選擇)一旦他們選擇了文本文件,我逐個打開文件,獲取文本並存儲內容使用List.Add()操作的List變量。

當用戶選擇異常大量的文本文件(如1264個文本文件,總大小高達750MB)時,我的問題就出現了,程序無法處理它。 它讀取了大約850個文件然后給我一個內存不足的例外。 在任務管理器中,當發生這種情況時,我的應用程序的內存(私有工作集)大約為1.5GB。 我使用x64機器與32GB內存。

我給出了通讀文件的代碼:

public static List<LoadData> LoadDataFromFile(string[] filenames)
{
    List<LoadData> MasterData = new List<LoadData>();
    lookingForJobs = new LookingForJobs(1,filenames.Length);
    lookingForJobs.Show();
    /*-------OUTER LOOP TO GO THROUGH ALL THE FILES-------*/
    for (int index = 0; index < filenames.Length; index++)
    {
        string path = filenames[index];
        /*----------INNER LOOP TO GO THROUGH THE CONTENTS OF EACH FILE------*/
        foreach (string line in File.ReadAllLines(path))
        {
            string[] columns = line.Split('\t');
            if (columns.Length == 9)
            {
                if (line.StartsWith("<"))    /*-------IGNORING THE FIRST 8 LINES OF EACH LOG FILE CONTAINING THE LOGGER INFO---------*/
                {
                    MasterData.Add(new LoadData
                    {
                        Event_Type = columns[0],
                        Timestamp = columns[1],
                        Log_Message = columns[2],
                        Category = columns[3],
                        User = columns[4],
                        Thread_ID = columns[5],
                        Error_Code = columns[6],
                        Application = columns[7],
                        Machine = columns[8]
                    });
                }
            }
        }
        lookingForJobs.SearchingForJobsProgress.PerformStep();
        /*--------END OF INNER LOOP--------*/
    }
    lookingForJobs.Dispose();
    /*-----------END OF OUTER LOOP-----*/
    return MasterData;
}

編輯:我知道我應該重新設計我的代碼,以便不是所有的文件都被立即讀入對象。 但是,我想知道列表對象或內存(私有工作集)的大小是否有任何限制。 我在一些文章中讀到,當你達到1.5-1.6 GB時會出現這些問題。

使用File.ReadLines而不是File.ReadAllLines因為第二個不必要地將所有文件加載到內存中,而您一次只需要一行。 MSDN說

使用ReadAllLines時,必須等待返回整個字符串數組才能訪問該數組。 因此,當您使用非常大的文件時,ReadLines可以更高效。

這將為您提供相當大的內存改進。

第二個想法是重新考慮是否真的需要存儲在內存中的如此大的數據。 也許你可以只將文件路徑存儲到每個文件中並按需讀取它們。

您的文件可能很小,但您正在構建的MasterData對象仍將存儲它在內存中找到的所有數據...

聽起來你可能需要重新設計一些應用程序......

您是否通過分析器運行此操作 - 看看您是否可以在整個程序過程中檢查內存使用情況?

您正在創建包含從文件中讀取的大部分數據的對象。 我認為類別,用戶,錯誤代碼,應用程序和機器的值將重復許多記錄。

您可以創建包含這些字符串值的字典。 對於您閱讀的每個值,您將檢查字典中是否已存在相等的字符串並使用該字符串,否則添加它。 這樣那些字符串只會在內存中存在一次。

字符串實習使用相同的原則,但是你實際上它們將保留在內存中的字符串直到應用程序關閉。 通過將它們放入字典中,您可以在不再需要它們時將其刪除。

例; 做一本字典:

Dictionary<string, string> values = new Dictionary<string, string>();

獲取值並在字典中使用/注冊值:

string category = columns[3];
if (values.ContainsKey(category)) {
  category = values[category];
} else {
  values.Add(category, category);
}

當然,您只能在期望具有大量重復值的值上使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM