Подтвердить что ты не робот

Сохранение строки как UTF8 в С#

Я делаю много строковых манипуляций на С#, и действительно нужно, чтобы строки сохранялись на один байт на символ. Это связано с тем, что мне требуется гигабайт текста одновременно в памяти, что вызывает проблемы с низкой памятью. Я точно знаю, что этот текст никогда не будет содержать символы, отличные от ASCII, поэтому для моих целей тот факт, что System.String и System.Char хранят все как два байта на символ, являются ненужными и реальной проблемой.

Я собираюсь начать кодирование своих собственных классов CharAscii и StringAscii - строка будет в основном содержать свои данные в виде байта [] и вызывать методы манипуляции строками, аналогичные тем, которые делает System.String. Однако, похоже, это большая работа, чтобы сделать что-то, что кажется очень стандартной проблемой, поэтому я действительно размещаю здесь, чтобы проверить, что еще нет более простого решения. Есть ли, например, каким-то образом я могу заставить System.String внутренне хранить данные как UTF8, которые я не заметил, или каким-то другим способом проблемы?

4b9b3361

Ответ 1

Как вы нашли, CLR использует UTF-16 для кодировки символов. Лучше всего использовать классы кодирования и битконвертер для обработки текста. У этого вопроса есть несколько хороших примеров для преобразования двух кодировок:

Преобразовать строку (UTF-16) в UTF-8 в С#

Ответ 2

Ну, вы можете создать оболочку, которая извлекает данные в виде байтов UTF-8 и преобразует фрагменты по мере необходимости в System.String, а затем наоборот, чтобы вывести строку обратно в память. Класс Encoding поможет вам:

var utf8 = Encoding.UTF8;
byte[] utfBytes = utf8.GetBytes(myString);

var myReturnedString = utf8.GetString(utfBytes);

Ответ 3

Не совсем. System.String предназначен для хранения строк. Ваше требование относится к очень конкретному подмножеству строк с конкретными преимуществами памяти.

Теперь "очень конкретное подмножество строк с конкретными преимуществами памяти" появляется много, но не всегда одно и то же очень определенное подмножество. Код, который является ASCII-only, предназначен не для чтения людьми, поэтому он имеет тенденцию быть либо короткими кодами, либо тем, что может обрабатываться в процессе обработки потока, или же фрагменты текста, объединенные с байтами, выполняющими другие задания ( например, несколько бинарных форматов будут иметь небольшие биты, которые переводят непосредственно в ASCII).

Таким образом, у вас довольно странное требование.

Тем более, когда вы приходите к гигабайтной части. Если я имею дело с концертами, я сразу же думаю о том, как я могу перестать иметь дело с концертами и/или получать гораздо более серьезные сбережения, чем только 50%. Я бы подумал о том, как отображать куски, которые меня сейчас не интересуют, или о веревках, или о нескольких других вещах. Конечно, они собираются работать в некоторых случаях и не для всех, так что опять же, мы не говорим о том, где .NET должен вставлять что-то как одноразмерное, потому что один размер не подходит все.

Кроме того, просто бит utf-8 не так уж и трудный. Это все другие методы, которые становятся работой. Опять же, то, что вам нужно, не будет таким же, как у кого-то другого.

Ответ 4

Как я вижу, ваша проблема заключается в том, что char в С# занимает 2 байта вместо одного.

Один из способов чтения текстового файла - открыть его с помощью:

    System.IO.FileStream fs = new System.IO.FileStream(file, System.IO.FileMode.Open);
    System.IO.BinaryReader br = new System.IO.BinaryReader(fs);

    byte[] buffer = new byte[1024];
    int read = br.Read(buffer, 0, (int)fs.Length);

    br.Close();
    fs.Close(); 

И таким образом вы читаете байты из файла. Я пробовал его с *.txt файлами, закодированными в UTF-8, 2 байта на char и ANSI, который 1 байт за char.