2 Stimmen

Gibt es eine bessere Möglichkeit, aus einer beliebigen Eingabe in ASCII zu konvertieren?

Ich muss in der Lage sein, eine beliebige Texteingabe zu nehmen, die einen Byte Order Marker (BOM) haben kann, um ihre Kodierung zu markieren, und sie als ASCII auszugeben. Wir haben einige alte Tools, die BOMs nicht verstehen, und ich muss ihnen Daten senden, die nur ASCII sind.

Ich habe diesen Code gerade fertig geschrieben und kann nicht glauben, wie ineffizient das ist. Vier Kopien der Daten, ganz zu schweigen von den internen Zwischenpuffern im StreamReader. Gibt es eine bessere Möglichkeit, dies zu tun?

// i_fileBytes is an incoming byte[]

string unicodeString = new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd();
byte[] unicodeBytes  = Encoding.Unicode.GetBytes(unicodeString.ToCharArray());
byte[] ansiBytes     = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, unicodeBytes);
string ansiString    = Encoding.ASCII.GetString(ansiBytes);

Ich brauche den StreamReader(), weil er einen internen BOM-Detektor hat, um die Kodierung zu wählen, um den Rest der Datei zu lesen. Der Rest ist dann nur noch die Umwandlung in den endgültigen ASCII-String.

Gibt es eine bessere Möglichkeit, dies zu tun?

1voto

Jon Skeet Punkte 1325502

Wenn Sie i_fileBytes bereits im Speicher haben, können Sie einfach prüfen, ob es mit einem BOM beginnt oder nicht, und dann entweder den gesamten Inhalt oder nur das Bit nach dem BOM mit Encoding.Unicode.GetString . (Verwenden Sie die Überladung, mit der Sie einen Index und eine Länge angeben können).

Also als Code:

int start = (i_fileBytes[0] == 0xff && i_fileBytes[1] == 0xfe) ? 2 : 0;
string text = Encoding.Unicode.GetString(i_fileBytes, start, i_fileBytes.Length-start);

Beachten Sie jedoch, dass dies eine echte Little-Endian UTF-16-Kodierung voraussetzt. Wenn Sie wirklich brauchen, um die Kodierung zuerst zu erkennen, könnten Sie entweder neu zu implementieren, was StreamReader tut, oder vielleicht nur einen StreamReader aus den ersten (sagen wir) 10 Bytes zu bauen, und verwenden Sie die CurrentEncoding Eigenschaft zu arbeiten, was Sie debe für die Kodierung verwenden.

EDIT: Nun, wie für die Konvertierung in ASCII - wenn Sie wirklich nur es als eine .NET-Zeichenfolge benötigen, dann vermutlich alles, was Sie tun möchten, ist ersetzen alle nicht-ASCII-Zeichen mit "?" oder etwas ähnliches. (Alternativ könnte es besser sein, eine Ausnahme zu werfen... das ist bis zu Ihnen, natürlich.)

EDIT: Beachten Sie, dass bei der Erkennung der Kodierung, wäre es eine gute Idee, nur aufrufen Read() ein einziges Mal, um ein Zeichen zu lesen. Rufen Sie nicht ReadToEnd() denn wenn man 10 Bytes als willkürliche Datenmenge wählt, könnte es mitten im Zeichen enden. Ich weiß nicht aus dem Stegreif, ob das eine Ausnahme auslösen würde, aber es hat sowieso keine Vorteile...

0voto

Joshua Punkte 37898
System.Text.Encoding.ASCII.GetBytes(new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd())

Das dürfte einige Hin- und Rückfahrten ersparen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X