在 Debian(Linux) 下,readdir(以及 opendir/readdir/readdir_r)本身不涉及“文本编码转换”,它返回的是原始字节序列(filename 的 byte string)。编码问题通常出现在 你如何解释这些字节 的时候。
下面按常见场景说明。
struct dirent {
ino_t d_ino;
off_t d_off;
unsigned short d_rendtl;
unsigned char d_type;
char d_name[]; // 原始字节(不一定是 UTF-8)
};
✅ d_name 是 字节数组
❌ 不是“字符串对象”
❌ 不保证是 UTF-8
touch 中文.txt
文件名在磁盘上就是 UTF-8 编码的字节readdir 仍然原样返回,不会自动转换什么都不用做:
while ((ent = readdir(dir)) != NULL) {
printf("%s\n", ent->d_name);
}
前提是:
char *mbstowcsiconvstd::string / std::filesystemC++17 示例:
for (auto& p : std::filesystem::directory_iterator(".")) {
std::cout << p.path().filename().string() << "\n";
}
你需要 显式转换:
#include <iconv.h>
// GBK -> UTF-8
iconv_t cd = iconv_open("UTF-8", "GBK");
⚠️ 注意:
readdir 返回的是 GBK 字节❌ locale 不会改变 readdir 的行为
export LANG=zh_CN.UTF-8
只会影响:
printfmbstowcs✅ 不会改变:
readdir 返回内容import os
for name in os.listdir('.'):
print(name) # name 是 str(自动按 fs encoding 解码)
Debian 默认:
sys.getfilesystemencoding() # 'utf-8'
| 问题 | 原因 |
|---|---|
| 中文乱码 | 文件名 GBK,终端 UTF-8 |
| readdir 崩溃 | 把 d_name 当宽字符 |
| 比较失败 | 编码不一致 |
| 跨平台乱码 | Windows 用 UTF-16 |
✅ 新项目
std::filesystem 或 opendir + UTF-8✅ 兼容老系统
readdir 原样保存字节iconv✅ 不要假设
如果你愿意,可以告诉我:
我可以直接给你对应代码。