utf8 -> string
От: neFormal Россия  
Дата: 20.10.08 15:29
Оценка:
Есть сервер под Linux. Есть клиент под винду на C#.
С сервера передаются строки в utf8. Тип данных wchar_t, длиной 4 байта. Клиенту они передаются тоже по 4 байта на символ.
На клиенте принимается строка и переводится в Encoding.Unicode через Encoding.UTF8.GetString().

Проблема:
Т.к. utf8 не имеет жесткого размера, а сервер присылает строку с жестким количеством байт на символ, то появляется бага.
Вместо строчки:
['H', 'e', 'l', 'l', 'o'] получаем:
['H', 0, 0, 0, 'e', 0, 0, 0, 'l', 0, 0, 0, 'l', 0, 0, 0, 'o', 0, 0, 0]
Т.е. на каждый распознанный конвертером символ получаем дополнительно 3 нуля. Фактически символ "умещался" в один байт, а сервер прислал 4 байта.

Как лучше избавиться от такого косяка?.

Сейчас клиент врукопашную удаляет ненужные нули. Но тогда при передаче серверу нужно будет "наращивать" нули. И это всё кажется жутко криво.
Есть еще вариант использовать на сервере iconv, но он(iconv) на сервере почему то падает.
...coding for chaos...
c# utf8 linux
Re: utf8 -> string
От: vmpire Россия  
Дата: 20.10.08 15:48
Оценка: +1
Здравствуйте, neFormal, Вы писали:

F>Есть сервер под Linux. Есть клиент под винду на C#.

F>С сервера передаются строки в utf8. Тип данных wchar_t, длиной 4 байта. Клиенту они передаются тоже по 4 байта на символ.
F>На клиенте принимается строка и переводится в Encoding.Unicode через Encoding.UTF8.GetString().

F>Проблема:

F>Т.к. utf8 не имеет жесткого размера, а сервер присылает строку с жестким количеством байт на символ, то появляется бага.
F>Вместо строчки:
F>['H', 'e', 'l', 'l', 'o'] получаем:
F>['H', 0, 0, 0, 'e', 0, 0, 0, 'l', 0, 0, 0, 'l', 0, 0, 0, 'o', 0, 0, 0]
F>Т.е. на каждый распознанный конвертером символ получаем дополнительно 3 нуля. Фактически символ "умещался" в один байт, а сервер прислал 4 байта.

F>Как лучше избавиться от такого косяка?.


F>Сейчас клиент врукопашную удаляет ненужные нули. Но тогда при передаче серверу нужно будет "наращивать" нули. И это всё кажется жутко криво.

F>Есть еще вариант использовать на сервере iconv, но он(iconv) на сервере почему то падает.

Это похоже на кодировку utf-32, может, нужно использовать её?
Re[2]: utf8 -> string
От: neFormal Россия  
Дата: 20.10.08 19:04
Оценка:
Здравствуйте, vmpire, Вы писали:

V>Это похоже на кодировку utf-32, может, нужно использовать её?


Честно говоря, не знаю о совместимости utf8 и utf32, возможно utf8 — это аналог utf32 с плавающим размером
Попробуем.

Но мне кажется логичным данное поведение для utf8, т.к. размер у него не жестко заданный, а в плюсовом коде нужно размер знать заранее.
И копипаста из вики, которая меня натолкнула на эту мысль:

Остальные символы Юникода изображаются последовательностями длиной от 2 до 6 байтов (реально только до 4 байт, поскольку использование кодов больше 221 не планируется), в которых первый байт всегда имеет вид 11xxxxxx, а остальные — 10xxxxxx.

...coding for chaos...
Re[3]: utf8 -> string
От: vmpire Россия  
Дата: 20.10.08 19:34
Оценка:
Здравствуйте, neFormal, Вы писали:

F>Здравствуйте, vmpire, Вы писали:


V>>Это похоже на кодировку utf-32, может, нужно использовать её?


F>Честно говоря, не знаю о совместимости utf8 и utf32, возможно utf8 — это аналог utf32 с плавающим размером

F>Попробуем.

F>Но мне кажется логичным данное поведение для utf8, т.к. размер у него не жестко заданный, а в плюсовом коде нужно размер знать заранее.

F>И копипаста из вики, которая меня натолкнула на эту мысль:
F>

F>Остальные символы Юникода изображаются последовательностями длиной от 2 до 6 байтов (реально только до 4 байт, поскольку использование кодов больше 221 не планируется), в которых первый байт всегда имеет вид 11xxxxxx, а остальные — 10xxxxxx.


utf-8, utf-16, utf-32, ucs-2... это формы представления символов Unicode, которые сами по себе занимают по 4 байта каждый.

uft-8 и utf-16 — кодировки переменной длины (utf-8 от 1 до 6 байтов, utf-16 — 2 или 4 байта)
utf-32 и ucs-4 — кодировки с фиксированным количеством байт (4 штуки)
В .NET есть встроенная кодировка uft-32, про которую я и говорю
Re: utf8 -> string
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.08 02:21
Оценка: 4 (1)
Здравствуйте, neFormal, Вы писали:

F>Есть сервер под Linux. Есть клиент под винду на C#.

F>С сервера передаются строки в utf8. Тип данных wchar_t, длиной 4 байта.
Этого не может быть. Два утверждения противоречат друг другу. В UTF-8 используется переменное количество байт на символ; в частности, вся латиница умещается в 1 байт на символ.
Поэтому нужно выяснить, в какой кодировке передаются строки с сервера на самом деле. Как уже верно предположили, это может быть UTF32.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: utf8 -> string
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.08 02:21
Оценка:
Здравствуйте, vmpire, Вы писали:

V>utf-8, utf-16, utf-32, ucs-2... это формы представления символов Unicode, которые сами по себе занимают по 4 байта каждый.

Это чрезмерно упрощенное представление. Сode points Unicode не занимают никакого количества байт; это натуральные числа.
Символ некоего алфавита не всегда имеет однозначное представление в виде code points, в частности, буква ё может быть представлена одним code point либо двумя (кириллическая е + две точки над ней).
Любая кодировка (в том числе и utf-32) задает правила конверсии между байтовой последовательностью и цепочкой натуральных чисел.
Таким образом, в зависимости от кодировки, та же буква ё может занимать от 1 до 8 байт.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: utf8 -> string
От: neFormal Россия  
Дата: 21.10.08 07:43
Оценка:
Здравствуйте, Sinclair, Вы писали:

F>>Есть сервер под Linux. Есть клиент под винду на C#.

F>>С сервера передаются строки в utf8. Тип данных wchar_t, длиной 4 байта.
S>Этого не может быть. Два утверждения противоречат друг другу. В UTF-8 используется переменное количество байт на символ; в частности, вся латиница умещается в 1 байт на символ.

Поэтому в линухе используется, видимо, количество байт "с запасом", чтобы все используемые символы наверняка влезли.
Вот кусок кода оттуда (stddef.h):
#ifndef __WCHAR_TYPE__
#define __WCHAR_TYPE__ int // neFormal: вот эти вот 4 байта
#endif
#ifndef __cplusplus
typedef __WCHAR_TYPE__ wchar_t;
#endif


Для сравнения в винде используется utf16le и 2 байта на символ и:
typedef unsigned short wchar_t; // neFormal: вот эти 2 байта


S>Поэтому нужно выяснить, в какой кодировке передаются строки с сервера на самом деле. Как уже верно предположили, это может быть UTF32.


Проверил, не utf32.
Коды символов, переданные по сети такие же, как если бы писать utf8 в файл. Разница только в дополнительных байтах.
...coding for chaos...
Re[4]: utf8 -> string
От: neFormal Россия  
Дата: 21.10.08 07:44
Оценка:
Здравствуйте, vmpire, Вы писали:

V>В .NET есть встроенная кодировка uft-32, про которую я и говорю


Да, я понял, я в курсе про utf32 в .net-е
Проверил, не оно.
Подробности: http://gzip.rsdn.ru/forum/message/3145818.1.aspx
Автор: neFormal
Дата: 21.10.08
...coding for chaos...
Re[5]: utf8 -> string
От: vmpire Россия  
Дата: 21.10.08 08:20
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, vmpire, Вы писали:


V>>utf-8, utf-16, utf-32, ucs-2... это формы представления символов Unicode, которые сами по себе занимают по 4 байта каждый.

S>Это чрезмерно упрощенное представление. Сode points Unicode не занимают никакого количества байт; это натуральные числа.
Так я и упрощаю. Реально там немногим больше миллиона символов, что в 2 байта не влезает, а в 4 — влезает. Поэтому можно считать, что одна четвёрка байтов в utf-32 соответствует одному символу (раздел 2.5 пункт "fixed width")

S>Символ некоего алфавита не всегда имеет однозначное представление в виде code points, в частности, буква ё может быть представлена одним code point либо двумя (кириллическая е + две точки над ней).

S>Любая кодировка (в том числе и utf-32) задает правила конверсии между байтовой последовательностью и цепочкой натуральных чисел.
S>Таким образом, в зависимости от кодировки, та же буква ё может занимать от 1 до 8 байт.
Спасибо, я это знаю (кстати, почему до восьми? utf-8 — 2 байта, utf-16 — 2 байта, utf-32 — 4 байта. Неужели UTF-64?)
Но в контексте топика я не думаю, что имеет смысл расказывать весь стандарт, понятия о encoding forms (transfer functions) тут вполне достаточно.
Re[3]: utf8 -> string
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.08 08:23
Оценка:
Здравствуйте, neFormal, Вы писали:

F>Проверил, не utf32.

И как ты это проверял?
F>Коды символов, переданные по сети такие же, как если бы писать utf8 в файл. Разница только в дополнительных байтах.
Эти дополнительные байты и есть UTF-32.
Вот файл.
Он прекрасно читается вот такой программой:

static void Main(string[] args)
{
    using(FileStream fs = new FileStream(args[0], FileMode.Open, FileAccess.Read))
    {
        using(TextReader tr = new StreamReader(fs, Encoding.UTF32))
        {
                Console.Write(tr.ReadToEnd());
        }
    }
}
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: utf8 -> string
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.08 08:40
Оценка:
Здравствуйте, vmpire, Вы писали:
V>Спасибо, я это знаю (кстати, почему до восьми? utf-8 — 2 байта, utf-16 — 2 байта, utf-32 — 4 байта.
4 байта на code point. Буква != code point. Я же написал, что букву (графему) ё можно представить как два код-поинта.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[3]: utf8 -> string
От: vmpire Россия  
Дата: 21.10.08 08:42
Оценка:
Здравствуйте, neFormal, Вы писали:

F>Проверил, не utf32.

F>Коды символов, переданные по сети такие же, как если бы писать utf8 в файл. Разница только в дополнительных байтах.
Тогда это какая-то своя кодировка, её нужно разбирать руками. Можно написать свой потомок класса Encoding, а там обрезать лишние нули и вызывать utf-8.
Только проверьте сначала, что это именно utf-8, передавая не латинские символы.
Re[7]: utf8 -> string
От: vmpire Россия  
Дата: 21.10.08 08:52
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Здравствуйте, vmpire, Вы писали:

V>>Спасибо, я это знаю (кстати, почему до восьми? utf-8 — 2 байта, utf-16 — 2 байта, utf-32 — 4 байта.
S>4 байта на code point. Буква != code point. Я же написал, что букву (графему) ё можно представить как два код-поинта.
А, точно, не обратил внимания что речь идёт именно о букве, извините
Re[4]: utf8 -> string
От: neFormal Россия  
Дата: 21.10.08 09:27
Оценка:
Здравствуйте, Sinclair, Вы писали:

F>>Проверил, не utf32.

S>И как ты это проверял?

Encoding.UTF32.GetString()?. Не?.
Передал массив байт, получил иероглифы. Где я ошибся?.

F>>Коды символов, переданные по сети такие же, как если бы писать utf8 в файл. Разница только в дополнительных байтах.

S>Эти дополнительные байты и есть UTF-32.
S>Вот файл.
S>Он прекрасно читается вот такой программой:

А gedit(стандартный редактор в Gnome) говорит:

Could not open the file /tmp/utf32.txt using the Unicode (UTF-32) character coding.



Вопрос в топик:
Как можно в плюсах указать использование utf8, если у кодировки плавающий размер?. Имхо использование размера "с запасом" как минимум логично..
Какие еще могут быть варианты?.
...coding for chaos...
Re[4]: utf8 -> string
От: neFormal Россия  
Дата: 21.10.08 09:30
Оценка:
Здравствуйте, vmpire, Вы писали:

V>Только проверьте сначала, что это именно utf-8, передавая не латинские символы.


Проверяли вроде, русские символы занимают 2 байта вместо одного.
Т.е. выглядит как:
['П', 0, 0, 'р', 0, 0, 'и', 0, 0, 'в', 0, 0, 'е', 0, 0, 'т']
...coding for chaos...
Re[5]: utf8 -> string
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.08 09:44
Оценка:
Здравствуйте, neFormal, Вы писали:
F>Encoding.UTF32.GetString()?. Не?.
F>Передал массив байт, получил иероглифы. Где я ошибся?.
Не знаю. Ты пока не привел пример строки, из которой ты получил иероглифы. Твой Hello прекасно прочитался, я тебе пример дал. Ты по какой-то непонятной мне причине отказываешься приводить примеры реального кода и реальных данных. Нам остается только телепатически гадать, где именно ты ошибся.

F>

Надо полагать, гном глючит. Ты на чем программируешь — на гноме или на дотнете?

F>Вопрос в топик:

F>Как можно в плюсах указать использование utf8, если у кодировки плавающий размер?.
Гм. Наверное, точно так же. Нужно просто понимать, что "строка" и "строка в кодировке" — это не муж и жена, а четыре разных человека.
Строка — это цепочка символов, строка в кодировке — цепочка байт.
F>Имхо использование размера "с запасом" как минимум логично..
F>Какие еще могут быть варианты?.
Варианты могут быть любые. Самый логичный — хранить строки в программе в формате, удобном для манипуляций, а передавать — в формате, удобном для передачи. UCS-2 и UCS-4 удобны тем, что к ним легко обращаться по индексу. (UTF16LE применяют редко, потому что в нем не все code points занимают 2 байта). UTF-8 удобен тем, что для латиницы хватает одного байта на букву. Не бывает одного тру енкодинга на все случаи жизни.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: utf8 -> string
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.08 09:44
Оценка:
Здравствуйте, neFormal, Вы писали:
F>Проверяли вроде, русские символы занимают 2 байта вместо одного.
F>Т.е. выглядит как:
F>['П', 0, 0, 'р', 0, 0, 'и', 0, 0, 'в', 0, 0, 'е', 0, 0, 'т']
Ничего не понятно. Приведите шестнадцатеричное представление байтового массива. У вас получилось 16 элементов массива на 6 букв. Это какой-то бред.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: utf8 -> string
От: neFormal Россия  
Дата: 21.10.08 09:58
Оценка:
Здравствуйте, Sinclair, Вы писали:

F>>Проверяли вроде, русские символы занимают 2 байта вместо одного.

F>>Т.е. выглядит как:
F>>['П', 0, 0, 'р', 0, 0, 'и', 0, 0, 'в', 0, 0, 'е', 0, 0, 'т']
S>Ничего не понятно. Приведите шестнадцатеричное представление байтового массива. У вас получилось 16 элементов массива на 6 букв. Это какой-то бред.

ступил.. после 'т' тоже два нуля..
...coding for chaos...
Re[6]: utf8 -> string
От: neFormal Россия  
Дата: 21.10.08 10:03
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Надо полагать, гном глючит. Ты на чем программируешь — на гноме или на дотнете?


Под гномом — сервер, под дотнетом — клиент.
К примеру, файлик в utf8 одинаково корректно читается и gedit-ом, и notepad-ом и тестовой программкой на .net-е.

S>Ты по какой-то непонятной мне причине отказываешься приводить примеры реального кода и реальных данных. Нам остается только телепатически гадать, где именно ты ошибся.


Извиняюсь, кода под рукой нет, чуть позже отпишусь снова, покажу конкретные примеры, когда сам у автора их заберу.
...coding for chaos...
Re[7]: utf8 -> string
От: Sinclair Россия https://github.com/evilguest/
Дата: 21.10.08 10:24
Оценка:
Здравствуйте, neFormal, Вы писали:
F>ступил.. после 'т' тоже два нуля..
И что? Три байта на символ???
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.