2

エンコーディングをマークするバイト オーダー マーカー (BOM) が含まれている可能性のある任意のテキスト入力を取得し、ASCII として出力できるようにする必要があります。BOM を認識しない古いツールがいくつかあり、それらに ASCII のみのデータを送信する必要があります。

今、私はこのコードを書き終えたところですが、ここでの非効率性はまったく信じられません。データの 4 つのコピー。StreamReader 内部の中間バッファーは言うまでもありません。これを行うより良い方法はありますか?

// 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);

StreamReader() が必要なのは、ファイルの残りを読み取るためのエンコーディングを選択するための内部 BOM 検出器があるためです。あとは、最終的な ASCII 文字列に変換するだけです。

これを行うより良い方法はありますか?

4

2 に答える 2

1

すでにメモリにi_fileBytesがある場合は、それがBOMで始まるかどうかを確認してから、全体またはBOMの少し後にを使用して変換できますEncoding.Unicode.GetString。(インデックスと長さを指定できるオーバーロードを使用してください。)

したがって、コードとして:

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

ただし、これは純粋にリトルエンディアンのUTF-16エンコーディングを想定していることに注意してください。本当に最初にエンコーディングを検出する必要がある場合は、StreamReaderの機能を再実装するか、最初の(たとえば)10バイトからStreamReaderを構築し、CurrentEncodingプロパティを使用してエンコーディングに何を使用するかを決定します。

編集:さて、ASCIIへの変換に関しては-本当に.NET文字列としてのみ必要な場合は、おそらく、ASCII以外の文字を「?」に置き換えるだけです。または同様のもの。(あるいは、例外をスローする方が良いかもしれません...もちろんそれはあなた次第です。)

編集:エンコーディングを検出するときはRead()、1回だけ呼び出して1文字を読み取ることをお勧めします。ReadToEnd()任意の量のデータとして10バイトを選択して呼び出すのではなく、文字の途中で終了する可能性があります。それが例外をスローするかどうかはわかりませんが、とにかく利点はありません...

于 2008-11-21T18:57:57.137 に答える
0
System.Text.Encoding.ASCII.GetBytes(new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd())

これにより、いくつかの往復を節約できます。

于 2010-07-27T20:08:20.887 に答える