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

Java读取含非UTF-8字符文件名失败,如何正确获取并执行stat操作?

解决ISO-8859-1编码文件名在Java NIO中显示为?的问题

问题原因

Java NIO的Path对象默认使用系统默认字符编码解码文件名。如果你的文件名是ISO-8859-1(Latin-1)编码,而系统默认编码是UTF-8,Java会将无法用UTF-8解码的字节替换为�(显示为?),且解码后的字符串丢失了原始字节信息,无法直接还原。

解决方案

1. 直接执行Stat操作(无需修正文件名)

注意:即使Path.toString()显示的文件名包含?,Path对象本身依然指向正确的文件,因此执行stat等文件操作不受影响。示例代码:

Path entry = iterator.next();
// 直接执行stat操作,无需关心toString()的显示
BasicFileAttributes attrs = Files.readAttributes(entry, BasicFileAttributes.class);
System.out.println("文件大小: " + attrs.size());

2. 获取正确的ISO-8859-1编码文件名(Unix/Linux/macOS)

通过Unix文件系统属性视图获取文件名的原始字节数组,再用ISO-8859-1解码,得到正确的文件名字符串:

import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;

// 遍历目录时替换原有的toString()逻辑
Path entry = iterator.next();
// 获取原始文件名字节数组
byte[] fileNameBytes = (byte[]) Files.getAttribute(entry, "unix:name");
// 用ISO-8859-1解码得到正确文件名
String correctFileName = new String(fileNameBytes, StandardCharsets.ISO_8859_1);
System.out.println("正确文件名: " + correctFileName);
// 同时执行stat操作
BasicFileAttributes attrs = Files.readAttributes(entry, BasicFileAttributes.class);
System.out.println("文件修改时间: " + attrs.lastModifiedTime());

3. 跨平台兼容方案(Windows/Unix通用)

通过调用系统命令读取目录原始输出,再用ISO-8859-1解码(需根据系统调整命令):

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;

public static void listFilesWithCorrectEncoding(String dir) throws Exception {
    // Unix用"ls -1",Windows用"cmd /c dir /b"
    ProcessBuilder pb = System.getProperty("os.name").toLowerCase().contains("win")
            ? new ProcessBuilder("cmd", "/c", "dir", "/b", dir)
            : new ProcessBuilder("ls", "-1", dir);
    pb.redirectErrorStream(true);
    Process process = pb.start();
    try (BufferedReader reader = new BufferedReader(
            new InputStreamReader(process.getInputStream(), StandardCharsets.ISO_8859_1))) {
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println("正确文件名: " + line);
            // 根据文件名构建Path并执行stat操作
            Path path = Paths.get(dir, line);
            BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
            System.out.println("文件大小: " + attrs.size());
        }
    }
}

关键说明

  • Java的Path对象内部通过操作系统的文件标识(而非解码后的字符串)定位文件,因此即使显示的文件名有?,文件操作依然有效。
  • Unix属性视图方案依赖JDK的UnixFileSystemProvider,仅在Unix-like系统可用;Windows环境建议使用系统命令方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:43:29