java.io.IOException的可能原因是什么:"文件名,目录名或者卷标签语法不正确"

时间:2020-03-06 14:42:27  来源:igfitidea点击:

我正在尝试使用以下代码复制文件:

File targetFile = new File(targetPath + File.separator + filename);
...
targetFile.createNewFile();
fileInputStream = new FileInputStream(fileToCopy);
fileOutputStream = new FileOutputStream(targetFile);
byte[] buffer = new byte[64*1024];
int i = 0;
while((i = fileInputStream.read(buffer)) != -1) {
    fileOutputStream.write(buffer, 0, i);
}

对于某些用户,targetFile.createNewFile会导致以下异常:

java.io.IOException: The filename, directory name, or volume label syntax is incorrect
    at java.io.WinNTFileSystem.createFileExclusively(Native Method)
    at java.io.File.createNewFile(File.java:850)

文件名和目录名似乎正确。在执行复制代码之前,甚至检查目录targetPath是否存在,文件名看起来像这样:AB_timestamp.xml

用户具有对targetPath的写权限,并且可以使用OS毫无问题地复制文件。

由于我无法访问计算机,因此这种情况仍在发生,并且无法在我自己的计算机上重现该问题,因此我向我们寻求有关此异常原因的提示。

解决方案

我们是否检查targetPath是目录,还是仅使用该名称存在? (我知道我们说用户可以从操作系统中复制它,但是也许他们正在输入其他内容)。

targetPath是否以File.separator结尾?

(如果我们可以登录并告诉我们失败情况下targetPath和filename的值,这将有所帮助)

也许问题是它正在通过网络将文件复制到共享驱动器?我认为,当路径类似于\ mypc \ myshared文件夹时,使用NFS编写文件时,java可能会出现问题。

发生此问题的路径是什么?

尝试添加一些日志记录,以确切查看文件要创建的名称和路径,以确保父目录位于目录中。

此外,我们还可以查看Channels而不是使用循环。 ;-)

我们说"对于某些用户",这样对其他用户有用吗?这有什么区别,用户是在不同的计算机上运行不同的实例,还是这是为并发用户提供服务的服务器?

如果是后者,我会说这是一个并发性错误,两个线程检查尝试使用WinNTFileSystem.createFileExclusively(Native Method)同时创建文件。

当我查看OpenJDK源代码时,createNewFile或者createFileExclusively都不会同步,因此我们可能必须自己同步此块。

尝试在其他目录中创建文件,例如确保具有对该目录的写访问权后,单击" C:"。如果可行,则文件的路径名错误。

查看Exception中的注释,并尝试更改文件路径名中的所有元素。实验。得出结论。

也许文件已经存在。如果时间戳分辨率不够好,则可能是这种情况。由于我们正在获取的是IOException,因此它可能不是权限问题(在这种情况下,我们将获得SecurityException)。

我会先尝试检查文件是否存在,然后再尝试创建文件并尝试记录正在发生的事情。

查看public boolean createNewFile(),以获取有关所使用方法的更多信息。

尝试一下,因为它更需要调整targetPath和filename之间路径中的目录分隔符:

File targetFile = new File(targetPath, filename);

由于我无法在自己的计算机上重现错误,也无法接触代码失败的用户的计算机,因此我一直等到现在才声明一个可接受的答案。
我将代码更改为以下内容:

File parentFolder = new File(targetPath);
... do some checks on parentFolder here ...
File targetFile = new File(parentFolder, filename);
targetFile.createNewFile();
fileInputStream = new FileInputStream(fileToCopy);
fileOutputStream = new FileOutputStream(targetFile);
byte[] buffer = new byte[64*1024];
int i = 0;
while((i = fileInputStream.read(buffer)) != -1) {
    fileOutputStream.write(buffer, 0, i);
}

之后,它可以为用户报告问题。

因此,尽管我实际上使用了与他给出的构造器稍有不同的构造器,但似乎沿用了同样的思路,但亚历山大的答案似乎有效。

我还不得不说服该用户通过再次运行旧版本并检查是否仍然失败来帮助我验证代码更改是否解决了错误(而不是他做了不同的事情)。

顺便提一句。日志记录到位,并且记录的路径似乎还可以,抱歉没有提及。我认为这是理所当然的,发现它不必要地使问题中的代码复杂化。

感谢帮助。

我只是遇到了同样的问题。我认为这与写访问权限有关。尝试写入c:\时出现错误,但在更改为D:\时一切正常。
显然,Java没有权限写入我的系统驱动器(在C:上运行Windows 7安装)