Страницы

Поиск по вопросам

пятница, 19 октября 2018 г.

Как стандартными способами c++11 записать файл в utf-8

А именно использую ofstream и в самом файле записывается русскими буками хорошо, а вот с названием документа проблемы. Что только не пробовал, название файла получается что-то вроде такого �.txt (неверная кодировка)

Может я не совсем правильно задал вопрос, мне нужно чтобы программа сохраняла txt файл с названиями аа.txt аб.txt ав.txt - ... - яя.txt
Кратко расскажу суть программы: Есть словарь слов, расположенный в алфавитном порядке, программа должна разбить этот словарь по 33*33 документам (Минус 3*32, нет слов начинающихся с ь,ы,ъ). Документ аб.txt будет иметь все слова начинающиеся с аб...
Запись в файлы корректная, единственное, что названия файлов неправильные
Вот моя функция main()
int main() { if (rfile.is_open()) { while (getline(rfile, line)) { string first, second; try { first = line[0]; second = line[1]; }catch (...) { continue; } if (first == " " || first == "." || first == "-" || first == "|" || first == "," || second == " " || second == "|" || second == "-" || second == "." || second == ",") continue; string wfilename = first + second + ".txt"; ofstream wfile; wfile.open(wdirectory + wfilename, ios_base::app); if (wfile.is_open()) wfile << line; wfile.close(); } rfile.close(); } else cout << "Unable to open file" << endl;
return 0; }
Система Linux mint x64

Решение найдено! Я брал первые две буквы строки и использовал их для составления названия. Чтобы все корректно работало, нужно было конвертировать исходный файл в utf-8. На linux эта команда выглядит как iconv -f windows-1251 < /home/user/filename.txt > /home/user/newEncodedFilename.txt Знаки < и > обязательны. Далее уже использовать новый файл. Спасибо sercxjo


Ответ

Русские буквы в utf-8 обычно занимают 2 байта. Выбирая первые два байта из строки вы скорее всего получите только одну русскую букву, но возможно если первый из них другой символ или длина utf-8-представления символа более 2 байт, некорректно прерывается последовательность utf-8 кодировки. Для первого байта последовательности (x&192)==192, для остальных (x&192)==128. По этим признакам можно вырезать первую и вторую буквы (точнее в первом байте указывается длина последовательности в единичной системе исчисления, но будем надеяться на правильность исходных данных). Таким образом, найти длину символа поможет функция:
int wlen(const string &x, int start) { if(x[start]==0) return 0; if((x[start]&192)!=192) return 1; int i=1; while((x[start+i]&192)==128) i++; return i; }
Теперь остаётся заменить получение первого и второго символов строки:
first = line.substr(0, wlen(line, 0)); second = line.substr(first.size(), wlen(line, first.size()));
Ну и далее можно добавить анализ, что first.size()==0 || second.size()==0
Из беседы в чате выяснилось, что исходный файл в кодировке windows-1251. Чтобы привести его в кодировку принятую в Linux Mint можно использовать команду iconv
iconv -f windows-1251 < исходный_файл > новый_файл
Если требуется включить перекодировку в саму программу, можно использовать libiconv пример

Комментариев нет:

Отправить комментарий