Чтение и запись файлов на кириллице в с ++ - PullRequest
1 голос
/ 23 сентября 2011

Я должен сначала прочитать файл на кириллице, затем случайным образом выбрать случайное количество строк и записать измененный текст в другой файл.Нет проблем с латинскими буквами, но я сталкиваюсь с проблемой с текстом на кириллице, потому что я получаю немного мусора.Вот как я пытался это сделать.

Скажем, файл 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 ]

2 голосов
/ 23 сентября 2011

Поскольку вы видели что-то вроде: ■ aaaaaaa 1 ♦ 1 ♦ 1 ♦ 1 ♦ 1 ♦ 1 ♦ 1 ♦ 2 ♦ 2 ♦ 2 ♦ 2 ♦ 2 ♦ 2 ♦ 2 ♦ выводится на консоль, кажется, чтозакодирован в кодировке 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 , определенного параметромвведите параметр Элем .Это означает, что строка 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 (обычно).

1 голос
/ 23 сентября 2011

Почему вы используете 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.
...