C++ 如何读取文件';将内容放入C+中的char16#t数组中+;?

C++ 如何读取文件';将内容放入C+中的char16#t数组中+;?,c++,C++,您可以使用以下功能将文件内容读入char数组: void readFileContentsIntoCharArray(char* charArray, size_t sizeOfArray) { std::ifstream inputFileStream; inputFileStream.read(charArray, sizeOfArray); } 现在文件是用UTF-16LE编写的,因此我想将文件内容读入char16\t数组,以便以后更容易地处理它。我尝试了以下代码 voi

您可以使用以下功能将文件内容读入
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);
}
当然没用了<代码>标准::ifstream不接受
char16\u t
。我一直在寻找解决方案,但到目前为止,我找到的唯一相关解决方案是,它没有帮助,因为它使用
wchar\t
而不是
char16\t


如何使用
char16\u t

我创建了一个示例
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);
}
std::string readUTF16(常量字符*文件名){
std::wifstream文件(文件名,std::ios::binary);
imbue(std::locale(file.getloc(),新std::codecvt_utf16));
std::wstring-ws;
for(wchar_t c;file.get(c);){
ws+=(char16_t)c;
}
std::wstring_转换器;
将转换器返回到_字节(ws);
}

您可以将字节读入
char16\t
数组,然后手动转换尾数(不同的体系结构以不同的内存顺序存储宽字符)

要做到这一点,你必须能够检测到你正在运行的机器的末端

我在本例中使用此选项,但您可能希望使用具有可移植编译时检查的适当库版本:

bool is_little_endian()
{
    char16_t const c = 0x0001;
    return *reinterpret_cast<char const*>(&c);
}
bool是_little_endian()
{
char16_t const c=0x0001;
返回*重新解释铸件(&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;
}
std::u16字符串读取(std::字符串常量和文件名)
{
//在末端打开以获得尺寸。
std::ifstream ifs(文件名,std::ios::binary | std::ios::ate);
如果(!ifs)
抛出std::runtime_错误(std::strerror(errno));
自动结束=ifs.tellg();
如果seekg(0,标准::ios::beg);
auto size=std::size_t(end-ifs.tellg());
如果(大小%2)
抛出std::runtime_错误(“错误的utf16格式(奇数字节)”;
std::u16字符串u16;
u16.调整大小(大小/2);
if(u16.empty())
抛出std::runtime_错误(“空文件”);
if(!ifs.read((char*)&u16[0],size))
抛出std::runtime_错误(“错误读取文件”);
如果(!is_little_endian())
{
//从big-endian转换(交换字节)
std::transform(std::begin(u16),std::end(u16),std::begin(u16),[](char16\u t c){
自动p=重新解释铸件(&c);
std::swap(p[0],p[1]);
返回c;
});
}
返回u16;
}

您可以读取
2*sizeOfArray
字节,然后手动将每个2
char
转换为
char16\t
。。。。。如果体系结构是big-endian,你就不能做得更好,如果是little-endian,你可以做一些指针转换。“该文件是用UTF-16LE编写的,”只需在使用say
iconv
之前对其进行转码,并告诉制作它的人,请立即停止,并使用UTF-8。“std::ifstream不接受char16\t”您应该将输入数组强制转换为
char*
。它在具有代理项对的Linux/macOS上不起作用,它将trunc代理项对并仅保留其一个字节。