2009-06-15 11 views
2

Ich erstelle eine Binärdatei, um sie an eine dritte Partei zu übertragen, die Bilder und Informationen über jedes Bild enthält. Die Datei verwendet ein Datensatzlängenformat, sodass jeder Datensatz eine bestimmte Länge hat. Der Anfang jedes Datensatzes ist der Datensatzlängenindikator, der 4 Zeichen lang ist und die Länge des Datensatzes im Big Endian-Format darstellt.Falsche Codierung beim Schreiben in eine Datei verwenden C#

Ich verwende einen BinaryWriter, um in die Datei zu schreiben, und für die Record Length Indicator verwende ich Encoding.Default.

Das Problem, das ich habe, ist, dass es ein Zeichen in einem Datensatz gibt, der als "?" weil es nicht erkannt wird. My-Algorithmus die Zeichenfolge für das Satzlängenanzeiger aufzubauen, ist dies:

private string toBigEndian(int value) 
    { 
     string returnValue = "";    
     string binary = Convert.ToString(value, 2).PadLeft(32, '0'); 
     List<int> binaryBlocks = new List<int>(); 
     binaryBlocks.Add(Convert.ToInt32(binary.Substring(0, 8), 2)); 
     binaryBlocks.Add(Convert.ToInt32(binary.Substring(8, 8), 2)); 
     binaryBlocks.Add(Convert.ToInt32(binary.Substring(16, 8), 2)); 
     binaryBlocks.Add(Convert.ToInt32(binary.Substring(24, 8), 2)); 

     foreach (int block in binaryBlocks) 
     {     
      returnValue += (char)block; 
     } 

     Console.WriteLine(value); 

     return returnValue; 
    } 

sie die Länge des Datensatzes stattfindet, wandelt sie in 32-Bit-Binär-, dass wandelt in Stücke von 8-Bit-Binär-, und wandelt dann jedes Stück zu seinem passenden Charakter. Die Zeichenfolge, die hier zurückgegeben wird, enthält die richtigen Zeichen, aber wenn sie in die Datei geschrieben wird, wird ein Zeichen nicht erkannt. Dies ist, wie ich es schreibe:

Vielleicht verwende ich die falsche Art der Codierung? Ich habe UTF-8 versucht, das sollte funktionieren, aber es gibt mir manchmal zusätzliche Zeichen.

Vielen Dank im Voraus für Ihre Hilfe.

+0

Was ist der Charakter, der nicht richtig konvertiert? –

+0

Da der Wert in ein Zeichen umgewandelt und dann so codiert wird, als wäre es ein echtes Zeichen, gibt es eine ganze Reihe von Werten, die nicht richtig funktionieren. Die meisten Werte über 127 wären wahrscheinlich falsch ... – Guffa

Antwort

6

Das Problem ist, dass Sie sollten gib den Wert überhaupt nicht als String zurück.

Wenn Sie den Wert in ein Zeichen umwandeln und dann als 8-Bit-Zeichen codieren, werden mehrere Werte in den falschen Byte-Code und mehrere Werte codiert, die überhaupt nicht codiert werden können die Charaktere). Die einzige Möglichkeit, Daten in diesem Schritt nicht zu verlieren, wäre, sie als UTF-16 zu kodieren, aber das würde Ihnen acht statt vier Bytes geben.

Sie sollten als Byte-Array zurückgeben, so dass Sie es in die Datei schreiben können, ohne es zwischen Zeichendaten und Binärdaten hin und her zu konvertieren.

private byte[] toBigEndian(int value) { 
    byte[] result = BitConverter.GetBytes(value); 
    if (BitConverter.IsLittleEndian) Array.Reverse(result); 
    return result; 
} 

fileWriter.Write(toBigEndian(length)); 
+0

Genau richtig und das Problem gelöst. Vielen Dank. – Aaron

1

Wenn Sie wirklich ein binären vier Bytes wollen (also nicht nur vier Zeichen, sondern ein Big-Endian-32-Bit-Längenwert), dann wollen Sie so etwas wie diese:

byte[] bytes = new byte[4]; 
bytes[3] = (byte)((value >> 24) & 0xff); 
bytes[2] = (byte)((value >> 16) & 0xff); 
bytes[1] = (byte)((value >> 8) & 0xff); 
bytes[0] = (byte)(value & 0xff); 
fileWriter.Write(bytes); 
0

Um/Schreib-Bits aus Binärströme mit entsprechender Endianess lesen Sie die BitConverter Klasse verwenden, da es explizite Unterstützung für Endianess hat: http://msdn.microsoft.com/en-us/library/system.bitconverter.islittleendian.aspx

auf binäre Konvertierung dann in Bytes Zeichenüber ist, muß ich sagen, das unorthodoxe Art und Weise sehe ich noch :)

+0

Die IsLittleEndian-Eigenschaft ist eine schreibgeschützte Eigenschaft, die angibt, ob das System groß oder Little Endian ist. Es erlaubt Ihnen nicht, Endian zu setzen. Dafür müssen Sie Ihre eigenen rollen oder einen von vielen online finden. –

+0

BitConverter unterstützt keine Endianität. Diese Eigenschaft gibt nur an, ob die aktuelle Plattform Little Endian ist oder nicht. Es wird nicht die Umwandlung in Big Endian für Sie tun. –

+0

Die Theorie besagt, dass Sie die Endianess überprüfen sollten, ob die GetBytes-Ausgabe zurückgesetzt werden soll oder nicht. Aber du hast recht, meine Antwort war insofern irreführend, als der BitConverter die Ausgabe nicht wirklich in der richtigen Endlichkeit anbieten kann. –

1

Erstellen Sie keine Zeichenfolge aus einem Int, um Bytes zu schreiben. Versuchen Sie besser dies:

byte[] result = 
    { 
     (byte)(value >> 24), 
     (byte)(value >> 16), 
     (byte)(value >> 8) , 
     (byte)(value >> 0) 
    }; 
Verwandte Themen