Как выполнить случайное чтение файла UTF8 - PullRequest
5 голосов
/ 08 февраля 2011

Насколько я понимаю, чтение в кодированный файл UTF8 или UTF16 не обязательно может быть случайным из-за случайного суррогатного байта (используется, например, в восточных языках).

Как я могу использовать .NET, чтобы перейти к приблизительной позиции в файле и прочитать текст в кодировке Юникод из полуслучайной позиции?

Стоит ли сбрасывать суррогатные байты и ждать, пока не прервется слово, чтобы продолжить чтение? Если да, то какие допустимые разрывы слов я должен ждать, пока не начну декодирование?

Ответы [ 3 ]

8 голосов
/ 08 февраля 2011

Легко, UTF-8 самосинхронизируется.
Просто перейдите к случайному байту в файле и пропустите-прочитайте все байты с начальными битами 10 (байты продолжения). Первый байт, у которого нет начального 10, является начальным байтом правильного символа UFT-8, и вы можете прочитать следующие байты, используя обычную кодировку UTF-8.

2 голосов
/ 08 февраля 2011

Предполагая, что вы хотите извлечь псевдослучайный символ из файла UTF-8, я лично откажусь от попыток понять, как прыгнуть в случайное место, а затем прокрутить вперед до гарантированного начала символа. 'позиция (что, как мне кажется, было бы сложным предложением) edit это неправильно . Как насчет чего-то вроде:

  1. Установить длину файла в байтах
  2. Эвристически угадать количество символов - например, путем масштабирования по константе, установленной из некоторого подходящего корпуса; или изучив первые n байтов и увидев, сколько символов они описывают, чтобы получить масштабную константу, которая могла бы быть более представительной для этого файла
  3. Выберите псевдослучайное число в 1..<guessed number of characters in file>
  4. Если файл очень большой (что, я полагаю, должен быть, иначе вы бы об этом не спрашивали), используйте буферизованное чтение для:
  5. Считайте байты файла, расшифровывая его до UTF-8, пока не достигнете нужного символа. Если вы упали с конца файла, используйте последний

Буферизованное чтение здесь должно будет использовать два буфера, которые поочередно являются «первыми», чтобы избежать потери контекста, когда байты символа разделены на два чтения, например:

Чтение буфера A: байты 1000-1999 Буфер чтения B: байты 2000-2999

Если символ занимает байты 1998-2001, использование одного буфера приведет к потере контекста.

Чтение буфера A: байты 3000-3999

Теперь действует буфер A , следующий за буфером B, когда мы преобразуем поток байтов в символы.


Как отметил @jleedev ниже, и, как видно из другого ответа, - это на самом деле легко и безопасно «прокрутить вперед» до гарантированного начала символа. Но приведенная выше оценка количества символов может оказаться полезной.

1 голос
/ 09 февраля 2011

Для UTF-16 вам всегда нужно перейти в четную байтовую позицию.Затем вы можете проверить, следует ли конечный суррогат.Если это так, пропустите его, в противном случае вы находитесь в начале правильно сформированной последовательности кодовых блоков UTF-16 (конечно, всегда предполагая, что файл правильно сформирован).

Кодировки Unicode UTF-8и UTF-16 были специально разработаны для самосинхронизации, и есть надежные гарантии того, что вам нужно пропустить не более небольшого числа кодовых блоков.

...