Есть ли лучший способ конвертировать в ASCII с произвольного ввода? - PullRequest
2 голосов
/ 21 ноября 2008

Мне нужно иметь возможность взять произвольный текстовый ввод, который может иметь маркер порядка байтов (BOM), чтобы отметить его кодировку, и вывести его как ASCII. У нас есть несколько старых инструментов, которые не понимают спецификации, и мне нужно отправлять им данные только для ASCII.

Теперь, я только что закончил писать этот код, и я просто не могу поверить в неэффективность здесь. Четыре копии данных, не говоря уже о каких-либо промежуточных буферах внутри 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 (), потому что он имеет внутренний детектор спецификации для выбора кодировки для чтения остальной части файла. Тогда остальное - просто преобразовать его в окончательную строку ASCII.

Есть ли лучший способ сделать это?

Ответы [ 2 ]

1 голос
/ 21 ноября 2008

Если у вас уже есть i_fileBytes в памяти, вы можете просто проверить, начинается ли она с спецификации, а затем преобразовать либо всю ее, либо только бит после спецификации, используя 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, либо, возможно, просто построить StreamReader из первых (скажем) 10 байтов и использовать свойство CurrentEncoding, чтобы выяснить, что должно использовать для кодирования.

РЕДАКТИРОВАТЬ: Теперь, что касается преобразования в ASCII - если вам действительно нужно это только как строку .NET, то, вероятно, все, что вы хотите сделать, это заменить любые не-ASCII символы на «?» или что-то подобное. (В качестве альтернативы может быть лучше создать исключение ... это, конечно, зависит от вас.)

РЕДАКТИРОВАТЬ: обратите внимание, что при обнаружении кодирования было бы неплохо просто вызвать Read() один раз, чтобы прочитать один символ. Не вызывайте ReadToEnd(), так как при выборе 10 байтов в качестве произвольного объема данных, он может заканчиваться средним символом. Я не знаю, будет ли это исключение, но это все равно не даст никаких преимуществ ...

0 голосов
/ 28 июля 2010
System.Text.Encoding.ASCII.GetBytes(new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd())

Это должно сэкономить несколько поездок туда и обратно.

...