无法读取C中的UNICODE文本文件

无法读取C中的UNICODE文本文件,c,windows,file,file-io,unicode,C,Windows,File,File Io,Unicode,(我查看了以前的帖子,尝试了他们的建议,但没有效果。) 我正在尝试读取一个只包含日语字符的文件。下面是该文件的外观: わたし わ エドワド オ’ハゲン です。 これ は なん です か? 当我尝试读取它时,控制台中没有显示任何输出,调试时,读取缓冲区只是垃圾。下面是我用来读取文件的函数: wchar_t* ReadTextFileW(wchar_t* filePath, size_t numBytesToRead, size_t maxBufferSize, const wchar_t* mod

(我查看了以前的帖子,尝试了他们的建议,但没有效果。)

我正在尝试读取一个只包含日语字符的文件。下面是该文件的外观:

わたし わ エドワド オ’ハゲン です。 これ は なん です か?

当我尝试读取它时,控制台中没有显示任何输出,调试时,读取缓冲区只是垃圾。下面是我用来读取文件的函数:

wchar_t* ReadTextFileW(wchar_t* filePath, size_t numBytesToRead, size_t maxBufferSize, const wchar_t* mode, int seekOffset, int seekOrigin)
{
    size_t numItems = 0;
    size_t bufferSize = 0;
    wchar_t* buffer = NULL;
    FILE* file = NULL;

    //Ensure the filePath does NOT lead to a device.
    if (IsPathADevice(filePath) == false)
    {
        //0 indicates to read as much as possible (the max specified).
        if (numBytesToRead == 0)
        {
            numBytesToRead = maxBufferSize;
        }

        if (filePath != NULL && mode != NULL)
        {
            //Ensure there are no errors in opening the file.
            if (_wfopen_s(&file, filePath, mode) == 0)
            {
                //Set the cursor location (back to the beginning of the file by default).
                if (fseek(file, seekOffset, seekOrigin) != 0)
                {
                    //Error: Could not change file cursor position.
                    fclose(file);
                    return NULL;
                }

                //Calculate the size of the buffer in bytes.
                bufferSize = numBytesToRead * sizeof(wchar_t);

                //Create the buffer to store file data in.
                buffer = (wchar_t*)_aligned_malloc(bufferSize, BYTE_ALIGNMENT);

                //Ensure the buffer was allocated.
                if (buffer == NULL)
                {
                    //Error: Buffer could not be allocated.
                    fclose(file);
                    return NULL;
                }

                //Clear any garbage data in the buffer.
                memset(buffer, 0, bufferSize);

                //Read the data from the file.
                numItems = fread_s(buffer, bufferSize, sizeof(wchar_t), numBytesToRead, file);

                //Check for read errors.
                if (numItems <= 0)
                {
                    //Error: File could not be read.
                    fclose(file);
                    _aligned_free(buffer);
                    return NULL;
                }

                //Ensure the file is closed without errors.
                if (fclose(file) != 0)
                {
                    //Error: File did not close properly.
                    _aligned_free(buffer);
                    return NULL;
                }

            }
        }
    }

    return buffer;
}
我还在.cpp的顶部定义了以下内容

#define UNICODE
#define _UNICODE
已解决:

要解决这个问题,正如Ryker提到的,您需要知道用于创建原始文件的编码。在记事本和记事本++中,有一个用于编码的下拉菜单。默认情况下(以及最常用的)是UTF-8

了解编码后,可以将wfopen_s()的读取模式更改为以下方式

wchar_t* retVal = ReadWide::ReadTextFileW(L"C:\\jap.txt", 0, 1024, L"r, ccs=UTF-8");
MessageBoxW(NULL, retVal, NULL, 0);
_aligned_free(retVal);

您必须使用消息框打印外来字符。

您读取了文件内容,并基本上将其复制到分配的内存缓冲区中

但一个关键点是:在文件中存储日文文本时使用了什么编码

例如,如果文本以UTF-8编码,则应将UTF-8转换为UTF-16(例如使用MultiByteToWideChar Win32 API),因为内存中似乎有一个wchar_t缓冲区

如果您使用的是Visual Studio的最新版本,还可以传递给_wfopen_s(使用
ccs
标志)

编辑由于您使用printf打印读取缓冲区的内容,请确保缓冲区以NUL结尾。

这是一个使用记事本++创建的缓冲区(在注释中说明为OP使用)

双字节编码,按用法也称为双字节字符 集合(DBCS)

其中一些是预先存在的Unicode,设计用于编码字符 具有大量字符的集合,主要出现在远东地区 具有表意文字或音节文字的语言:

The 2 Bytes Universal Character Set : UCS-2 Big Endian and UCS-2 Little Endian
The Japanese Code Page : Shift-JIS ( Windows-932 )
The Chinese Code Pages : Simplified Chinese GB2312 ( Windows-936 ),
Traditionnal Chinese Big5 ( Windows-950 )
The Korean Code Pages : Windows 949, EUC-KR
看起来Shift-JIS可能是您试图读取的编码。 从

Shift JIS(Shift日本工业标准,也称SJIS,MIME名称 Shift_JIS)是日语的字符编码, 最初由一家名为ASCII公司的日本公司于年开发 与微软合作


通常,您需要确定用于在文件中创建多字节字符的编码,然后才能由C或任何其他语言中的函数正确读取这些字符

你确定文件的格式吗?链接讨论了多字节等。@Ryker我不理解你的问题。我只是建议你尝试解码一个包含多字节字符的文件,但还没有确定它们由什么编码组成。请看我在上一篇评论中留下的链接。你能拿出你的“已解决”部分作为正确答案发布吗?我看你找到了一个解决方案!我刚刚查看了@Mr.C64的答案下的大量评论记录。看来C64先生是真正回答你问题的人。虽然我非常感谢您接受的答案,但我认为它应该应用于其他地方。:)
wchar\u t
没有标准编码。不过,现代系统使用UTF-32。OP没有写,他使用的是Windows。@Olaf您是对的,wchar\u t在标准中没有明确定义,但在Windows上它用于UTF-16,OP的代码似乎是特定于Windows的。我怎么知道我的日语文本文件是用什么编码的?我只是简单地给它写了日语文本,并将其保存为.txt。如果文件是UTF-8,我会将语言环境设置为UTF-8吗?我不明白答案。@Katianie也许控制台不能显示日文字符?尝试使用MessageBox而不是printf,例如
MessageBox(NULL,text,L“Test”,MB_OK)
@Mr.C64-我刚刚注意到同样的事情。我对你的答案(这是一个很好的答案,我在发布我的答案之前点击了它)的投票仍然有效。谢谢,这对理解编码非常有帮助。在notepad++的顶部有一个编码选项,您可以设置它。我使用的是UTF-8。好吧,我在帖子中的假设是不正确的,但更重要的是,你现在知道你的编码是什么,应该能够对代码进行调整以适应。我尝试将wfopen的读取模式更改为“r,ccs=UTF-8”缓冲区是正确的,但是没有任何东西被打印到我的printfI控制台。我现在没有时间拍摄,但我可能稍后会。我的方法是简单地从代码库(在post中)开始,在函数参数中使用离散选项集。(我甚至可以上传记事本++来测试:))如果我发现任何有用的东西,我会编辑我的答案。
The 2 Bytes Universal Character Set : UCS-2 Big Endian and UCS-2 Little Endian
The Japanese Code Page : Shift-JIS ( Windows-932 )
The Chinese Code Pages : Simplified Chinese GB2312 ( Windows-936 ),
Traditionnal Chinese Big5 ( Windows-950 )
The Korean Code Pages : Windows 949, EUC-KR