You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言调用ReadFile读取文件存入wchar_t输出方块问号乱码如何解决

ReadFile读取文本到wchar_t数组输出乱码的错误原因

你的代码存在4个核心逻辑错误,直接导致输出乱码:

  • 编码匹配错误:ReadFile仅做原始字节读取,不会自动完成编码转换。Windows平台wchar_t对应2字节长度的UTF-16 LE编码,只有当a.txt本身存储为UTF-16 LE格式时,直接读取字节到wchar_t数组才可能正确解析。但系统默认生成的txt文件多为GBK(ANSI)或UTF-8编码,属于单/变长多字节编码,强行按2字节一组解析为宽字符必然出现乱码。
  • 内存分配逻辑错误:你获取的sizeF是文件的字节总长度,分配内存时写malloc(sizeF * sizeof(wchar_t))会申请2倍于实际需求的内存,属于无意义的资源浪费。
  • 字符串终止位置错误:wchar_t数组的索引以宽字符为单位计数,而非字节。你直接在readBuffer[sizeF]位置写入终止空字符,位置完全错误——若文件为UTF-16编码,实际宽字符数为字节数/2,该写入位置要么越界,要么导致字符串截断异常。
  • 缺少必要的错误处理与BOM兼容:代码没有判断CreateFileW的返回值是否为INVALID_HANDLE_VALUE,也没有使用ReadFile输出的bytesRead参数确认实际读取字节数;即便文件为UTF-16编码,Windows默认保存的Unicode文本会在开头带2字节BOM头(0xFFFE),直接输出会出现异常字符。
修正方案

根据目标文件的实际编码选择对应处理逻辑:

场景1:a.txt为UTF-8/ANSI编码(绝大多数默认场景)

先按原始字节读取文件内容,再通过MultiByteToWideChar完成编码转换为UTF-16格式的宽字符串,核心实现参考:

#include <stdio.h>
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <stdlib.h>

int main() {
    _setmode(_fileno(stdout), _O_U16TEXT);

    HANDLE fh = CreateFileW(
        L"a.txt",
        GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (fh == INVALID_HANDLE_VALUE) {
        return 1;
    }

    LARGE_INTEGER size;
    GetFileSizeEx(fh, &size);
    DWORD byteSize = size.QuadPart;
    char* byteBuf = (char*)malloc(byteSize + 1);
    DWORD bytesRead = 0;

    if (!ReadFile(fh, byteBuf, byteSize, &bytesRead, NULL)) {
        CloseHandle(fh);
        free(byteBuf);
        return 1;
    }
    byteBuf[bytesRead] = '\0';
    CloseHandle(fh);

    // 若文件为ANSI编码,将CP_UTF8替换为CP_ACP
    int wLen = MultiByteToWideChar(CP_UTF8, 0, byteBuf, -1, NULL, 0);
    wchar_t* readBuffer = (wchar_t*)malloc(wLen * sizeof(wchar_t));
    MultiByteToWideChar(CP_UTF8, 0, byteBuf, -1, readBuffer, wLen);

    wprintf(L"%s\n", readBuffer);

    free(byteBuf);
    free(readBuffer);
    return 0;
}

场景2:a.txt本身为UTF-16 LE编码

修正内存分配、终止符位置,增加BOM跳过逻辑即可:

  • 内存按字节数分配即可,额外多申请2字节存放终止空字符
  • 实际读取完成后,根据bytesRead计算实际宽字符数,在对应位置写入终止符
  • 检查数组开头2字节是否为UTF-16 LE的BOM标识0xFEFF,若存在则将输出指针向后偏移2字节跳过BOM

内容的提问来源于stack exchange,提问作者Nazarevsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 21:18:26