Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"? / 13 сообщений из 13, страница 1 из 1
17.05.2016, 22:05
    #39237781
BagaBaga
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
Пишу простенький код
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
using namespace std;
    setlocale(LC_ALL, "ru_RU.UTF-8");
    vector<string> v{"русский", "язык"};

    ofstream of;
    of.open("c:/temp/test_ru.html");
    of << "<HTML>";
    for(const auto &e : v ){
        of << e << "<br/>" << endl;
        for(const auto ch : e){
            of << '[' << ch << ']' << endl;
        }
    }
    of << "</HTML>";


вместо ожидаемого вывода
русский
[р]
[у]
[с]
...
получаю
русский
[?]
[?]
[?]

Среда разработки - QT Creator под Win7. Кодировка исходника - UTF8. Кодировка выходного файла (как установил) - UTF8. Получается, т.к. std::string ничего о UTF не знает, при выводе строки целиком "магическим образом" происходит преобразование в UFT8, а вот при выводе "по символу" такого преобразования не происходит...

Как можно весь текст привести к одной локали?
...
Рейтинг: 0 / 0
18.05.2016, 01:33
    #39237816
egorych
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
BagaBaga,
wstring, L"русский", не?
...
Рейтинг: 0 / 0
18.05.2016, 08:02
    #39237849
YesSql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
в UTF-8 кирилица двухбайтная .
...
Рейтинг: 0 / 0
18.05.2016, 08:05
    #39237850
YesSql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
egorychBagaBaga,
wstring, L"русский", не?

Нет. он кирилицу UTF-8 разворачивает побайтно.
...
Рейтинг: 0 / 0
18.05.2016, 09:36
    #39237910
egorych
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
YesSqlegorychBagaBaga,
wstring, L"русский", не?Нет. он кирилицу UTF-8 разворачивает побайтно.ну. а разве строка из двухбайтных символов не спасёт ОРД?
...
Рейтинг: 0 / 0
18.05.2016, 09:52
    #39237943
YesSql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
egorychYesSqlпропущено...
Нет. он кирилицу UTF-8 разворачивает побайтно.ну. а разве строка из двухбайтных символов не спасёт ОРД?
Он все делает в UTF-8 и его IDE тоже.

вот это
Код: plaintext
1.
2.
std::string v("это моя строка");
std::cout << v.size() << std::endl;


даст результат 26
...
Рейтинг: 0 / 0
18.05.2016, 13:31
    #39238202
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
очень странно, все мои исходники лежает в utf8 и не жалуются.

думаю проблема в том, что то, чем потом открывается файл не понимает, что этот файл в utf8 - может быть задать там кодировку в мета (если я правильно понимаю, то это ведь html файл, да?)..=

как работает std::cout ? тоже крокозябры показвыает?

и кстати вопрос, исходник правда в utf8 или только локаль такая стоит ,а исходник в cp1251 на самом деле?
...
Рейтинг: 0 / 0
18.05.2016, 13:36
    #39238205
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
ой, извиняюсь, в тему не вник...
ответ уже дали :)
...
Рейтинг: 0 / 0
18.05.2016, 14:46
    #39238305
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
BagaBaga,


там надо кодеки задавать для файла. для QT шного. Или самому из QSTring преобразовывать.
В общем, все сложно...
...
Рейтинг: 0 / 0
18.05.2016, 19:21
    #39238583
BagaBaga
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
Ок, чудес не бывает. А так хотелось.
После нескольких экспериментов и раздумий, пришел к выводу, что причина такая:

IDE действительно "хранит" русский код в UTF8 - установить это "без проблем".
std::string знать ничего не знает о многобайтовых кодировках. В результате код
Код: plaintext
1.
vector<string> v{"русский", "язык"}


создаст вектор строк, каждая из которых будет инициализирована по-байтно... в конце концов, кто сказал, что все символы должны быть печатными ("видимыми")?
При этом код
Код: plaintext
1.
2.
3.
for(const auto &e : v ){
        of << e << "<br/>" << endl;
...


просто "выплюнет" сохранённый массив байт. И любой редактор прочтёт его как валидный UTF8 текст... ведь эти байты - и есть последовательность байт, представляющих строку в UTF8...
Тогда вот этот код
Код: plaintext
1.
2.
3.
4.
5.
for(const auto &e : v ){
        for(const auto ch : e){
            of << '[' << ch << ']' << endl;
        }
    }


отработает "в лоб". Будет извлекать по байту и "выплёвывать" их в обрамлении скобочек. При этом, понятное дело, многобайтовое представление символа будет "порвана" на байты, и какие "этим байтам" будут соответствовать значки ... как повезёт, в общем.

Решения? Можно попробовать новый литерал u8 (пока не пробовал - мой компилятор не поддерживает). Или "загонять" в QString и преобразовывать из неё... Или использовать ICU. Или другую либу. Или собтвенный велосипед в стиле UTF8_2_MyLocale...
...
Рейтинг: 0 / 0
18.05.2016, 20:32
    #39238612
YesSql
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
или воспользоваться
Код: plaintext
1.
std::mblen(...)
...
Рейтинг: 0 / 0
20.05.2016, 04:38
    #39239632
Пётр Седов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
BagaBaga, в кодировке UTF-8, слово «русский» кодируется следующей последовательностью байтов:
209, 128, 209, 131, 209, 129, 209, 129, 208, 186, 208, 184, 208, 185
То есть каждая русская буква кодируется двумя байтами. Поэтому вместо кода:
BagaBaga
Код: plaintext
1.
2.
3.
        for(const auto ch : e){
            of << '[' << ch << ']' << endl;
        }

попробуйте так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
// разбиваем строку на символы
size_t char_pos = 0;
while (char_pos < e.length()) {
  size_t char_len = utf8_char_len(e, char_pos);
  of << '[' << e.substr(char_pos, char_len).c_str() << ']' << endl;
  char_pos += char_len;
}

где функция utf8_char_len возвращает сколько байт занимает символ в кодировке UTF-8:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
#include <assert.h>

typedef unsigned char byte_t;

size_t utf8_char_len(const string& s, size_t char_pos) {
  byte_t e = s[char_pos];
  if (e <= 127) return 1; // если e вида 0xxxxxxx
  assert(e >= 192);
  if (e <= 223) return 2; // если e вида 110xxxxx
  if (e <= 239) return 3; // если e вида 1110xxxx
  if (e <= 247) return 4; // если e вида 11110xxx
  if (e <= 251) return 5; // если e вида 111110xx
  if (e <= 253) return 6; // если e вида 1111110x
  assert(false);
  return 0;
}
...
Рейтинг: 0 / 0
20.05.2016, 11:45
    #39239857
alexy_black
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"?
http://www.boost.org/doc/libs/1_61_0/libs/locale/doc/html/boundary_analysys.html (boost.org/libs/locale)

или перевести utf8 to utf16
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Qt-ofstream-и-UTF8 в локали - как убрать "кракозябры"? / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]