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