#cpp #linux #utf_8 #cpp11 #потоки_данных
А именно использую 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
Ответы
Ответ 1
Русские буквы в 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 пример.Ответ 2
Проверяйте вашу системную локаль и что именно содержится в файлах. Ибо всё прекрасно работает: 1: $ locale LANG=ru_RU.UTF-8 LANGUAGE= LC_CTYPE="ru_RU.UTF-8" LC_NUMERIC="ru_RU.UTF-8" LC_TIME="ru_RU.UTF-8" LC_COLLATE="ru_RU.UTF-8" LC_MONETARY="ru_RU.UTF-8" LC_MESSAGES="ru_RU.UTF-8" LC_PAPER="ru_RU.UTF-8" LC_NAME="ru_RU.UTF-8" LC_ADDRESS="ru_RU.UTF-8" LC_TELEPHONE="ru_RU.UTF-8" LC_MEASUREMENT="ru_RU.UTF-8" LC_IDENTIFICATION="ru_RU.UTF-8" LC_ALL= $ ls ф* ффф.текст $ cat ффф.текст ффф.результат $ ./a.out ффф.результат $ ls ф* ффф.результат ффф.текст 2: #include#include #include int main() { std::ifstream rfile; rfile.open( "ффф.текст" ); std::string line; getline(rfile, line); rfile.close(); std::cout << line << std::endl; std::ofstream wfile; wfile.open( line.c_str() ); wfile.close(); }
Комментариев нет:
Отправить комментарий