c++ 在Windows上使用MSVC将“\n”重新解释为UTF16

j2qf4p5b  于 2023-10-21  发布在  Windows
关注(0)|答案(1)|浏览(126)

我试图写一个简单的程序,将大的txt文件划分为较小的文件。这个问题开始于UTF16编码的文件。不管我怎么努力,例如。如果我们在UTF16 LE文件行结束为“0D 00 0A 00”,在除法之后它是“0D 00 0D 0A 00”,或者在UTF16 BE“00 0D 00 0A”的情况下,它变成“00 0D 00 0A”。这意味着每次无论如何我都要保存“0D 0A”字节。尝试了不同的方法,如下面的评论。我唯一的想法是在二进制模式下操作,不想使用std以外的其他库。任何线索都很感激。

std::wifstream winfile;
std::wofstream woutfile;
using namespace std;

int main()
{
    std::wstring line, temp;
    unsigned int limit;
    unsigned int part = 1;

    //(...)
    
    while (!winfile.eof()) {
        limit = 1000000;
        woutfile.open(save_path + std::to_string(part) + ".txt", std::ios::out | std::ios::app);
        limit--;
        while (limit > 0 && !winfile.eof()) {
            getline(winfile, temp);
            wchar_t lf[]{ L'\n'};
            woutfile << temp << lf;   
            /*
            wchar_t lf[]{ 0x00, 0x0D, 0x00, 0x0A};
            woutfile << temp << lf;
            
            woutfile << temp << L"\n";
            woutfile << temp << std::endl;
            */
            
            limit--;
        }
        part++;
        winfile.close();
        woutfile.close();
    }
    system("pause");
}
p4rjhz4m

p4rjhz4m1#

我们可以看到您的输出流是文本模式。听起来你的输入流是二进制模式的(或者是UTF-16的事实混淆了行尾的解释)。
对于二进制输入,您将同时读取回车符(CR)和换行符(LF)。
std::getline的默认换行符是'\n',它在几乎所有的实现中都是一个换行符。所以getline将回车符视为另一个字符,并在换行符处划分行。因此,结果字符串以回车符结束,您将其写回。然后在这一行之后写'\n',由于输出流是文本模式的,所以它被转换为CR+LF。因此,输出字符串以CR+CR+LF结束。
有几种方法可以处理这个问题:

  • 在文本模式下打开输入,如果有必要,按照@RemyLebeau在评论中的建议注入它。
  • 在二进制模式下执行所有操作。
  • 在将每一行发送到输出流时,保持所有内容不变,但跳过任何尾随回车。

相关问题