Чтение и запись файлов на кириллице в с ++
Я должен сначала прочитать файл на кириллице, затем случайным образом выбрать случайное количество строк и записать измененный текст в другой файл. Нет проблем с латинскими буквами, но я сталкиваюсь с проблемой с текстом на кириллице, потому что получаю мусор. Вот как я пытался это сделать.
Скажи, файл input.txt
является
ааааааа
ббббббб
ввввввв
Я должен прочитать это и поместить каждую строку в вектор:
vector<wstring> inputVector;
wstring inputString, result;
wifstream inputStream;
inputStream.open("input.txt");
while(!inputStream.eof())
{
getline(inputStream, inputString);
inputVector.push_back(inputString);
}
inputStream.close();
srand(time(NULL));
int numLines = rand() % inputVector.size();
for(int i = 0; i < numLines; i++)
{
int randomLine = rand() % inputVector.size();
result += inputVector[randomLine];
}
wofstream resultStream;
resultStream.open("result.txt");
resultStream << result;
resultStream.close();
Итак, как я могу работать с кириллицей, чтобы она производила читаемые вещи, а не только символы?
2 ответа
Поскольку вы увидели что-то вроде ■a a a a a a a 1♦1♦1♦1♦1♦1♦1♦ 2♦2♦2♦2♦2♦2♦2♦, напечатанное на консоли, кажется, что input.txt
кодируется в кодировке UTF-16, вероятно, UTF-16 LE + BOM. Вы можете использовать свой оригинальный код, если измените кодировку файла на UTF-8.
Причиной использования UTF-8 является то, что независимо от типа символа потока файла, basic_fstream
в основе basic_filebuf
использует codecvt
объект для преобразования потока char
объекты в / из потока объектов типа char; т.е. при чтении char
Поток, который читается из файла, преобразуется в wchar_t
поток, но при написании wchar_t
поток преобразуется в char
поток, который затем записывается в файл. В случае std::wifstream
, codecvt
объект является экземпляром стандарта std::codecvt<wchar_t, char, mbstate_t>
, который обычно преобразует UTF-8 в UCS-16.
Как объяснено на странице документации MSDN дляbasic_filebuf
:
Объекты типа basic_filebuf создаются с внутренним буфером типа char * независимо от типа char_type, указанного параметром типа Elem. Это означает, что строка Unicode (содержащая символы wchar_t) будет преобразована в строку ANSI (содержащую символы char) перед ее записью во внутренний буфер.
Аналогично, при чтении строки Unicode (содержащей wchar_t
персонажи), basic_filebuf
преобразует строку ANSI, прочитанную из файла, в wchar_t
строка возвращается getline
и другие операции чтения.
Если вы измените кодировку input.txt
до UTF-8, ваша оригинальная программа должна работать правильно.
Для справки, это работает для меня:
#include <cstdlib>
#include <ctime>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
int main()
{
using namespace std;
vector<wstring> inputVector;
wstring inputString, result;
wifstream inputStream;
inputStream.open("input.txt");
while(!inputStream.eof())
{
getline(inputStream, inputString);
inputVector.push_back(inputString);
}
inputStream.close();
srand(time(NULL));
int numLines = rand() % inputVector.size();
for(int i = 0; i < numLines; i++)
{
int randomLine = rand() % inputVector.size();
result += inputVector[randomLine];
}
wofstream resultStream;
resultStream.open("result.txt");
resultStream << result;
resultStream.close();
return EXIT_SUCCESS;
}
Обратите внимание, что кодировка result.txt
также будет UTF-8 (в общем).
Почему вы используете wifstream
- уверены ли вы, что ваш файл состоит из последовательности (зависящих от системы) широких символов? Почти наверняка это не так. (В частности, потому что широкий набор символов системы на самом деле не определен вне рамок программы на C++).
Вместо этого просто прочитайте входной поток байтов, как он есть, и отобразите его соответствующим образом:
std::ifstream infile(thefile);
std::string line;
std::vector<std::string> input;
while (std::getline(infile, line)) // like this!!
{
input.push_back(line);
}
// etc.