使用File.ReadAllText(x)读取大文件时如何避免“内存不足”异常

时间:2013-11-19 15:04:20

标签: vb.net visual-studio-2010 visual-studio-2012 memory-leaks

这是我的代码,用于搜索包含字符串“hello”的驱动器“G:\”中所有文件和文件夹的字符串:

Dim path = "g:\"
Dim fileList As New List(Of String)

 GetAllAccessibleFiles(path, fileList)

 'Convert List<T> to string array if you want
  Dim files As String() = fileList.ToArray

  For Each s As String In fileList
      Dim text As String = File.ReadAllText(s)
      Dim index As Integer = text.IndexOf("hello")
      If index >= 0 Then
           MsgBox("FOUND!")
           ' String is in file, starting at character "index"
      End If
  Next

此代码也会导致内存泄漏/内存不足异常(因为我读取的文件大到5GB!)。也许它会将整个文件带到RAM中,然后进行字符串检查。

Dim text As String = File.ReadAllText("C:\Users\Farizluqman\mybigmovie.mp4") 
    ' this file sized as big as 5GB!
    Dim index As Integer = text.IndexOf("hello")
    If index >= 0 Then
        MsgBox("FOUND!")
        ' String is in file, starting at character "index"
    End If

但是,问题是:此代码实际上是 DANGEROUS ,这可能导致内存泄漏或使用100%的RAM。问题是,上面的代码有什么办法或解决方法吗?也许分块或读取部分文件然后处置以避免内存泄漏/内存不足?或者有没有办法在使用代码时最小化内存使用量?因为我觉得对其他人的计算机稳定性负责。请帮助:)

1 个答案:

答案 0 :(得分:3)

你应该使用System.IO.StreamReader,它逐行读取所有行(这里你有一个类似的post in C#);我个人从不使用ReadAll ***,除非在非常特殊的条件下。代码的示例改编:

Dim index As Integer = -1
Dim lineCount As Integer = -1
Using reader As System.IO.StreamReader = New System.IO.StreamReader("C:\Users\Farizluqman\mybigmovie.mp4")
    Dim line As String
    line = reader.ReadLine
    If (line IsNot Nothing AndAlso line.Contains("hello")) Then
        index = line.IndexOf("hello")
    Else
        If (line IsNot Nothing) Then lineCount = line.Length
        Do While (Not line Is Nothing)
            line = reader.ReadLine
            If (line IsNot Nothing) Then
                lineCount = lineCount + line.Length
                If (line.Contains("hello")) Then
                    index = lineCount - line.Length + line.IndexOf("hello")
                    Exit Do
                End If
            End If
        Loop
    End If
End Using

If index >= 0 Then
    MsgBox("FOUND!")
    ' String is in file, starting at character "index"
End If