Windwos文件系统文件名长度限制

在使用 Windows 10 操作系统时,文件管理是一个不可避免的任务。然而,即使是在这样一个常见的任务中,用户可能会遇到某些限制,其中之一就是文件名的长度限制。本文将结合笔者的工作经历探讨 Windows 10 中文件名长度的限制,以及如何处理它。

背景介绍

公司的一个需求,简单的来说满足windows用户的一个需求:存入本地文件中,但是文件名完全由用户自定义。然后就收到了用户的bug反馈。我一看反馈回来的日志,好家伙,用户那个文件名比我屏幕都长。

写个demo

现在就简单模拟一下,用户尝试向一个长文件名文件中写入hello world 感兴趣的windows10用户可以测试一下。先建好GeekDog这个文件夹

java 复制代码
package Test;

import java.io.FileWriter;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        // 文件路径
        String filePath = "D:\\GeekDog\\heeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeello.txt";

        try {
            System.out.println(filePath.replace("D:\\GeekDog\\","").length());
            // 创建FileWriter对象
            FileWriter writer = new FileWriter(filePath);
            // 向文件中写入内容
            writer.write("hello world");
            // 关闭文件写入流
            writer.close();
            System.out.println("文件创建并写入成功!");
        } catch (IOException e) {
            System.out.println("创建文件时出错:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

很遗憾最后失败了错误信息为

csharp 复制代码
256
创建文件时出错:D:\GeekDog\heeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeello.txt (文件名、目录名或卷标语法不正确。)
java.io.FileNotFoundException: D:\GeekDog\heeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeello.txt (文件名、目录名或卷标语法不正确。)
	at java.base/java.io.FileOutputStream.open0(Native Method)
	at java.base/java.io.FileOutputStream.open(FileOutputStream.java:293)
	at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:235)
	at java.base/java.io.FileOutputStream.<init>(FileOutput

查阅资料

Windows的问题那就要去官网查,链接放在这learn.microsoft.com/en-us/windo...

说白了,就是微软对文件系统的文件名是有最长限制的,

  • 在 Windows API ((以下段落) 中介绍的一些例外情况)中,路径的最大长度为 MAX_PATH,定义为 260 个字符。 本地路径按以下顺序构建:驱动器号、冒号、反斜杠、用反斜杠分隔的名称组件以及终止 null 字符。 例如,驱动器 D 上的最大路径为"D:\some 256 个字符的路径字符串",其中""表示当前系统代码页的不可见终止 null 字符。 (此处使用的字符 <> 是为了直观明了,不能是有效路径 string 的一部分。)

也就是说,默认情况下,文件名最长255个字符 + 一个终止字符

那就再试试减少一个字母看看

java 复制代码
package Test;

import java.io.FileWriter;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        // 文件路径
        String filePath = "D:\\GeekDog\\eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeello.txt";

        try {
            System.out.println(filePath.replace("D:\\GeekDog\\","").length());
            // 创建FileWriter对象
            FileWriter writer = new FileWriter(filePath);
            // 向文件中写入内容
            writer.write("hello world");
            // 关闭文件写入流
            writer.close();
            System.out.println("文件创建并写入成功!");
        } catch (IOException e) {
            System.out.println("创建文件时出错:" + e.getMessage());
            e.printStackTrace();
        }
    }
}


//去掉了h
//255
//文件创建并写入成功!

加长路径长度

我这个人一向很多疑,我就是想看看真的就是文件名影响这个结果吗?

然后写入到这个文件中

java 复制代码
package Test;

import java.io.FileWriter;
import java.io.IOException;

public class Main {
    public static void main(String[] args) {
        // 文件路径
        String filePath = "D:\\GeeeeeeekDog\\eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeello.txt";

        try {
            System.out.println(filePath.replace("D:\\GeeeeeeekDog\\","").length());
            // 创建FileWriter对象
            FileWriter writer = new FileWriter(filePath);
            // 向文件中写入内容
            writer.write("hello world");
            // 关闭文件写入流
            writer.close();
            System.out.println("文件创建并写入成功!");
        } catch (IOException e) {
            System.out.println("创建文件时出错:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

//255
//文件创建并写入成功!

路径名确实不影响。

最后我们觉得增加这个文件名长度限制会更好,在前端写了一个文件名长度校验方法。

其他解决方案

Win10贴心的给出了两个解决方案。

扩展前缀

'\?\' 前缀用于指示 Win32 文件路径字符串的完全限定形式。使用 \?\ 前缀可以绕过一些路径长度限制以及文件名字符限制。

java 复制代码
  import java.io.File;
import java.io.IOException;

public class CreateFileWithLongPath {
    public static void main(String[] args) {
        // 长路径名
        String longPath = "\\\\?\\C:\\my\\very\\long\\path\\to\\file.txt";

        File file = new File(longPath);

        try {
            // 创建文件
            if (file.createNewFile()) {
                System.out.println("文件创建成功!");
            } else {
                System.out.println("文件已存在。");
            }
        } catch (IOException e) {
            System.out.println("创建文件时出错:" + e.getMessage());
            e.printStackTrace();
        }
    }
}

注册表

在Windows 10, Version 1607和更新的版本中,若要启用新的长路径行为,必须满足以下两个条件:

  • 注册表项 Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled (Type: REG_DWORD) 必须存在,并且设置为 1。 第一次调用受影响的 Win32 文件或目录函数后,系统 (将按进程) 缓存密钥的值, (请参阅下面的函数) 列表。 在进程的生存期内,不会重新加载注册表项。 为了使系统上的所有应用都能识别密钥的值,可能需要重新启动,因为某些进程可能在设置密钥之前启动。 还可以将此代码复制到 .reg 可为你设置此代码的文件,或使用具有提升权限的终端窗口中的 PowerShell 命令:
    • 注册表 (.reg) 文件
ini 复制代码
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem]
"LongPathsEnabled"=dword:00000001
  

或者

  • PowerShell
sql 复制代码
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force

还可以通过 组策略 来控制Computer Configuration > Administrative Templates > System > Filesystem > Enable Win32 long paths此注册表项。

应用程序清单还必须包含 longPathAware 元素。

xml 复制代码
<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
        <ws2:longPathAware>true</ws2:longPathAware>
    </windowsSettings>
</application>

如果选择加入长路径行为,这些目录管理功能不再具有 MAX_PATH 限制:CreateDirectoryW、CreateDirectoryExW GetCurrentDirectoryW RemoveDirectoryW SetCurrentDirectoryW。

选择加入长路径行为时,这些是不再具有 MAX_PATH 限制的文件管理功能:CopyFileW、CopyFile2、CopyFileExW、CreateFileW、CreateFile2、CreateHardLinkW、CreateSymbolicLinkW、DeleteFileW、 FindFirstFileW、FindFirstFileExW、FindNextFileW、GetFileAttributesW、GetFileAttributesExW、SetFileAttributesW、GetFullPathNameW、GetLongPathNameW、MoveFileW、MoveFileExW、MoveFileWithProgressW、ReplaceFileW、SearchPathW、FindFirstFileNameW、FindNextFileNameW、FindFirstStreamW、FindNextStreamW、GetCompressedFileSizeW、GetFinalPathNameByHandleW。

总结

尽管 Windows 10 中存在文件名长度的限制,但用户仍然可以通过合理规划文件组织结构以及利用操作系统提供的特殊功能来处理这一问题。在文件管理时,了解这些限制是非常重要的,以确保文件系统的稳定性和可靠性。

相关推荐
ai小鬼头3 小时前
百度秒搭发布:无代码编程如何让普通人轻松打造AI应用?
前端·后端·github
考虑考虑3 小时前
@FilterRegistration和@ServletRegistration注解
spring boot·后端·spring
一只叫煤球的猫3 小时前
🔥 同事混用@Transactional和TransactionTemplate被我怼了,三种事务管理到底怎么选?
java·spring boot·后端
你的人类朋友9 天前
(●'◡'●)从Dockerfile快速入门Docker Compose
后端
GetcharZp9 天前
「神器推荐」Rclone:轻松玩转云端存储,FTP 也能飞起来!
后端
华子w9089258599 天前
基于 SpringBoot+JSP 的医疗预约与诊断系统设计与实现
java·spring boot·后端
舒一笑9 天前
工作流会使用到Webhook是什么
后端·程序员
止观止9 天前
Rust智能指针演进:从堆分配到零复制的内存管理艺术
开发语言·后端·rust
学無芷境9 天前
Cargo 与 Rust 项目
开发语言·后端·rust
ai小鬼头9 天前
AIStarter开发者熊哥分享|低成本部署AI项目的实战经验
后端·算法·架构