您可以使用以下函数将文件内容读入char
数组:
void readFileContentsIntoCharArray(char* charArray, size_t sizeOfArray) {
std::ifstream inputFileStream;
inputFileStream.read(charArray, sizeOfArray);
}
现在文件是用UTF-16LE编写的,所以我想将文件的内容读入char16_t
数组,以便以后更容易处理。我尝试了以下代码。
void readUTF16FileContentsIntoChar16Array(char16_t* char16Array, size_t sizeOfArray) {
std::ifstream inputFileStream;
inputFileStream.read(char16Array, sizeOfArray);
}
当然它没有用。 std::ifstream
不接受char16_t
。我一直在寻找解决方案很长一段时间,但到目前为止我发现的唯一相关的是https://stackoverflow.com/a/10504278/1031769,这没有用,因为它使用wchar_t
而不是char16_t
。
如何使它与char16_t
一起使用?
您可以将字节读入char16_t
数组,然后手动转换字节顺序(不同的体系结构以不同的内存顺序存储宽字符)。
为此,您必须能够检测正在运行的计算机的字节顺序。
我在本例中使用它,但您可能希望使用具有可移植编译时检查的正确库版本:
bool is_little_endian()
{
char16_t const c = 0x0001;
return *reinterpret_cast<char const*>(&c);
}
然后你可以这样做:
std::u16string read_utf16le(std::string const& filename)
{
// open at end to get size.
std::ifstream ifs(filename, std::ios::binary|std::ios::ate);
if(!ifs)
throw std::runtime_error(std::strerror(errno));
auto end = ifs.tellg();
ifs.seekg(0, std::ios::beg);
auto size = std::size_t(end - ifs.tellg());
if(size % 2)
throw std::runtime_error("bad utf16 format (odd number of bytes)");
std::u16string u16;
u16.resize(size / 2);
if(u16.empty())
throw std::runtime_error("empty file");
if(!ifs.read((char*)&u16[0], size))
throw std::runtime_error("error reading file");
if(!is_little_endian())
{
// convert from big endian (swap bytes)
std::transform(std::begin(u16), std::end(u16), std::begin(u16), [](char16_t c){
auto p = reinterpret_cast<char*>(&c);
std::swap(p[0], p[1]);
return c;
});
}
return u16;
}
我已经创建了一个示例UTF-16LE
文件,这段代码能够正确读取它。你可以尝试一下:
std::string readUTF16(const char* filename) {
std::wifstream file(filename, std::ios::binary);
file.imbue(std::locale(file.getloc(), new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>));
std::wstring ws;
for(wchar_t c; file.get(c); ) {
ws += (char16_t) c;
}
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.to_bytes(ws);
}