Что я должен делать в .NET с кодированной строкой UTF8? - PullRequest
0 голосов
/ 22 сентября 2019

Я использую Google Chrome Native Messaging, который сообщает, что он поддерживает кодировку USON в кодировке UTF8. Находится здесь.

Я почти уверен, что мой код довольно стандартный и в значительной степени является копией ответов здесь, в C #. Например, см. Этот вопрос SO.

Private Function OpenStandardStreamIn() As String
    Dim MsgLength As Integer = 0
    Dim InputData As String = ""
    Dim LenBytes As Byte() = New Byte(3) {} 'first 4 bytes are length

    Dim StdIn As System.IO.Stream = Console.OpenStandardInput() 'open the stream
    StdIn.Read(LenBytes, 0, 4) 'length
    MsgLength = System.BitConverter.ToInt32(LenBytes, 0) 'convert length to Int

    Dim Buffer As Char() = New Char(MsgLength - 1) {} 'create Char array for remaining bytes

    Using Reader As System.IO.StreamReader = New System.IO.StreamReader(StdIn) 'Using to auto dispose of stream reader
        While Reader.Peek() >= 0 'while the next byte is not Null
            Reader.Read(Buffer, 0, Buffer.Length) 'add to the buffer
        End While
    End Using

    InputData = New String(Buffer) 'convert buffer to string

    Return InputData
End Function

Проблема, с которой я столкнулся, заключается в том, что когда JSON включает такие символы, как ß Ü Ö, тогда вся строка кажется разнородной, и я не могудесериализовать это.Это читабельно, и мой журнал показывает, что строка в порядке, но есть что-то другое.Пока строка НЕ ​​содержит эти символы, десериализация работает нормально.Я не предоставляю код JavascriptSerializer, так как это не проблема.

Я пытался создать StreamReader с различными кодировками, такими как

New System.IO.StreamReader(StdIn, Encoding.GetEncoding("iso-8859-1"), True)

, однако ß Ä и т. Д. В этом случае не верны.

Чего я не понимаю, так это если строка UTF8 и .NET использует UTF16, как мне убедиться, что преобразование выполнено правильно?

ОБНОВЛЕНИЕ

Проводил тестирование.Я обнаружил, что если я получаю строку с fuß, тогда длина сообщения (предоставляемая собственным обменом сообщениями) равна 4, но число Char в буфере равно 3, если строка равна fus, тогда длина сообщения равна 3, а количество символов равно3. Почему это так?

При использовании приведенного выше кода объект Buffer 1 слишком велик, и поэтому возникает проблема.Если я просто использую метод Read в потоке, то он работает нормально.Похоже, что Google Messaging отправляет сообщение длиной, отличной от ß в строке.

Если я хочу использовать приведенный выше код, то как узнать, что длина сообщения неверна?

Ответы [ 2 ]

1 голос
/ 29 сентября 2019

"Каждое сообщение сериализуется с использованием JSON, кодировки UTF-8, и ему предшествует 32-битная длина сообщения в собственном байтовом порядке. Максимальный размер одного сообщения с собственного хоста обмена сообщениями составляет 1 МБ."Это подразумевает, что длина сообщения также указывается в байтах, что длина не является частью сообщения (и, следовательно, его длина не включена в длину).

Ваша путаница, по-видимому, связана с одной из двух вещей:

  1. UTF-8 кодирует кодовую точку Unicode в 1-4 кодовых единицах.(Единица кода UTF-8 составляет 8 битов, один байт.)
  2. Char - это единица кода UTF-16.(Единица кода UTF-16 - это 16 битов, два байта. UTF-16 кодирует кодовую точку Unicode в 1–2 единицы кода.)

Невозможно определить, сколько кодовых точек или UTF-16 единиц кода находятся в сообщении до тех пор, пока оно не будет преобразовано (или отсканировано, но тогда вы можете просто преобразовать его).

Тогда, предположительно, stream будет либо найден закрытым, либо следующей прочитанной будет другая длина и сообщение.

Итак,

Private Iterator Function Messages(stream As Stream) As IEnumerable(Of String)
    Using reader = New BinaryReader(stream)
        Try                
            While True
                Dim length = reader.ReadInt32
                Dim bytes = reader.ReadBytes(length)
                Dim message = Encoding.UTF8.GetString(bytes)
                Yield message
            End While
        Catch e As EndOfStreamException
            ' Expected when the sender is done
            Return
        End Try
    End Using
End Function

Использование

Messages(stream).ToList()

или

For Each message In Messages(stream)
    Debug.WriteLine(message)            
Next message
0 голосов
/ 22 сентября 2019

если вы отображаете вывод этого кода в консоли, это может произойти неуверенно.потому что консоль Windows не отображает символы Unicode.если это не так, попробуйте использовать построитель строк для преобразования данных в потоке StdIn в строку

...