Probleme mit Datei-Hash Berechnung

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

danibert

Betreff: Probleme mit Datei-Hash Berechnung

BeitragDo, Mai 06, 2010 14:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo,

ich möchte Hashwerte für Dateien berechnen. Zur Berechnung habe ich das Beispiel von http://www.blitzbasic.com/code...?code=1449
verwendet, was auch recht gut funktioniert.

Den Code habe ich in der Datei hashAlgos.bmx gespeichert und binde ihn wie folgt ein:
Code: [AUSKLAPPEN]
Import maxgui.drivers
Strict
Include "hashAlgos.bmx"
' Quelle: http://www.blitzbasic.com/codearcs/codearcs.php?code=1449

    Function md5_File:String(path:String)
        If FileType(path) = 1 Then
            Local bytes:Byte[] = New Byte[FileSize(path)]
            Local s:TStream = ReadStream(path)
            If s Then
                s.ReadBytes(bytes, bytes.Length)
                s.Close()
                Local str:String = String.FromBytes(bytes, bytes.length)
                Return MD5(str)               
            End If
        End If
        Return ""
    End Function

' Testdatei
Local sourcefile:String = "F:\testfile.avi"

Print md5_File(sourcefile)

Repeat
  WaitEvent()
  Select EventID()
  Case EVENT_WINDOWCLOSE
     End
   End Select
Forever

Nun zum Problem: Wenn die zu verarbeitenden Dateien größer als ca. 300 MB sind, stürzt mein Programm mit der Meldung "Windows Exception: EXCEPTION_ACCESS_VIOLATION" ab. Keine weitere Beschreibung des Fehlers, der Debugger findet auch nichts. Bei kleineren Dateien klappt alles problemlos und die Hashwete werden korrekt berechnet.

Wie lässt sich dieses Problem beheben?
Hat jemand Erfahrung mit diesem Fehler?

Danke im Voraus für alle Tipps

mpmxyz

BeitragDo, Mai 06, 2010 18:14
Antworten mit Zitat
Benutzer-Profile anzeigen
BlitzMax: [AUSKLAPPEN]
Local bytes:Byte[] = New Byte[FileSize(path)]
[...]
String.FromBytes(bytes, bytes.length)

Du überlastest einfach deinen PC.
Das erste Array braucht für die Datei 300 MB Speicher.
Aus diesem Array erstellst du aber noch einen String mit der selben Länge. (+600 MB)
Das macht 900 MB an Speicher, welchen du innerhalb von wenigen Befehlen anforderst.
Das kann einfach nicht gut gehen, wenn du nicht gerade einen Superrechner hast.
Wandle die Hashfunktion am Besten so um, dass sie Streams ausliest und maximal ca. 1 KiB auf einmal bearbeitet.
mfG
mpmxyz
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer
  • Zuletzt bearbeitet von mpmxyz am Do, Mai 06, 2010 18:32, insgesamt einmal bearbeitet
 

danibert

BeitragDo, Mai 06, 2010 18:29
Antworten mit Zitat
Benutzer-Profile anzeigen
@mpmxyz
Ich habe momentan knapp 7 GB verfügbaren RAM (XP 64 Bit)
Was mich an der Sache wundert, zum Überprüfen der berechneten Hashwerte benutze ich ein Tool namens Hashcalc. Dieses berechnet mir auf dem selben Rechner problemlos Hashwerte von 4 GB großen Files (noch dazu in extremer Geschwindigkeit, nichts mit auslagern etc.).
Wie kann das funktionieren? Leider habe ich keinen Quelltext von Hashcalc Sad

mpmxyz

BeitragDo, Mai 06, 2010 18:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Hmm... Das ist schon seltsam.
Bestimme die Quelle des Fehlers am Besten mit "DebugLog" und "DebugStop".
Vielleicht löst sich das Rätsel dann.
mfG
mpmxyz
Moin Moin!
Projekte: DBPC CodeCruncher Mandelbrot-Renderer
 

danibert

BeitragDo, Mai 06, 2010 19:33
Antworten mit Zitat
Benutzer-Profile anzeigen
...ich versuche gerade, das Ganze wie angesprochen umzubauen, dass nur wenige KB auf einmal bearbeitet werden. Mir fehlt aber irgendwie der Ansatz, wie ich die Datei anders in die Hashfunktion bringen soll.

Zudem überlege ich, eine Progressbar zur Anzeige des Fortschritts einzubauen, was die Sache noch erschwert. Wie bekomme ich aus der Hashberechnung einen Event, der die Progressbar steuert? Ich glaube, da braucht es noch viel üben....
 

FWeinb

ehemals "ich"

BeitragDo, Mai 06, 2010 19:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Vor langer Zeit mal im BB.com Forum gefunden.
BlitzMax: [AUSKLAPPEN]
Function MD5:String(in:String)
Local h0:Int = $67452301, h1:Int = $EFCDAB89, h2:Int = $98BADCFE, h3:Int = $10325476

Local r:Int[] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, ..
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,..
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,..
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]

Local k:Int[] = [$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A, ..
$A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE,..
$6B901122, $FD987193, $A679438E, $49B40821, $F61E2562, $C040B340,..
$265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8,..
$21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8,..
$676F02D9, $8D2A4C8A, $FFFA3942, $8771F681, $6D9D6122, $FDE5380C,..
$A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA,..
$D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,..
$F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92,..
$FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1,..
$F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391]

Local intCount:Int = (((in:String.length + 8) Shr 6) + 1) Shl 4
Local data:Int[intCount]

For Local c:Int = 0 Until in:String.length
data[c:Int Shr 2] = data[c:Int Shr 2] | ((in:String[c:Int] & $FF) Shl ((c:Int & 3) Shl 3))
Next
data[in$.length Shr 2] = data[in$.length Shr 2] | ($80 Shl ((in$.length & 3) Shl 3))
data[data.length - 2] = (Long(in$.length) * 8) & $FFFFFFFF
data[data.length - 1] = (Long(in$.length) * 8) Shr 32

For Local chunkStart:Int = 0 Until intCount Step 16
Local a:Int = h0, b:Int = h1, c:Int = h2, d:Int = h3

For Local i:Int = 0 To 15
Local f:Int = d ~ (b & (c ~ d))
Local t:Int = d

d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + i]), r[i]) + b
a = t
Next

For Local i:Int = 16 To 31
Local f:Int = c ~ (d & (b ~ c))
Local t:Int = d

d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((5 * i) + 1) & 15)]), r[i]) + b
a = t
Next

For Local i:Int = 32 To 47
Local f:Int = b ~ c ~ d
Local t:Int = d

d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + (((3 * i) + 5) & 15)]), r[i]) + b
a = t
Next

For Local i:Int = 48 To 63
Local f:Int = c ~ (b | ~d)
Local t:Int = d

d = c ; c = b
b = Rol((a + f + k[i] + data[chunkStart + ((7 * i) & 15)]), r[i]) + b
a = t
Next

h0 :+ a ; h1 :+ b
h2 :+ c ; h3 :+ d
Next

Return (LEHex(h0) + LEHex(h1) + LEHex(h2) + LEHex(h3)).ToLower()
End Function


Function FileMD5:String(filePath:String, bufferSize:Int = $400000)
Assert (bufferSize & 63) = 0 Else "bufferSize must be a multiple of 64 bytes"

Local h0:Int = $67452301, h1:Int = $EFCDAB89, h2:Int = $98BADCFE, h3:Int = $10325476

Local r:Int[] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, ..
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,..
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,..
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]

Local k:Int[] = [$D76AA478, $E8C7B756, $242070DB, $C1BDCEEE, $F57C0FAF, $4787C62A, ..
$A8304613, $FD469501, $698098D8, $8B44F7AF, $FFFF5BB1, $895CD7BE,..
$6B901122, $FD987193, $A679438E, $49B40821, $F61E2562, $C040B340,..
$265E5A51, $E9B6C7AA, $D62F105D, $02441453, $D8A1E681, $E7D3FBC8,..
$21E1CDE6, $C33707D6, $F4D50D87, $455A14ED, $A9E3E905, $FCEFA3F8,..
$676F02D9, $8D2A4C8A, $FFFA3942, $8771F681, $6D9D6122, $FDE5380C,..
$A4BEEA44, $4BDECFA9, $F6BB4B60, $BEBFBC70, $289B7EC6, $EAA127FA,..
$D4EF3085, $04881D05, $D9D4D039, $E6DB99E5, $1FA27CF8, $C4AC5665,..
$F4292244, $432AFF97, $AB9423A7, $FC93A039, $655B59C3, $8F0CCC92,..
$FFEFF47D, $85845DD1, $6FA87E4F, $FE2CE6E0, $A3014314, $4E0811A1,..
$F7537E82, $BD3AF235, $2AD7D2BB, $EB86D391]

Local fileStream:TStream = OpenStream(filePath$, True, False)
If fileStream = Null Then Return ""

Local buffer:Byte Ptr = MemAlloc(bufferSize)
Local bitCount:Long, dataTop:Int = bufferSize

Repeat
Local bytesRead:Int = fileStream.Read(buffer, bufferSize)

If fileStream.Eof()
dataTop = (((bytesRead + 8) Shr 6) + 1) Shl 6
If dataTop > bufferSize
buffer = MemExtend(buffer, bufferSize, dataTop)
EndIf

bitCount :+ (bytesRead Shl 3)

For Local b:Int = (bytesRead + 1) Until (dataTop - 8)
buffer[b] = 0
Next

buffer[bytesRead] = $80
LEPokeLong(buffer, dataTop - 8, bitCount)
Else
bitCount :+ (bufferSize Shl 3)
EndIf

For Local chunkStart:Int = 0 Until (dataTop Shr 2) Step 16
Local a:Int = h0, b:Int = h1, c:Int = h2, d:Int = h3

For Local i:Int = 0 To 15
Local f:Int = d ~ (b & (c ~ d))
Local t:Int = d

d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + i) Shl 2)), r[i]) + b
a = t
Next

For Local i:Int = 16 To 31
Local f:Int = c ~ (d & (b ~ c))
Local t:Int = d

d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + (((5 * i) + 1) & 15)) Shl 2)), r[i]) + b
a = t
Next

For Local i:Int = 32 To 47
Local f:Int = b ~ c ~ d
Local t:Int = d

d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + (((3 * i) + 5) & 15)) Shl 2)), r[i]) + b
a = t
Next

For Local i:Int = 48 To 63
Local f:Int = c ~ (b | ~d)
Local t:Int = d

d = c ; c = b
b = Rol((a + f + k[i] + LEPeekInt(buffer, (chunkStart + ((7 * i) & 15)) Shl 2)), r[i]) + b
a = t
Next

h0 :+ a ; h1 :+ b
h2 :+ c ; h3 :+ d
Next
Until fileStream.Eof()

fileStream.Close()
MemFree(buffer)

Return (LEHex(h0) + LEHex(h1) + LEHex(h2) + LEHex(h3)).ToLower()
End Function

Function Rol:Int(val:Int, shift:Int)
Return (val Shl shift) | (val Shr (32 - shift))
End Function

Function LEPeekInt:Int(buffer:Byte Ptr, offset:Int)
Return (buffer[offset + 3] Shl 24) | (buffer[offset + 2] Shl 16) | ..
(buffer[offset + 1] Shl 8) | buffer[offset]
End Function

Function LEPokeLong(buffer:Byte Ptr, offset:Int, Value:Long)
For Local b:Int = 7 To 0 Step - 1
buffer[offset + b] = (value Shr (b Shl 3)) & $ff
Next
End Function

Function LEHex:String(val:Int)
Local out$ = Hex(val)

Return out$[6..8] + out$[4..6] + out$[2..4] + out$[0..2]
End Function


Hoffe das Hilft dir.

MfG
ich
"Wenn die Menschen nur über das sprächen, was sie begreifen, dann würde es sehr still auf der Welt sein." Albert Einstein (1879-1955)
"If you live each day as if it was your last, someday you'll most certainly be right." Steve Jobs
 

danibert

BeitragSa, Mai 08, 2010 11:32
Antworten mit Zitat
Benutzer-Profile anzeigen
...Neuer Versuch, gleiches Ergebnis Sad

Folgendes habe ich Probiert: Da ich nicht unbedingt den Hashwert für die gesamte Datei (am Stück) brauche, versuche ich also, die Datei in kleineren Paketen zu lesen und für jedes Paket einen Hash zu errechnen. Im Beispiel sind es 50MB, es funktioniert aber auch mit anderen Paketgrößen nicht. Das Problem kommt auch nicht von der Hashfunktion selbst, wenn ich diese komplett weglasse, habe ich das selbe Problem.
Code: [AUSKLAPPEN]
Import maxgui.drivers

Strict

Include "hashAlgos.bmx"
' Quelle: http://www.blitzbasic.com/codearcs/codearcs.php?code=1449

   Function makeHashes:String(path:String)
      If FileType(path) = 1 Then

         ' Startvariablen festlegen
         Local bytesGesamt:Int = Int(FileSize(path) )
         Local packageSize:Int = 52428800    ' Größe der Hashpakete in Byte
         Local currentByte:Int = 0
         Local str:String
         Local i
         
         ' Anzahl der Datenpakete errechnen
         Local rounds2Hash:Int = Floor(bytesGesamt / packageSize)
         Local rest2hash:Int   = bytesGesamt - (rounds2Hash * packageSize)      
               
         ' Datei öffnen
         Local bytes:Byte[] = New Byte[FileSize(path)]
         Local s:TStream = ReadFile(path)
         
         ' Datenpakete aus Datei lesen und Hash berechnen
            If s Then                  
         
               For i=1 To rounds2Hash         
                  
                  s.Seek(currentByte)
                  s.ReadBytes(bytes, packageSize)                     
      
                  str = String.FromBytes(bytes, bytes.length)
                  
                  Print MD5(str)
                  
                  currentByte = packageSize * i
                  
                  Print "weiter..."

               Next
               
               ' Restliche Bytes auslesen und Hash berechnen
               If (bytesGesamt-currentByte) > 0 Then
                  s.Seek(currentByte)
                  s.ReadBytes(bytes, (bytesGesamt-currentByte))   
                  str = String.FromBytes(bytes, (bytesGesamt-currentByte))

                  Print MD5(str)
               EndIf
   
               ' Datei schließen
               s.Close()
                  
            End If            
         End If
      Return ""
   End Function

' Testdatei
Local sourcefile:String = "J:\Testfile_500mb.test"
Local hashResult:String = makeHashes(sourcefile)

End

Ich kann den Fehler einfach nicht finden....
Hat jemand eine Idee, wie das funktionieren könnte?
 

danibert

BeitragSa, Mai 08, 2010 12:14
Antworten mit Zitat
Benutzer-Profile anzeigen
Rolling Eyes Schade, dass es hier keinen Smiley mit Tomaten auf den Augen gibt!! Rolling Eyes

Ich hatte komplett übersehen, dass ich mit
str = String.FromBytes(bytes, bytes.length)
ja doch wieder die gesamte Datei in die Variable drücke. Naja, aller Anfang ist schwer. Danke nochmal für alle Tipps.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group