将 Unicode 字符串写入文件

Write Unicode strings into a file

本文关键字:文件 字符串 Unicode      更新时间:2023-10-16

我正在尝试计算一个读取和写入文件的类。 对于字符串,有两种方法:ANSI和Unicode。ANSI 函数没问题,但我的 Unicode 函数有问题。

的意思是,我可以直接阅读 Unicode 文件,而无需检查或跳过"0xFEFF"内容,这有点连线。 无论我使用哪种语言,它都可以工作(我尝试过英语,中文和日语(。 有什么我应该知道的吗?

然后最大的问题跳了出来:将Unicode字符串写入文件。 首先,我尝试了没有""字符的简单英语字母表,它确实效果很好。 然后我把''推入,事情开始出错:输出插入了许多空格,如"a b c d e f g h i j k l m n o p q r s t u v w x y z " (''工作但这么多空格(,文件又是 ANSI。不要问其他语言的字符,我什至根本看不懂。

所以这里有一个问题:我应该怎么做才能正确地将 Unicode 字符串写入文件以及如何? 请不要提及"_wopen"功能,该文件已经使用"fopen"功能打开。

答案和建议将不胜感激。

我使用的是Windows 7和Visual Studio。

编辑:它适用于具有以下代码的非英语字符,但仍然错误为""。

char* cStart = "xffxfe";
if (::ftell(m_pFile) == 0)
    ::fwrite(cStart, sizeof(wchar_t), 1, m_pFile);

但这是如何工作的呢?我的意思是我在阅读文件时没有看到它。

编辑:我代码的一部分。

void File::ReadWText(wchar_t* pString, uint32 uLength)
{
    wchar_t cLetter = L'';
    uint32 uIndex = 0;
    do {
        cLetter = L'';
        ::fread(&cLetter, sizeof(wchar_t), 1, m_pFile);
        pString[uIndex] = cLetter;
    }while (cLetter != L'' && !::feof(m_pFile) && uIndex++ < uLength);
    pString[uIndex] = L'';
}
void File::WriteWText(wchar_t* pString, uint32 uLength)
{
    char* pStart = "xffxfe";
    if (::ftell(m_pFile) == 0)
        ::fwrite(pStart, sizeof(wchar_t), 1, m_pFile);
    m_uSize += sizeof(wchar_t) * ::fwrite(pString, sizeof(wchar_t), uLength, m_pFile);
}
void main()
{
    ::File* pFile = new File();
    wchar_t* pWString = L"abcdefgnhijklmnnopqrstnuvwxyz";
    pFile->Open("TextW.txt", File::Output);
    // fopen("TextW.txt", "w");
    pFile->WriteWText(pWString, ::wcslen(pWString));
    pFile->Close();
}

输出文件的内容是:"abcdefg਍栀椀樀榀氀洀渀ഀopqrst਍甀瘀眀眀礀稀",文件是Unicode。

我不知道这是否是"L'"的正确表达,我以前从未使用过Unicode。感谢您帮助我:)

我刚刚注意到这个问题被标记为 C 和 C++:下面讨论的是C++的情况。它完全忽略了 的使用,我不知道如何处理使用的不同编码。

读取或写入文件时,您需要告诉系统文件的编码是什么,以便它可以在读取时将文件中的字节转换为程序内部的字符,并在写入时将字符转换为字节。在许多情况下,这种转换被完全忽略,因为从字节到字符的转换是标识:字节可以解释为字符,反之亦然。当外部编码为 ASCII 时也是如此(我假设在您的问题中这被称为"ANSI"(。

假装 UTF-8 编码的文件使用标识转换从字节转换为字符可以进行某些扩展。C++ 中内部字符表示的最初愿景是每个字符有一个单元,例如charwchar_t。尽管 Unicode 已经设定了一组可以很好地与之配合的目标(例如,每个字符由一个单位表示,单位大小为 16 位(,但他们觉得牺牲了他们所有最初的目标,我们最终得到了一个系统,其中一个字符(嗯,我认为它们实际上被称为"代码点",但我不是 Unicode 专家(可以由多个单词组成(例如,当使用组合字符时(。无论如何,只要单个单元不在不注意字符的情况下发生突变,通常可以将 UTF-8 处理为char序列(例如作为std::string(,将 UTF-16 处理为wchar_t序列(例如作为std::wstring(。但是,当读取与 UTF-8(或 ASCII,它是 UTF-8 的子集(不同的内容时,您需要小心设置流,以便它知道使用了哪种编码。

设置文件流以了解特定编码的标准方法是创建一个合适的std::locale,其中包含使用其特定编码在外部字节和内部字符之间进行转换的相应std::codecvt<...>分面。如何实际获得相应的std::locale取决于各个实现。默认转换旨在假装程序使用 ASCII 的扩展名,该扩展名涵盖了 char 的所有值。在读取和写入 UTF-8 时,这应该可以正常工作。

我不确定你所说的"编写 Unicode 字符串"是什么意思,但从外观上看,你是在编写一个没有设置编码的std::wstring

使用来源回答编辑的问题:

void File::ReadWText(wchar_t* pString, uint32 uLength)是越野车。如果uLength是数组的大小(wchar_t string[size](

while (.... && uIndex++ < uLength);应该while (.... && (++uIndex)+1 < uLength);

否则pString[uIndex] = L'';可能会溢出!

新线问题.. L"abcdefgnhijklmnnopqrstnuvwxyz";Windows 使用rn作为换行符。 L"abcdefgrnhijklmnrnopqrstrnuvwxyz";应该有效。

基于这个 msdn 线程 unicode 换行符问题和你的// fopen("TextW.txt", "w");,我相信你必须用"wb"打开你的文件!否则n将自动扩展到rn这会搞砸您的 unicode 编码。

嗯,

这可能会有所帮助。

不要忘记在开头写 BOM FF FE.

因为你没有发布任何代码..我相信您将新行写为 ASCII 'n'(如您的问题中所写(

对于新行,您需要写0D 00 0A 00

或者如果要使用 'n' ,则必须将其强制转换为(short)'n'