温馨提示×

linux readdir为啥乱码

小樊
42
2026-10-02 17:10:04
栏目: 智能运维

在 Linux 下使用 readdir(或更常见的 readdir() / readdir_r())读取目录时出现“乱码”,通常不是 readdir 本身的问题,而是字符编码或终端显示的问题。下面按常见原因给你梳理一下。


一、最常见原因:文件名本身是 UTF-8,但终端不是 UTF-8

Linux 文件名是以字节序列存储的,readdir 返回的 d_name 也是字节数组,不关心编码。

如果:

  • 文件名是 UTF-8 编码(中文、日文等)
  • 你的终端 / locale 是 C 或 GBK

就会出现乱码。

检查当前 locale

locale

如果看到:

LANG=C
LC_ALL=C

那基本就是原因。

解决方法

export LANG=zh_CN.UTF-8
export LC_ALL=zh_CN.UTF-8

或者临时测试:

LANG=en_US.UTF-8 ./your_program

二、你在 C 程序里直接 printf 了 d_name

示例:

printf("%s\n", entry->d_name);

这本身没问题,前提是终端编码和文件名编码一致。

如果你在 Windows 的串口工具(如旧版 SecureCRT、Putty 默认 GBK)访问 Linux,而文件名是 UTF-8,就会乱码。

✅ 解决:

  • 终端改为 UTF-8
  • 或把 UTF-8 转 GBK(不推荐,复杂且易错)

三、文件名本来就是“乱”的(非法 UTF-8)

有些文件是从 Windows、FTP、U盘拷贝过来的,文件名可能是:

  • GBK
  • 损坏的 UTF-8
  • 二进制名

readdir 如实返回,显示自然怪。

查看真实字节

for (i = 0; d_name[i]; i++)
    printf("%02x ", d_name[i]);

或用命令行:

ls | hexdump -C

四、你误以为 readdir 返回“字符串”

struct dirent 中的:

char d_name[256];

只是原始字节,不是“字符串编码转换后的结果”。

如果你用:

  • wprintf
  • 宽字符函数
  • Qt / Java / Python 错误解码

都会出问题。


五、NFS / FAT / NTFS 文件系统编码问题

某些文件系统:

  • vfat:默认 iocharset=gb2312
  • ntfs-3g:可能 UTF-8 / 本地编码不一致

挂载时可指定:

mount -o iocharset=utf8 /dev/sdb1 /mnt

六、一个正确示例(C)

#include <dirent.h>
#include <stdio.h>

int main() {
    DIR *dir = opendir(".");
    struct dirent *entry;

    while ((entry = readdir(dir))) {
        printf("%s\n", entry->d_name);
    }
    closedir(dir);
    return 0;
}

只要:

  • 终端 UTF-8
  • 文件名 UTF-8

就不会乱码。


七、快速自查清单 ✅

  • [ ] locale 是不是 UTF-8
  • [ ] 终端编码是不是 UTF-8
  • [ ] 文件名是不是合法 UTF-8
  • [ ] 有没有跨文件系统(vfat/ntfs)
  • [ ] 是不是 Windows 工具访问 Linux

如果你愿意,可以把:

  • 你的 代码片段
  • locale 输出
  • 乱码截图或 hex

发出来,我可以精确告诉你到底是哪一步出的问题。

0 踩