#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(); }
Комментариев нет:
Отправить комментарий