【问题标题】:Reading and writing files in Cyrillic in c++在 C++ 中以 Cyrillic 读写文件
【发布时间】:2011-11-23 05:23:22
【问题描述】:

我必须先读取西里尔文的文件,然后随机选择随机行数并将修改后的文本写入不同的文件。拉丁字母没有问题,但我遇到了西里尔文字的问题,因为我得到了一些垃圾。所以这就是我尝试做的事情。

说,文件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();

那么我怎样才能使用 Cyrillic 来生成可读的东西,而不仅仅是符号呢?

【问题讨论】:

  • readable things, not just symbols? 是什么意思 result.txt 是什么样的,您想要它是什么样的?
  • 我想得到 аааааавввввввв 的东西,但是得到 2A =04 ?@> (那样的东西)。我不知道如何阅读西里尔文,以及如何写回西里尔文。
  • 文件的编码是什么?
  • 我使用 Unicode 进行文件编码。也试过 _setmode(_fileno(stdout), _O_U16TEXT); - 适用于控制台输出,但我仍然在文件中得到垃圾。
  • 您在 Windows 上吗?打开resultStream 后,在输出result 之前尝试resultStream.write("\xFEFF", 4);resultStream.write("\xFFFE", 4); 行,看看你得到了什么。

标签: c++ file input wofstream wifstream


【解决方案1】:

因为您看到类似■aaaaaaa 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 的原因是,无论文件流的 char 类型如何,basic_fstream 的底层 basic_filebuf 使用 codecvt 对象将 char 对象流转换为/从char 类型的对象流;即在读取时,从文件中读取的char 流转换为wchar_t 流,但在写入时,wchar_t 流转换为char 流,然后写入文件。对于std::wifstreamcodecvt 对象是标准std::codecvt&lt;wchar_t, char, mbstate_t&gt; 的一个实例,它通常将UTF-8 转换为UCS-16。

the MSDN documentation page for basic_filebuf 中所述:

basic_filebuf 类型的对象是使用 char * 类型的内部缓冲区创建的,而与类型参数 Elem 指定的 char_type 无关。这意味着 Unicode 字符串(包含 wchar_t 字符)将在写入内部缓冲区之前转换为 ANSI 字符串(包含 char 字符)。

同样,在读取 Unicode 字符串(包含 wchar_t 字符)时,basic_filebuf 将从文件中读取的 ANSI 字符串转换为返回给 getlinewchar_t 字符串和其他读取操作。

如果您将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(通常)。

【讨论】:

  • 现在就像一个魅力!感谢您的帮助和 MSDN 链接!
【解决方案2】:

你为什么要使用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.

【讨论】:

  • 试图以这种方式读取文件,然后输出到控制台如下所示: ■aaaaaaa 1♦1♦1♦1♦1♦1♦1♦ 2♦2♦2♦2♦2 ♦2♦2♦
  • 确保您的环境设置为与文件编码对应的正确语言环境,并且您的终端支持所需的字符集。
猜你喜欢
  • 2015-07-31
  • 2014-05-09
  • 2012-06-23
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多