我正在尝试列出目录的内容,并重命名某些文件。
public void run(String dirName) {
try {
File parDir = new File(dirName);
File[] dirContents = parDir.listFiles();
// Rename if necessary
for(File f : dirContents) {
System.out.println("f is:\n" + f.toString());
String name = f.getName();
String subbedName = name.replaceAll("\uFFFD", "_");
System.out.println("\n" + "name = " + name + ", subbedName = " + subbedName + "\n");
if(!name.equals(subbedName)) {
File newFile = new File(f.getParentFile(), subbedName);
System.out.println("newFile is:\n" + newFile.toString());
if(!f.renameTo(newFile))
System.out.println("Tried to change file name but couldn't.");
}
}
}
catch(Exception exc1) {
System.out.println("Something happened while listing and renaming directory contents: " + exc1.getMessage());
}
}
当我运行它时,我得到“Tried to change file name but couldn't.
”我不相信 Java正在考虑将这些文件“打开”,所以我不认为这就是原因。我甚至运行了chmod 777 myDir
,其中myDir
是传递到dirName
方法的run
字符串的值。
我在这里缺少什么?为什么Java不会重命名这些文件?这些是CentOS机器。
修改:为f
和newFile
添加了打印输出,如下所示:
f is:
/root/path/to/mydir/test�.txt
newFile is:
/root/path/to/mydir/test_.txt
答案 0 :(得分:2)
问题是f.getName()
返回由f
表示的路径的姓氏成分。然后按下此字符串并将其转回File
。但File
现在表示相对于当前目录的路径,而不是包含原始路径的目录。
因此,您的代码实际上是在尝试将文件从dirName
重命名为应用程序的当前目录。这可能会失败,因为当前目录中的文件已存在这些名称,或者因为dirName
和当前目录位于不同的文件系统中。 (您无法将文件从一个文件系统重命名为另一个文件系统......您必须复制它。)
请注意,Java中的File
表示路径名,而不是文件或文件夹。在您的代码中,f
对象是由字符串dirname
表示的文件系统对象(文件或文件夹)的路径名。这些f
个对象中的每一个都有一个目录部分。
修复代码的方法不止一种;例如
name = f.getName()
更改为name = f.toString()
new File(subbedName)
更改为new File(f.getParentFile(), subbedName)
我有一个替代/额外的理论。
包含\uFFFD
字符的文件的路径名称为“mojibake”;即使用错误的编码显示编码文本时出现的乱码文本。由于我们看到3个乱码文字,我怀疑它试图将\uFFFD
的UTF-8渲染显示为Latin-1。
所以我的理论是,当File.renameTo
方法将f
转换为它将提供给系统调用的形式时,同样的想法正在发生。由于某些原因我不清楚,Java可能使用了错误的编码,因此产生了原始文件的“名称”,该名称与文件系统中的文件名不匹配。这足以导致重命名失败。
可能相关的问题/链接:
答案 1 :(得分:1)
您需要使用这些文件的完整路径名创建新的File
对象。所以
String name = f.getName(); // gets the name without the directory
应该是:
String name = f.getAbsolutePath();
(您的搜索/替换可能需要更改)
答案 2 :(得分:1)
f.getName();
仅返回文件夹的名称,而不是完整路径。因此subbedName
成为相对路径文件。尝试使用f.getCanonicalPath()
代替。