无法在C

时间:2016-10-13 13:55:26

标签: c windows file file-io unicode

(我查看了以前的帖子并尝试了他们的建议但无济于事。)

我正在尝试读取仅包含日文字符的文件。这是该文件的样子:

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

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

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;
}

要调用此函数,我正在执行以下操作。也许我没有正确使用setlocale(),但从我读到的内容看起来就像是我。只是为了重新迭代,我遇到的问题是垃圾似乎被读入并且控制台中没有显示任何内容:

    setlocale(LC_ALL, "jp");
    wchar_t* retVal = ReadTextFileW(L"C:\\jap.txt");
    printf("%S\n", retVal);
    _aligned_free(retVal);

我还在.cpp

的顶部定义了以下内容
#define UNICODE
#define _UNICODE

解决:

要解决此问题,正如ryyker所提到的,您需要知道用于创建原始文件的编码。在记事本和记事本++中有一个用于编码的下拉菜单。默认情况下(以及最常用的)是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);

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

2 个答案:

答案 0 :(得分:2)

这是一个 excerpt discussing content on encoding for Japanese language ,使用Notepad ++创建(在评论中声明为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可能是您尝试阅读的编码。 来自 here

  

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

通常,您需要确定用于在文件中创建多字节字符的编码,然后才能通过C语言或任何其他语言正确读回它们。 This link may help

答案 1 :(得分:0)

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

但关键是:编码用于将日文文本存储在文件中?

例如,如果文本以UTF-8编码,则应该从UTF-8转换为UTF-16(例如使用MultiByteToWideChar Win32 API),因为您在内存中看起来有一个wchar_t缓冲区。

如果您使用的是最新版本的Visual Studio,还可以specify some encoding information in the mode string传递给_wfopen_s(使用ccs标志)。

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