Могу ли я прочитать поток в строку, включая спецификацию Unicode? - PullRequest
0 голосов
/ 03 июля 2019

Content - это поток, содержащий символы Юникода. Это могут быть UTF-8, UTF-16 или UTF-32, и возможны оба порядка байтов.

Вот пример с UTF-16 символами Юникода, завершенный, включая спецификацию, указывающую Little Endian: FF FE.

У меня есть таблица позиций в этом файле. Эти позиции выражены в 16-битных символах. Спецификация находится в позиции 0, 2 байта после спецификации - позиция 1.

При выполнении

Dim oContent = New StreamReader(Content, Text.Encoding.Unicode)
Dim sContent = oContent.ReadToEnd

Спецификация полностью проглочена:

?scontent
"AAaa" & vbCrLf & "BB111" & vbCrLf & "BB22222" & vbCrLf & "CCc" & vbCrLf & ...

При установке detectEncodingFromByteOrderMarks на False:

    Dim oContent = New StreamReader(Content, False)
    Dim sContent = oContent.ReadToEnd

каждый символ представляет байт (но включая спецификацию):

?scontent
"��A" & vbNullChar & "A" & vbNullChar & "a" & vbNullChar & "a" & vbNullChar & vbCr & vbNullChar & vbLf & ...

Сочетание двух

    Dim oContent = New StreamReader(Content, Text.Encoding.Unicode, False)
    Dim sContent = oContent.ReadToEnd

полностью проглотит спецификацию снова:

?scontent
"AAaa" & vbCrLf & "BB111" & vbCrLf & "BB22222" & vbCrLf & "CCc" & vbCrLf & "DDddd" & vbCrLf

Вопрос: Можно ли как-то получить следующее в строку, точно так же, как в потоке?

Char    0     1     2     3
Byte    0  1  2  3  4  5  6  7
Content FF FE 41 00 41 00 61 00 ...

String.Substring (1, 3) должен выдавать "AAa"

Если нет: Можно ли как-то определить, какая спецификация была предоставлена ​​и в каком количестве байтов? (Это отличается среди входных файлов.)

1 Ответ

1 голос
/ 03 июля 2019

Можно ли как-то определить, какая спецификация была предоставлена ​​и в каком количестве байтов?

Если ваш файл (или поток, что угодно) имеет кодировку UTF-16, спецификация всегда будет 2 байта: либо FE FF, либо FF FE.

Так что, если вам действительно нужно знать спецификацию (если ваш файл с прямым или прямым порядком байтов), просто прочитайте первые два байта вашего файла (или потока):

Dim data as Byte()
Using fs = File.OpenRead("path/to/file/test.txt")
    Using binaryReader = new BinaryReader(fs)
        data = binaryReader.ReadBytes(2)
    End Using
End Using

Если ваш файл содержит спецификацию, data теперь будет содержать либо FE FF, либо FF FE.

Но вы также сказали, что уже знаете, что у вас файл с прямым порядком байтов UTF-16, поэтому мне не ясно, чего вы на самом деле пытаетесь достичь.

Когда вы читаете файл / поток в строку, строка не будет содержать спецификацию, так как это не имеет смысла: спецификация не является частью реального содержимого, это просто маркер, указывающий на то, как интерпретировать куча байтов.

Также обратите внимание, что не каждый символ в строке UTF-16 представлен двумя 8-битными байтами: символ также может быть представлен 4 байтами.

Если вы хотите содержимое в виде строки, просто используйте StreamReader(Content, Text.Encoding.Unicode).

Для вашего примера

String.Substring(1, 3) должен произвести "AAa"

либо просто вычтите 1 из индекса (String.Substring(0, 3)), либо просто добавьте в строку фиктивный 16-битный символ (Dim sContent = "x" + oContent.ReadToEnd).


Обновление: чтобы получить кодировку файла / потока, пусть StreamReader сделает всю работу за вас:

 Dim encoding as Encoding
 using sr = new StreamReader(filename, true)
    sr.peek()
    encoding = sr.CurrentEncoding
 end using

encoding.BodyName сейчас, например, utf-16BE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...