2009-09-14 4 views
19

Also hier ist der Deal: Ich versuche, eine Datei (aus Bytes) zu öffnen, konvertieren Sie es in eine Zeichenfolge, damit ich einige Metadaten in der Kopfzeile verwirren kann, konvertieren Sie es zurück zu Bytes und speichern Sie es. Das Problem, auf das ich gerade stoße, ist mit diesem Code. Wenn ich die Zeichenfolge, die vor und zurück konvertiert wurde (aber nicht anderweitig modifiziert wurde), mit dem ursprünglichen Byte-Array vergleicht, ist sie ungleich. Wie kann ich das schaffen?Konvertieren von Byte-Array in String und wieder zurück in C#

public static byte[] StringToByteArray(string str) 
{ 
    UTF8Encoding encoding = new UTF8Encoding(); 
    return encoding.GetBytes(str); 
} 

public string ByteArrayToString(byte[] input) 
{ 
    UTF8Encoding enc = new UTF8Encoding(); 
    string str = enc.GetString(input); 
    return str; 
} 

Hier ist, wie ich sie vergleiche.

byte[] fileData = GetBinaryData(filesindir[0], Convert.ToInt32(fi.Length)); 
string fileDataString = ByteArrayToString(fileData); 
byte[] recapturedBytes = StringToByteArray(fileDataString); 
Response.Write((fileData == recapturedBytes)); 

Ich bin sicher, dass es UTF-8, mit:

StreamReader sr = new StreamReader(filesindir[0]); 
Response.Write(sr.CurrentEncoding); 

die "System.Text.UTF8Encoding" zurückgibt.

+6

Sind Sie sicher, dass seine UTF-8 zu beginnen? –

+0

Ich bin unsicher. Wie würde ich sagen, ob es ist oder nicht? –

+0

Was meinst du, es ist ungleich? Deine Saite ist ungleich? Sie erhalten nicht das gleiche String-Ergebnis? – Khan

Antwort

16

Probieren Sie die statischen Funktionen der Klasse Encoding aus, die Ihnen Instanzen der verschiedenen Codierungen zur Verfügung stellt. Sie sollten die Encoding nicht instanziieren, nur um zu/von einem Bytearray zu konvertieren. Wie vergleicht man die Strings im Code?

bearbeiten

Sie Arrays sind zu vergleichen, keine Strings. Sie sind ungleich, weil sie sich auf zwei verschiedene Arrays beziehen; Mit dem Operator == werden nur ihre Referenzen verglichen, nicht ihre Werte. Sie müssen jedes Element des Arrays überprüfen, um festzustellen, ob sie äquivalent sind.

public bool CompareByteArrays(byte[] lValue, byte[] rValue) 
{ 
    if(lValue == rValue) return true; // referentially equal 
    if(lValue == null || rValue == null) return false; // one is null, the other is not 
    if(lValue.Length != rValue.Length) return false; // different lengths 

    for(int i = 0; i < lValue.Length; i++) 
    { 
     if(lValue[i] != rValue[i]) return false; 
    } 

    return true; 
} 
+0

Ich habe die Frage bearbeitet, um zu zeigen, wie ... der Code nicht direkt im Kommentar erscheint! –

+0

Ich habe das versucht, sie geben zurück, dass sie nicht von der gleichen Länge sind. Es muss woanders sein. –

+3

Werfen Sie einen Blick auf die Dokumentation für die UTF8-Codierung. Es gibt eine Option, ob die Präambel angegeben werden soll oder nicht. Wenn Sie feststellen, dass das generierte Byte-Array länger als das Original ist, ist das wahrscheinlich Ihr Problem. Auch hier müssen Sie sicherstellen, dass UTF8 in der Tat die richtige Kodierung ist. Wie Sie es sehen können, müssten Sie fragen, wer Sie mit den Daten versorgt. –

3

Ihr Problem scheint der Weg zu sein, die das Array von Bytes sind zu vergleichen:

Response.Write((fileData == recapturedBytes)); 

Dies wird immer false zurück, da Sie die Adresse des Byte-Arrays sind zu vergleichen, nicht die Werte, die es enthält. Vergleichen Sie die Zeichenfolgendaten oder verwenden Sie eine Methode zum Vergleichen der Bytearrays. Man könnte dies auch stattdessen tun:

Response.Write(Convert.ToBase64String(fileData) == Convert.ToBase64String(recapturedBytes)); 
5

Aufgrund der Tatsache, dass .NET Strings Unicode-Strings verwenden, können Sie nicht mehr tun dies wie Menschen in den meisten Fällen in C hat, sollte man nicht einmal Versuch zu hin und her von String < -> Byte-Array, wenn der Inhalt tatsächlich Text ist.

ich diesen Punkt machen klar: In .NET, wenn die byte[] Daten nicht Text ist, dann versuchen Sie es nicht zu einem string zu konvertieren mit Ausnahme der speziellen Base64 Codierung für binäre Daten über einen Text Kanal. Dies ist ein weit verbreitetes Missverständnis unter Leuten, die in .NET arbeiten.

+4

Zeichenfolge <-> byte [] Konvertierungen sollten in der Regel über eine der System.Text.Encoding-Klassen, nicht die BitConverter-Klasse durchgeführt werden. BitConverter.ToString konvertiert ein Byte-Array in eine hexadezimale Zeichenfolgendarstellung der Zahlen, ** konvertiert ** ein Byte-Array jedoch nicht in eine Zeichenfolge. –

+1

Heh, ich hätte diese Zeile entfernen sollen, sobald ich wusste, dass das nicht der Sinn meines Beitrags war. –

7

Wenn Sie rohe Bytes (8-Bit möglicherweise nicht-druckbare Zeichen) haben und wollen, dass sie als .NET-String zu manipulieren und sie in Bytes zurück, können Sie dies tun, indem

Encoding.GetEncoding(1252) 

mit anstelle von UTF8Encoding. Diese Codierung funktioniert, um einen beliebigen 8-Bit-Wert zu übernehmen und in ein .NET 16-Bit-Zeichen umzuwandeln, und wieder zurück, ohne irgendwelche Informationen zu verlieren.

In dem speziellen Fall, den Sie oben beschreiben, können Sie mit einer Binärdatei nicht mit Metadaten in der Kopfzeile "herumhantieren" und die Dinge funktionieren, solange die Daten nicht verändert werden. Wenn der Header beispielsweise

enthält und Sie ABC in DEF ändern möchten, sollte das so funktionieren, wie Sie möchten. Aber wenn Sie ABC in WXYZ ändern wollen, müssen Sie über das Byte schreiben, das auf "C" folgt, oder Sie werden (im Wesentlichen) alles um ein Byte weiter nach rechts verschieben. In einer typischen Binärdatei wird das alles sehr vermasseln. Wenn die Bytes nach "ABC" Leerzeichen oder Nullzeichen sind, besteht eine größere Chance, dass das Schreiben größerer Ersatzdaten keine Probleme verursacht - aber Sie können ABC nicht einfach durch WXYZ in der .NET-Zeichenkette ersetzen, wodurch es länger wird - Sie müssten ABC {whatever_follows_it} durch WXYZ ersetzen. In Anbetracht dessen können Sie vielleicht feststellen, dass es einfacher ist, die Daten als Bytes zu belassen und die Ersatzdaten jeweils ein Byte zu schreiben.

+0

Wenn man ein Array von Bytes hat und alle Vorkommen einer bestimmten Sequenz durch eine andere Sequenz einer anderen Länge ersetzen möchte (zB alle Vorkommen von {0x7D, 0x5E} durch {0x7E} ersetzen), würde das Konvertieren in String mit 'String .Replace', und dann zurück konvertieren ein vernünftiger Ansatz sein? Würde die oben erwähnte Kodierung jeden Byte-Wert 0-255 durch seinen entsprechenden Code mit gleicher Nummer ersetzen [die Tatsache, dass die Kodierung verlustfrei ist, würde dies selbst nicht implizieren]? – supercat

+0

@supercat - Ja, dieser Ansatz (sofern Sie die 1252-Codierung verwenden) würde funktionieren. Aber aus den in meiner Nachricht genannten Gründen ist das mit den meisten binären Dateiformaten immer noch nicht möglich. –

+0

Wenn man positionsempfindliche Formate verwendet, müsste man natürlich dafür sorgen, dass Dinge, die sich nicht bewegen sollen, dies nicht tun. Selbst dann würde es Fälle geben, in denen "String.Replace" nützlich wäre, wenn die "Original" - und "Ersatz" -Strings die gleiche Länge hätten. – supercat

Verwandte Themen