C语言读取含韩文的CSV文件时字符乱码问题求助
解决C语言读取含韩文CSV文件的乱码问题
问题背景
我有一个包含韩文的CSV文件,内容如下:
name,hp,damage 대학오리,20,5 대학냥이,30,10 시계탑기린,100,20
编写了如下C语言代码读取并打印该文件:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char name[1000]; int hp; int damage; } Monster; typedef struct { char header1[sizeof "name"]; char header2[sizeof "hp"]; char header3[sizeof "damage"]; } Header; int main() { FILE* fp = fopen("entityData.csv", "r"); if (!fp) { printf("Error opening file\n"); return 1; } Monster monsters[100]; int num_records = 0; char line[100]; Header header; fgets(line, sizeof line, fp); strncpy(header.header1, strtok(line, ","), sizeof header.header1); strncpy(header.header2, strtok(NULL, ","), sizeof header.header2); strncpy(header.header3, strtok(NULL, "\n"), sizeof header.header3); while (fgets(line, sizeof(line), fp)) { char* token = strtok(line, ","); //, 기준으로 나눠서 token에 저장 strncpy(monsters[num_records].name, token, 20); token = strtok(NULL, ","); monsters[num_records].hp = atoi(token); token = strtok(NULL, ","); monsters[num_records].damage = atoi(token); num_records++; } for (int i = 0; i < num_records; i++) { printf("%s:%s %s:%d %s:%d\n", header.header1, monsters[i].name, header.header2, monsters[i].hp, header.header3, monsters[i].damage); } fclose(fp); return 0; }
期望输出:
name:대학오리 hp:20 damage:5 name:대학냥이 hp:30 damage:10 name:시계탑기린 hp:100 damage:20
实际运行时韩文名称出现乱码,尝试使用wchar_t但出错,请求解决方法。
解决方案
韩文属于Unicode字符,通常以UTF-8编码存储(每个韩文占2-3字节),乱码主要源于控制台编码不匹配或宽字符处理流程错误,以下是两种可行方案:
方案1:保持UTF-8字节流处理,修正控制台编码
如果CSV文件是UTF-8编码,直接用char存储韩文是可行的,只需确保控制台输出使用UTF-8编码:
- Windows环境:在代码开头添加
system("chcp 65001 >nul");(>nul用于隐藏编码切换的输出信息); - Linux/macOS环境:控制台默认大多支持UTF-8,无需额外设置。
修改后的核心代码片段:
int main() { // Windows下切换控制台为UTF-8编码 system("chcp 65001 >nul"); FILE* fp = fopen("entityData.csv", "r"); // 后续代码保持不变... }
说明:strtok、strncpy等函数仅处理字节流,不会解析字符编码,只要控制台编码与文件编码匹配,就能正确显示韩文。
方案2:使用宽字符(wchar_t)规范处理
若需严格按宽字符处理Unicode,需使用对应版本的文件操作、字符串处理函数:
- 用
_wfopen打开文件,指定UTF-8编码; - 使用
fgetws读取宽字符行; - 使用
wcstok分割宽字符串; - 使用
wprintf输出宽字符内容; - 结构体中
name字段改为wchar_t类型。
完整示例代码:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <wchar.h> #include <string.h> typedef struct { wchar_t name[1000]; int hp; int damage; } Monster; typedef struct { wchar_t header1[sizeof L"name"]; wchar_t header2[sizeof L"hp"]; wchar_t header3[sizeof L"damage"]; } Header; int main() { // Windows下切换控制台为UTF-8编码 system("chcp 65001 >nul"); // 以宽字符模式打开UTF-8编码的文件 FILE* fp = _wfopen(L"entityData.csv", L"r, ccs=UTF-8"); if (!fp) { wprintf(L"Error opening file\n"); return 1; } Monster monsters[100]; int num_records = 0; wchar_t line[100]; Header header; fgetws(line, sizeof line / sizeof(wchar_t), fp); // 分割宽字符串表头 wchar_t* token = wcstok(line, L","); wcsncpy(header.header1, token, sizeof(header.header1)/sizeof(wchar_t)); token = wcstok(NULL, L","); wcsncpy(header.header2, token, sizeof(header.header2)/sizeof(wchar_t)); token = wcstok(NULL, L"\n"); wcsncpy(header.header3, token, sizeof(header.header3)/sizeof(wchar_t)); while (fgetws(line, sizeof(line)/sizeof(wchar_t), fp)) { token = wcstok(line, L","); wcsncpy(monsters[num_records].name, token, sizeof(monsters[num_records].name)/sizeof(wchar_t)); token = wcstok(NULL, L","); monsters[num_records].hp = _wtoi(token); // 宽字符串转整数 token = wcstok(NULL, L","); monsters[num_records].damage = _wtoi(token); num_records++; } for (int i = 0; i < num_records; i++) { wprintf(L"%s:%s %s:%d %s:%d\n", header.header1, monsters[i].name, header.header2, monsters[i].hp, header.header3, monsters[i].damage); } fclose(fp); return 0; }
说明:
_wfopen的ccs=UTF-8参数指定文件编码,确保读取时正确转换为宽字符;- 所有字符串操作均使用宽字符版本函数(
wcstok、wcsncpy、wprintf等); _wtoi用于将宽字符串转换为整数,替代atoi。
内容的提问来源于stack exchange,提问作者Mr Cake
相关产品推荐
相关产品推荐

