在我的Java应用程序中,我将文件重命名为String参数中提供的文件名。有一种方法
boolean OKtoRename(String oldName, String newName)
基本上检查newName是否已被其他文件占用,因为我不想埋没现有文件。
现在我想到,newName String可能不会表示有效的文件名。所以我想把这个检查添加到方法中:
if (new File(newName).isFile()) {
return false;
}
这显然不是正确的方法,因为在大多数情况下newFile尚不存在,因此虽然是 OKtoRename,但该函数返回false。
我想知道,有没有像canExist()
这样的方法(我知道java.io.File对象没有)?或者我是否必须使用正则表达式来确保newFile String不包含无效字符(例如?,*,“,:)?我想知道是否有一个函数隐藏在JDK的某个地方会告诉我是否有字符串可能表示有效的文件名。
答案 0 :(得分:58)
我在几个月前根据一些在线研究汇总了非法文件名字符列表(考虑UNIX,Mac OS X和Windows系统)。如果新文件名包含其中任何一个,则存在在所有平台上可能无效的风险。
private static final char[] ILLEGAL_CHARACTERS = { '/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':' };
修改强> 我想强调,这是不是一个完整的解决方案:正如评论者指出的那样,即使通过此测试,您的文件名仍可能是Windows特定的关键字,如COM,PRN等。但是,如果您的文件名包含任何这些字符,那么它肯定会在跨平台环境中造成麻烦。
答案 1 :(得分:23)
使用createNewFile()
,只有当文件尚不存在时才会自动创建文件。
如果创建了文件,则该名称有效且不会破坏现有文件。然后,您可以使用FileChannel.transferXXX
操作打开文件并有效地将数据从一个复制到另一个。
重要的是要记住,一般来说,检查和创建应该是原子的。如果您首先检查操作是否安全,则作为单独的步骤执行操作,同时条件可能已更改,从而使操作不安全。
此相关帖子提供了额外的思考:"Move/Copy operations in Java."
更新
由于这个答案,我们引入了NIO.2 API,它们增加了与文件系统的更多交互。
假设您有一个交互式程序,并希望在每次击键后验证该文件是否可能有效。例如,您可能只想在条目有效时启用“保存”按钮,而不是在按“保存”后弹出错误对话框。创建并确保删除我上面建议的许多不必要的文件似乎是一团糟。
使用NIO.2,您无法创建包含对文件系统非法的字符的Path
实例。尝试创建InvalidPathException
时会引发Path
。
但是,没有用于验证由有效字符组成的非法名称的API,例如Windows上的“PRN”。作为一种解决方法,实验表明,在尝试访问属性时,使用非法文件名会引发一个明显的异常(例如,使用Files.getLastModifiedTime()
)。
如果为存在的文件指定合法名称,则不会出现异常。
如果为不存在的文件指定合法名称,则会引发NoSuchFileException
。
如果您指定了非法名称,则会引发FileSystemException
。
然而,这看起来非常糟糕,在其他操作系统上可能不可靠。
答案 2 :(得分:18)
Here系统特定方式。
public static boolean isFilenameValid(String file) {
File f = new File(file);
try {
f.getCanonicalPath();
return true;
} catch (IOException e) {
return false;
}
}
答案 3 :(得分:6)
如果要开发Eclipse,请查看org.eclipse.core.internal.resources.OS
public abstract class OS {
private static final String INSTALLED_PLATFORM;
public static final char[] INVALID_RESOURCE_CHARACTERS;
private static final String[] INVALID_RESOURCE_BASENAMES;
private static final String[] INVALID_RESOURCE_FULLNAMES;
static {
//find out the OS being used
//setup the invalid names
INSTALLED_PLATFORM = Platform.getOS();
if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) {
//valid names and characters taken from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp
INVALID_RESOURCE_CHARACTERS = new char[] {'\\', '/', ':', '*', '?', '"', '<', '>', '|'};
INVALID_RESOURCE_BASENAMES = new String[] {"aux", "com1", "com2", "com3", "com4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
"com5", "com6", "com7", "com8", "com9", "con", "lpt1", "lpt2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
"lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "nul", "prn"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$
Arrays.sort(INVALID_RESOURCE_BASENAMES);
//CLOCK$ may be used if an extension is provided
INVALID_RESOURCE_FULLNAMES = new String[] {"clock$"}; //$NON-NLS-1$
} else {
//only front slash and null char are invalid on UNIXes
//taken from http://www.faqs.org/faqs/unix-faq/faq/part2/section-2.html
INVALID_RESOURCE_CHARACTERS = new char[] {'/', '\0',};
INVALID_RESOURCE_BASENAMES = null;
INVALID_RESOURCE_FULLNAMES = null;
}
}
/**
* Returns true if the given name is a valid resource name on this operating system,
* and false otherwise.
*/
public static boolean isNameValid(String name) {
//. and .. have special meaning on all platforms
if (name.equals(".") || name.equals("..")) //$NON-NLS-1$ //$NON-NLS-2$
return false;
if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) {
//empty names are not valid
final int length = name.length();
if (length == 0)
return false;
final char lastChar = name.charAt(length-1);
// filenames ending in dot are not valid
if (lastChar == '.')
return false;
// file names ending with whitespace are truncated (bug 118997)
if (Character.isWhitespace(lastChar))
return false;
int dot = name.indexOf('.');
//on windows, filename suffixes are not relevant to name validity
String basename = dot == -1 ? name : name.substring(0, dot);
if (Arrays.binarySearch(INVALID_RESOURCE_BASENAMES, basename.toLowerCase()) >= 0)
return false;
return Arrays.binarySearch(INVALID_RESOURCE_FULLNAMES, name.toLowerCase()) < 0;
}
return true;
}
}
答案 4 :(得分:4)
这是我实现这个的方式:
public boolean isValidFileName(final String aFileName) {
final File aFile = new File(aFileName);
boolean isValid = true;
try {
if (aFile.createNewFile()) {
aFile.delete();
}
} catch (IOException e) {
isValid = false;
}
return isValid;
}
答案 5 :(得分:3)
对我来说,这似乎是一个依赖操作系统的问题。您可能只想检查文件名中的某些无效字符。当您尝试重命名文件时Windows会执行此操作,它会弹出一条消息,指出文件不能包含以下任何字符:\ /:*? &LT; &GT; | 我不确定你的问题是“是否有图书馆为我做这个工作?”在那种情况下,我不知道。
答案 6 :(得分:3)
我发现,在java 7及更高版本中,有一个名为Paths
的类,它有一个名为get
的方法,它接受一个或多个String
s并抛出
InvalidPathException
- 如果路径字符串无法转换为路径
答案 7 :(得分:0)
使用
String validName = URLEncoder.encode( fileName , "UTF-8");
File newFile = new File( validName );
是否有效。
我今天刚刚找到。我不确定它是否100%有效,但到目前为止,我已经能够创建有效的文件名。