2013-10-28 6 views
0

데이터 테이블에 작은 바이너리 파일 (약 32MB)을 바이트 단위로 읽고 16 진수에서 8 진수로 8 바이트를 변환합니다.작은 이진 파일 읽기, 메모리 부족 예외

큰 파일의 경우 시스템 메모리 부족 예외 오류 메시지가 나타나고 코드를 더 부드럽거나 빠르 게 개선하는 방법을 생각할 수 없습니다.

3F F3 45 C6 03 00 11 00 00 6F 층 (1D) 16 12 07 0 D

을 : 판독되는 데이터

Public Function DecToBin(ByVal DeciValue As Long, Optional ByVal NoOfBits As Integer = 8) As String 
    Dim i As Integer 
    Do While DeciValue > (2^NoOfBits) - 1 
     NoOfBits = NoOfBits + 8 
    Loop 
    DecToBin = vbNullString 
    For i = 0 To (NoOfBits - 1) 
     DecToBin = CStr((DeciValue And 2^i)/2^i) & DecToBin 
    Next i 
End Function 

Private Sub importData(ByVal openFile As String) 
    If fullFilePath.EndsWith("variable.dat") Then 
     Dim importedData As New DataTable 
     Cursor.Current = Cursors.WaitCursor 
     Using reader As New BinaryReader(File.Open(openFile, FileMode.Open)) 
      Dim pos As Integer = 0 
      Dim length As Integer = reader.BaseStream.Length 
      loadingBar.loadingLabel.Text = "Lines of data: " & length 

      loadingBar.loadingProgress.Minimum = 0 
      loadingBar.loadingProgress.Maximum = length 
      loadingBar.loadingProgress.Step = 1 

      importedData.Columns.Add("Data0") 
      importedData.Columns.Add("Data1") 
      importedData.Columns.Add("Data2") 
      importedData.Columns.Add("Data3") 
      importedData.Columns.Add("Data4") 
      importedData.Columns.Add("Data5") 
      importedData.Columns.Add("Data6") 
      importedData.Columns.Add("Data7") 

      importedData.Columns.Add("Time") 
      importedData.Columns.Add("Date") 

      importedData.Columns.Add("Day") 
      importedData.Columns.Add("Month") 
      importedData.Columns.Add("Year") 

      importedData.Columns.Add("Blank") 

      While pos < length 

       For i = 0 To 15 
        Dim value As Decimal = reader.ReadByte 
        rawDataArray(i) = value.ToString() 
        pos += 1 
       Next 

       loadingBar.BringToFront() 
       loadingBar.Show() 
       Cursor.Current = Cursors.WaitCursor 

       loadingBar.loadingProgress.Value = pos 


       convertedDataArray(0) = DecToBin(rawDataArray(0)) 
       convertedDataArray(1) = DecToBin(rawDataArray(1)) 
       convertedDataArray(2) = DecToBin(rawDataArray(2)) 
       convertedDataArray(3) = DecToBin(rawDataArray(3)) 
       convertedDataArray(4) = DecToBin(rawDataArray(4)) 
       convertedDataArray(5) = DecToBin(rawDataArray(5)) 
       convertedDataArray(6) = DecToBin(rawDataArray(6)) 
       convertedDataArray(7) = DecToBin(rawDataArray(7)) 

       convertedDataArray(8) = Format((rawDataArray(12) + 0), "00") & ":" & Format((rawDataArray(11) + 0), "00") & ":" & Format((rawDataArray(10) + 0), "00") & "." & Format((rawDataArray(8) * 256) + rawDataArray(9), "000") 
       convertedDataArray(9) = Format((rawDataArray(13) + 0), "00") & "." & Format((rawDataArray(14) + 0), "00") & "." & "20" & Format((rawDataArray(15) + 0), "00") 

       convertedDataArray(10) = Format((rawDataArray(13) + 0), "00") 
       convertedDataArray(11) = Format((rawDataArray(14) + 0), "00") 
       convertedDataArray(12) = Format((rawDataArray(15) + 0), "00") 

       importedData.Rows.Add(convertedDataArray) 
       Application.DoEvents() 
      End While 
      loadingBar.Close() 
      importedData.DefaultView.Sort = "Year,Month,Day,Time" 
      dataGrid.DataSource = importedData.DefaultView 
     End Using 
     dataGrid.Columns(0).Visible = False ' Data 0 
     dataGrid.Columns(1).Visible = False ' Data 1 
     dataGrid.Columns(2).Visible = False ' Data 2 
     dataGrid.Columns(3).Visible = False ' Data 3 
     dataGrid.Columns(4).Visible = False ' Data 4 
     dataGrid.Columns(5).Visible = False ' Data 5 
     dataGrid.Columns(6).Visible = False ' Data 6 
     dataGrid.Columns(7).Visible = False ' Data 7 
     dataGrid.Columns(8).Visible = True ' Data Time 
     dataGrid.Columns(9).Visible = True ' Data Date 
     dataGrid.Columns(10).Visible = False ' Data Day 
     dataGrid.Columns(11).Visible = False ' Data Month 
     dataGrid.Columns(12).Visible = False ' Data Year 
     dataGrid.Columns(13).Visible = False ' Data Blank 

    Else 
     MsgBox("Wrong file selected") 
    End If 
End Sub 

예 : 여기

내 코드 출력 예 :

00111111 1 29 : : 1,110,011 01,000,101 11,000,110 00,000,011 00,000,000 00,010,001 00,000,000 (22) 31.111 2013년 7월 18일 18 07 13

+0

질문은 codereview에 속합니다 – Peter

+0

@peer 어떻게 보입니까? OP의 설명에도 불구하고 *** 작은 *** 파일을 처리 할 때 특정 문제에 대해 묻습니다. –

+1

왜 모든 ToString()/DecToBin 항목을 수행하고 있습니까? 'ReadByte()'는 이미'byte' ***를 리턴합니다 (특히, EOF의 경우 음수이거나 0-255의 범위에있는'int'를 리턴합니다. 단지' byte'와 : job done) : 당신이하려고하는 일의 몇 가지 예제 입/출력이 있습니까? 여기 중간에 작품을 발명하는 것처럼 보입니다 ... 또한 :'convertedDataArray'의 유형은 무엇입니까? –

답변

1

System.OutOfMemoryException를 얻는 것은 가능 필요한 크기의 할당되지 않은 메모리의 단일 연속 지역은 없습니다 것을 의미합니다. 반드시 메모리가 남아 있다는 의미는 아니지만 메모리가 조각난 방식으로 너무 많이 사용된다는 의미는 아닙니다.

문제를 해결하는 한 가지 방법은 이름에서 알 수 있듯이 프로세스의 가상 메모리 부분을 하드 드라이브의 데이터로 매핑하는 MemoryMappedFile 클래스를 사용하는 것입니다.

문제를 해결할 수있는 또 다른 방법은 메모리를 가비지 수집 프로세스의 일부로 압축하는 GC.Collect을 호출하는 것입니다. 하지만이 방법을 사용하지 않는 것이 좋습니다.

ANTS Memory Profiler 또는 windbg (Windows SDK의 일부로 제공)를 사용하여 메모리가 사용되는 곳을 확인할 수 있습니다.

코드에 대해서는 의심스럽지 않습니다. (Marc Gravell이 이미 지적한 DecToBin 제외).

희망이 도움이됩니다.