簡體   English   中英

使用C#讀取大型文本文件時出現System.OutofMemoryException

[英]System.OutofMemoryException while reading a large text file using C#

我有讀取文本文件並填充.Net數據表的代碼。 當讀取具有100,000行數據的較小尺寸的文本文件時,該代碼可以正常工作。 (請參閱下面的代碼段)當我嘗試讀取較大的文本文件大小(如200MB)並具有360萬行數據時,拋出System.OutofMemoryException異常。 想問一個將大數據讀入某些塊的有效方法。

        using (var stream = File.Open(filePath, FileMode.Open))
        {
            var content = new StreamContent(stream);
            var fileStream = content.ReadAsStreamAsync().Result;

            if (fileStream == null) throw new ArgumentException(Constants.FileEmptyErrorMessage);

            using (var bs = new BufferedStream(fileStream))
            {
                using (var reader = new StreamReader(bs, Encoding.GetEncoding(Constants.IsoEncoding)))
                {


                    while (!reader.EndOfStream)
                    {
                        var line = reader.ReadLine();
                        if (!String.IsNullOrEmpty(line))
                        {
                            string[] rows = line.Trim().Split(new char[] { ';' }, StringSplitOptions.None);

                            DataRow dr = Table.NewRow();
                            dr[Constants.Percepcion] = rows[0];
                            dr[Constants.StartDate] = DateTime.ParseExact(rows[2].ToString(), "ddMMyyyy",
                                CultureInfo.InvariantCulture);
                            dr[Constants.EndDate] = DateTime.ParseExact(rows[3].ToString(), "ddMMyyyy",
                                CultureInfo.InvariantCulture);
                            dr[Constants.CID] = rows[4];
                            dr[Constants.Rate] = rows[8];

                            Table.Rows.Add(dr);
                        }
                    }
                }
            }
        }

我可以看到內存泄漏不是因為您已經逐行讀取整個文件var line = reader.ReadLine(); 我認為泄漏是因為數據Table的大小,因為它包含整個文件的所有數據。
我建議這些選項之一:
1.如果要在數據表的行上執行聚合函數,則只需執行它們(如設置整數計數器或double max_columnX),而不必保留整個行。
2.如果您確實需要保留所有行。 創建一個數據庫(MSSQL / MYSQL /或任何數據庫)並逐行讀取文件(與您一樣),然后將這些數據插入數據庫中。 然后使用您的條件查詢數據庫。
3.您可以將整個文件批量插入數據庫中,而無需通過C#應用程序進行處理。 這是一個SQL SERVER 示例

BULK INSERT AdventureWorks2012.Sales.SalesOrderDetail
   FROM 'f:\orders\lineitem.tbl'
   WITH
     (
        FIELDTERMINATOR =';',
        ROWTERMINATOR = '\n',
        FIRE_TRIGGERS
      );

編輯:您可以附加一個內存探查器,以查找究竟占用了大內存的內容並將其添加到問題中。 這將有助於獲得更好的答案。

如果您更改BufferedStream的默認緩沖區大小,則它將為您更高效率地加載較大的文件。 例如

using (var bs = new BufferedStream(fileStream, 1024))
{
    // Code here.
}

您也許可以簡單地使用FileStream而不指定BufferedStream來指定緩沖區大小,從而擺脫困境。 有關更多詳細信息,請參見此MSDN博客

這是我閱讀大文本文件的工作。 無需使用緩沖蒸汽。

var filteredTextFileData = (from textFileData in File.ReadAllLines(_filePathList[0]).Skip(1).Where(line => !string.IsNullOrEmpty(line))
                    let textline = textFileData.Split(';')
                    let startDate = DateTime.ParseExact(textline[2].ToString(), Constants.DayMonthYearFormat, CultureInfo.InvariantCulture)
                    let endDate = !string.IsNullOrEmpty(textline[3]) ? DateTime.ParseExact(textline[3], Constants.DayMonthYearFormat, CultureInfo.InvariantCulture) : (DateTime?)null
                    let taxId = textline[0]
                    join accountList in _accounts.AsEnumerable()
                    on taxId equals accountList.Field<string>(Constants.Comments)
                    where endDate == null || endDate.Value.Year > DateTime.Now.Year || (endDate.Value.Year == DateTime.Now.Year && endDate.Value.Month >= DateTime.Now.Month)
                    select new RecordItem()
                    {
                        Type = Constants.Regular,
                        CustomerTaxId = taxId,
                        BillingAccountNumber = accountList.Field<Int64>(Constants.AccountNo).ToString(),
                        BillingAccountName = accountList.Field<string>(Constants.BillCompany),
                        StartDate = DateTime.Compare(startDate, accountList.Field<DateTime>(Constants.DateActive)) < 1 ? accountList.Field<DateTime>(Constants.DateActive) : startDate,
                        EndDate = endDate,
                        OverrideRate = 0,
                        Result = Constants.NotStarted,
                        TaxCode = _taxCode,
                        ImpliedDecimal = 4
                    }).ToList();

暫無
暫無

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

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