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

相关推荐
2401_857439698 分钟前
SpringBoot框架在资产管理中的应用
java·spring boot·后端
怀旧6669 分钟前
spring boot 项目配置https服务
java·spring boot·后端·学习·个人开发·1024程序员节
阿华的代码王国29 分钟前
【SpringMVC】——Cookie和Session机制
java·后端·spring·cookie·session·会话
德育处主任Pro1 小时前
『Django』APIView基于类的用法
后端·python·django
哎呦没3 小时前
SpringBoot框架下的资产管理自动化
java·spring boot·后端
2401_857600953 小时前
SpringBoot框架的企业资产管理自动化
spring boot·后端·自动化
NiNg_1_2347 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
Chrikk9 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*9 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue9 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang