在尝试从this answer读取带有提示的UTF-16编码文件时,我遇到的问题是,在读取几千个字符后,getline
方法开始在垃圾mojibake中读取。 / p>
这是我的主要爱好:
#include <cstdio>
#include <fstream>
#include <iostream>
#include <codecvt>
#include <locale>
int main(void) {
std::wifstream wif("test.txt", std::ios::binary);
setlocale(LC_ALL, "en_US.utf8");
if (wif.is_open())
{
wif.imbue(
std::locale(
wif.getloc(),
new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>
)
);
std::wstring wline;
while (std::getline(wif, wline))
{
std::wcout << wline;
}
wif.close();
}
return 0;
}
test.txt
文件包含FF
,FE
字节顺序标记,后跟100行,每行80个'a'
。这是一个在* nix上生成test.txt
的bash脚本:
#!/bin/bash
echo -n -e \\xFF\\xFE > test.txt
for i in $(seq 1 100)
do
for i in $(seq 1 80)
do
echo -n -e \\x61\\x00 >> test.txt
done
echo -n -e \\x0A\\x00 >> test.txt
done
这是我编译和运行main的方式:
g++-8 -std=c++17 -g main.cpp -o m && ./m
我的期望:打印了8000 'a'
个
实际发生的情况:
在打印了几千个a
之后,输出变为以下垃圾:
aaaaaaaaaa愀愀愀愀愀愀愀愀愀愀
,偶尔还有不可打印的字符,它们看起来像0A00
的矩形。
愀
字符的二进制代码点值为110000100000000
,因此看起来像a
字节,后跟0
字节。
似乎在读取期间丢失了一些字节,从那时起,所有内容都未对齐,并且所有其余符号均被错误地解码。或者,因为输出以0A00
-thingie结尾,所以可能是在读取数千个a
之后,字节序反转了,但是这种行为也毫无意义。
为什么会发生这种情况,最简单的解决方法是什么?
答案 0 :(得分:1)
一种简单的解决方法(但不是通用解决方案)
如果您确定输入文件具有特定的字节序,则可以简单地对字节序as shown in the example in the documentation进行硬编码:
wif.imbue(
std::locale(
wif.getloc(),
new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>
)
);
使用硬编码的std::little_endian
,问题似乎消失了,并且可以正确读取文件。字节序相反的文件可能无法使用。