Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Hallo!
Ich verwende SHA1 als Prüfsumme beim versenden einer Datei. Die Prüfsumme wird zunächst mit Java gebildet. Da erhalte ich in einem Array beispielsweise 6,228,76,-64,-105,-91.
Die Datei wird auf einen PDA übertragen und mit C# wird erneut die Prüfsumme erstellt: 6,228,76,192,151,165
Warum bekomme ich bei Java negative Werte und in C# nicht. Denke schon, dass ich die Funktionen richtig verwende (192 -(-64) = 256; 151-(-105)=256 usw.) aber so bringt mir das nichts, denn die Prüfsummen sind ja falsch. Kann ich da irgend welche Einstellungen vornehmen oder das abfangen?
Bis denne
Benne
MessageDigest md = null;
byte[] byteHash = null;
StringBuffer resultString;
try {
// Choose between MD5 and SHA1
md = MessageDigest.getInstance("SHA1");
} catch(Exception e) {
System.out.println("NoSuchAlgorithmException caught!");
//System.exit( -1);
}
md.reset();
md.update(mybytearray,i,schrittgroesse); //Der Teil der Datei der aktuell verschickt werden soll
resultString.append(Integer.toHexString(0xFF & byteHash[j]));
wobei mybytearray die Datei ist. Dadurch das die Datei > 30 mb ist werden immer nur teile übertragen. Für jeden Teil soll dann der SHA1 berechnet und mitgeschickt werden. Hatte das Beispiel woanders gefunden.
ich meine das Ergbnis sieh ja auch soweit richtig aus - aber Java scheint mit den Bytes irgendwie anders umzugehen als .NET
Aus irgend einem Grund werden hier negative Bytes geschrieben und in C# stattdessen wesentlich höhere Bytes. Hat das was mit diesem Litte bzw Big Endian zu tun?
dein Ergebnis zieht sowieso sehr seltsam aus, wenn ich es mit dem Tutorial vergleiche
Da sollte eigentlich z.B. sowas: ABAC19481F4367DB4AE592B463E002C3CDD47906
rauskommen.
Schau dir das dort nochmal an, oder poste ein kleines, lauffähiges Beispiel. Nur mit Codeschnipzeln ist es schwer mit der Fehlerdiagnose.
Das sieht deswegen so seltsam aus weil ich die bytes des Arrays angegeben habe - nicht den Hash. Damit wollte ich nur beweisen, dass die Funktion sehr wohl funktioniert - es nur ein Problem zwischen Java und c# gibt.
Hallo Benne,
du hast alles richtig gemacht. Die Lösung hast du ja eigentlich auch selbst genannt. C rechnet hier vermutlich mit einem unsigned datentypen, daher die positiven zahlen. Mein Lösungsvorschlag:
resultString.append(Integer.toHexString(0xFF & temp));
}
Nun passen die Hashwerte schonmal in int(wenn du nut temp ausgibst), wenn du möchtest kannst du mit diesen Werten ja jetzt wieder ein Array füllen.
Gruß, der Red
hi - danke für die Antwort.
Befürchte nur, dass mir das ganze Konzept der Prüfsumme bei meinem eigentlichen Problem nicht hilft. Ich versuche eine große Datei (knapp 20-30 MB) per Sockets vom PC (Java) auf einen PDA (C#) zu schicken. Hin und wieder wird die Datei korrekt übertragen, aber gerade bei großen Dateien häufen sich die Fehler. Verzweifle mittlerweile fast 14 Tage an diesem Problem.
TCP übernimmt die Aufgabe der Transportsicherung. Wenn die Datei dennoch kaputt ist, ist wohl entweder beim Sender, oder beim Empfänger, oder bei beiden im Argen. Da solltest du ansetzen.
Hast du evtl. generell Probleme mit dem unterschiedlichen Byte-Handling auch beim Übertragen der Daten via Socket? Hast du versucht mit einem TCP-Monitor die Übertragung der Packete nachzuvollziehen? Sind die Daten, die via Java per stream rausgeschickt werden, die selben, wie sie auch beim PDA ankommen, bzw. ist evtl. nur die Interpretation eines solchen Datums anders? ich würde mir da einzelne Bytes mal angucken wie die Binär aussehen und ob man "Gemeinsamkeiten" entdecken kann...
ja das die Transportsicherung bei TCP liegt habe ich auch rausbekommen. Darum hatte ich ja auch die Idee mit der Checksumme aufgegeben.
Ich kann ja mal nen bisschen beschreiben was ich so versucht habe.
1.
Java
Code:
Outputstream os;
mybytearray = meine Datei als Bytearray
os.write(mybytearray,0,mybytearray.length);
C# bietet keine Funktion um die Die Datei im ganzen zu empfangen. Würde aber eh nicht gehen, weil der Speicher des PDAs nicht reichen würde. Darum rufe ich immer X Byte (z.B. 10240) ab und schreibe die direkt in einen FileStream
Code:
bytes = new Byte[10240];
while (bytecounter < length) {
stream.Read(bytes, 0, bytes.Length);
stream.Flush();
fs.Write(bytes, 0, bytes.Length);
bytecounter += bytes.Length;
}
Die Dateien die ich so empfange sind leider kaputt (schon wenn die nen bisschen größer als nen MB sind)
Da habe ich mir gedacht, dass vielleicht zu schnell Daten versendet werden und der PDA nicht schnell genug diese abrufen kann.
2.
Also versende ich auf Java Seite die Datei auch nur noch in 10240 Byte großen Streams. Bevor die nächsten 10240 Byte versendet werden können wird auf nen ack des PDA gewartet. Das funktioniert ganz gut und die Dateien sind FAST identisch (bytes verglichen). Probleme gibt es gegen Ende wenn nicht mehr wirklich 10240 Byte versendet werden. Die Empfangende Datei wird größer als das original - kaputt.
3. Vor jedem Datenpaket versende ich in einem Byte einen int Wert (1-7) den ich als Übertragungsmodus interpretiere. 1=10240, 2= 5120.... So dass eigentlich immer die richtige anzahl Bytes gelesen werden sollte. Bei Dateien bis 10 mb gibt es eigentlich auch fast keine Fehler mehr. Bei 30 MB sind knapp 50% der Dateien defekt. Der Grund liegt daran, dass hin und wieder das Modus-Byte falsch gelesen wird (werte größer als 7). Also muss irgend etwas die doch eigentlich sehr strickte Reihenfolge (es wird auf beiden Seiten vor dem Versenden auf ein ack gewartet) beeinflussen.
Des weiteren habe ich nur viele viele weitere kleinere Versuche gemacht, aber ich bekomme das einfach nicht in den Griff.
Eiegntlich müsste ich mir doch diese ganze Stückelei auf der JAvaSeite sparen können, oder? Wenn das doch eh durch TCP überwacht wird.
Und noch was - gibt es ne Grenze darüber wie groß man die Byte-Schritte machen darf? Klar - irgendwann gibt es keine Geschwindigkeitsvorteile mehr, aber es würde mich schon interessieren.
Bis denne
Benne
Kannst du nicht einfach in Java in einen Stream schreiben ohne um dir ob der bytes Gedanken zu machen, und das gleiche auf C# Seite? Wenn dabei dann ein byte kippt, hat man etwas das man sich näher ansehen kann.
hab nochmal ganz vorne angefangen und jetzt klappt es auch. Geht eigentlich so leicht wie man es erhofft:
Java-Seite:
Code:
os.write(mybytearray,0,mybytearray.length);
C#
Code:
while (bytecounter < length)
{
bytes = new Byte[10240];//8192
int value = stream.Read(bytes, 0, bytes.Length);
stream.Flush();
fs.Write(bytes, 0, value);
bytecounter += value;
}
Der Fehler war, dass ich zuvor immer den kompletten Array in den Filestream geschrieben habe. Die Funktion stream.Read() gibt aber die tatsächlich gelesenen Bytes zurück und nur diese Anzahl darf in den FileStream geschrieben werden.
Nun habe ich aber ein weiteres Problem - allerdings glaube ich nicht, dass dies so schwierig zu lösen ist. Wenn ich auf Java-Seite eine Sehr große Datei (z.B. 60MB) öffne um sie zu verschicken, dann bekomme ich eine Memory Exception. Hat jemand ein Beispiel wie ich z.B nur 10MB einer Datei einlese und erst danach erst die nächsten 10MB?
Code:
for (int i =0; i<pards; i++)
{
byte [] mybytearray = new byte[1048576]; //1MB
System.out.println("Sending part "+i+": "+i*mybytearray.length);
int v = bis.read(mybytearray,i*mybytearray.length,mybytearray.length);
os.write(mybytearray,0,v);
os.flush();
}
Wenn ich an der Stelle bis.read(mybytearray,i*mybytearray.length,mybytearray.length); das zweite MB laden will bekomme ich immer "null". (nicht einmal ne Exception).