【问题标题】:Renaming a file throwing Exception in thread "main" java.nio.file.FileSystemException:在线程“main”java.nio.file.FileSystemException 中重命名抛出异常的文件:
【发布时间】:2014-02-17 11:25:51
【问题描述】:

我正在使用WatchService.查看用于创建新文件的目录,每当创建新文件或进入此目录时,我都需要更改该文件的名称。

我有以下代码

Path pathfolder=Paths.get("D:\\tempm\\watch");
        WatchService watcherService=FileSystems.getDefault().newWatchService();
        pathfolder.register(watcherService, StandardWatchEventKinds.ENTRY_CREATE);

        System.out.println("Watching that directory");
        boolean valid=true;
        do{
            WatchKey watchKey=watcherService.take();
            for(WatchEvent<?> event:watchKey.pollEvents()){
                WatchEvent.Kind kind=event.kind();
                if(StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())){
                    final String fileName=event.context().toString();
                    if(fileName.endsWith(".jar")){
                    System.out.println("File created--"+fileName);
                    File oldFileName=new File("D:\\tempm\\watch\\"+fileName);

                        File destFile=new File("D:\\tempm\\watch\\"+fileName.substring(0,fileName.lastIndexOf("."))+"_processing.jar");
                        File path=new File("D:\\tempm\\watch\\");
                            if(!fileName.contains("_processing")){
                        Files.move(oldFileName.toPath(), destFile.toPath(),StandardCopyOption.ATOMIC_MOVE,StandardCopyOption.REPLACE_EXISTING); //Line Number 45
                        FileDeleteStrategy.FORCE.delete(oldFileName);
                        System.out.println("Old file deleted");
                            }
                        }
                    }
            }
            valid=watchKey.reset();
        }while(valid);

当我第一次将文件粘贴到该目录时,它已成功重命名。如果我第二次添加任何文件,则会引发异常。我不知道为什么会出现此异常。需要一些帮助。

我的输出

Watching that directory
File created--dom4j.jar
Old file deleted
File created--dom4j_processing.jar
File created--watchplc.jar
Exception in thread "main" java.nio.file.FileSystemException: D:\tempm\watch\watchplc.jar -> D:\tempm\watch\watchplc_processing.jar: The process cannot access the file because it is being used by another process.

    at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
    at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
    at sun.nio.fs.WindowsFileCopy.move(Unknown Source)
    at sun.nio.fs.WindowsFileSystemProvider.move(Unknown Source)
    at java.nio.file.Files.move(Unknown Source)
at ext.gt.test.MonitorDirectory.main(MonitorDirectory.java:45)

【问题讨论】:

  • 有人正在使用该文件,阻止重命名。使用 ProcExplorer(Sys internals) 找出谁在处理它。
  • @Jayan 你能给我ProcExplorer的文档链接吗?我之前没用过
  • @Jayan 你能告诉我是否有任何 java 类可以检查哪个进程正在保存我的文件?我应该如何检查\杀死它?
  • 恕我直言,纯 java 将无济于事。您可以编写一些本机代码。在stackoverflow.com/questions/11104916/…查看一些提示

标签: java file


【解决方案1】:

您的程序失败,因为StandardWatchEventKinds.ENTRY_CREATE 只告诉您文件已创建,而不是进程已停止写入文件或释放文件句柄。您可以通过自己创建一个简单的程序来复制错误。

public class FileCreator
{
    public static void main(String... args)
    {
        new FileCreator().go();
    }

    public void go()
    {
        FileWriter fileWriter = null;
        try
        {
            File file = new File("d:/tempm/watch/" + System.currentTimeMillis() + ".jar");
            fileWriter = new FileWriter(file);
            for (int counter = 0; counter < 100; counter++)
            {
                // first write
                fileWriter.write(String.valueOf(System.nanoTime()));
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if(fileWriter != null)
            {
                try
                {
                    // data is flushed and file handles are closed
                    fileWriter.flush();
                    fileWriter.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}

请注意,一旦遇到第一个write(),就会创建一个文件。这个程序仍然有一个文件句柄并继续写入它,直到流被刷新和关闭。您的其他程序会在该文件上的流关闭之前拾取该文件以将其移动。

在您尝试在文件上创建move 之前,您需要一个系统来告诉您文件是否已完全写入您正在查看的目录。

【讨论】:

  • 你能解释一下StandardWatchEventKinds.ENTRY_CREATE 与保存将在我的代码中创建的文件有何关系吗?我在这里没有使用任何 FileWriter 或阅读器
  • 重点不是你可能用过FileWriter。应用程序正在将文件写入该目录。我试图说明创建文件比完全写入文件并刷新它要快。在完成此操作之前,您无法移动文件。
猜你喜欢
  • 1970-01-01
  • 2017-11-25
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多