java.nio.file.NoSuchFileException:为什么nio没有创建文件

时间:2015-06-18 07:16:33

标签: java file-io nio

我正在使用java.nio.file包并尝试使用以下代码创建文件。

        private static void printReport(String filename, String str)throws Exception{

    ErrorCheck ec           = new ErrorCheck();
    String fileName         = "/var/Emails_log/"+filename;      
    Path filePath           = Paths.get(fileName);
    File file           = new File(fileName);               
    final BufferedWriter out    = Files.newBufferedWriter(filePath, StandardCharsets.UTF_8, StandardOpenOption.APPEND);         

    try{                

        final Path tmp = filePath.getParent();
        if (tmp != null){ // null will be returned if the path has no parent
                Files.createDirectories(tmp);   
        }
        else{
            out.write(str);
            out.write('\n');
        }               
        }catch (Exception e){
        ec.errorMsg("ERROR: GSW.SendEmail.Exception =>",e);
        } 
       finally {
            if (out != null) {
                out.flush();
                out.close();
            }
    }           
}

这会抛出以下异常:

java.nio.file.NoSuchFileException: /var/Emails_log/GSWvalidSentAddresses.txt
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
at java.nio.file.spi.FileSystemProvider.newOutputStream(FileSystemProvider.java:430)
at java.nio.file.Files.newOutputStream(Files.java:170)
at java.nio.file.Files.newBufferedWriter(Files.java:2720)
at SendEmail.printReport(SendEmail.java:114) SendEmail.send(SendEmail.java:87)

我的问题是为什么不创建文件?

请告知

感谢您的期待

1 个答案:

答案 0 :(得分:7)

更新了答案

现在您已经显示了完整的代码,有两个主要问题:

  1. 您正在尝试打开该文件,然后确保存在导致该目录的目录,

  2. 您正在使用StandardOpenOption.APPEND,但不会创建文件;它将附加到现有的文件。

  3. ......以及与实际代码行数相关的最佳实践的大量问题。

    见评论:

    private static void printReport(String filename, String str) throws Exception /* No, it doesn't. The only calls you had outside your catch-all `try` don't throw exceptions. */ {
        ErrorCheck ec           = new ErrorCheck();            // Recommend not creating this until/unless you need it
        String fileName         = "/var/Emails_log/"+filename; // VERY poor practice having two locals that only differ by the capitalization of one character in the middle (`filename` and `fileName`)
        Path filePath           = Paths.get(fileName);
        //  File file               = new File(fileName);      <== Removed, since you never use it for anything
    
        try {
            // Make sure the directories exist
            Files.createDirectories(filePath.getParent());  // No need for your null check, so I removed it; based on `fileName`, it will always have a parent
    
            // Open the file, creating it if it doesn't exist
            try (
                final BufferedWriter out = Files.newBufferedWriter(
                                                filePath,
                                                StandardCharsets.UTF_8,
                                                StandardOpenOption.CREATE,
                                                StandardOpenOption.APPEND)
            ) {
                // Write to out here
            }
        } catch (Exception e) {
            // Log-and-continue isn't generally best practice; and if you're going to do it
            ec.errorMsg("ERROR: GSW.SendEmail.Exception =>",e); // <== Um...send mail failed? This isn't sending mail, it's putting something in a file.
        }
        // Using the try-with-resources, we don't have to worry about the flush and close calls
    }
    

    但这是我建议你写的方式:

    private static void printReport(String filename, String str) throws IOException {
        Path filePath           = Paths.get("/var/Emails_log/" + filename);
    
        // Make sure the directories exist
        Files.createDirectories(filePath.getParent());
    
        // Open the file, creating it if it doesn't exist
        try (
            final BufferedWriter out = Files.newBufferedWriter(
                                            filePath,
                                            StandardCharsets.UTF_8,
                                            StandardOpenOption.CREATE,
                                            StandardOpenOption.APPEND)
        ) {
            // Write to out here, perhaps outputting `str`?
        }
    }
    

    ...并处理调用层中的异常。请注意,同样,因为我们使用的是try-with-resourcesclose是自动的(无论何时出现异常,何时出现异常)。

    或者,如果您真的想要记录并继续:

    private static void printReport(String filename, String str) {
        try {
            Path filePath           = Paths.get("/var/Emails_log/" + filename);
    
            // Make sure the directories exist
            Files.createDirectories(filePath.getParent());
    
            // Open the file, creating it if it doesn't exist
            try (
                final BufferedWriter out = Files.newBufferedWriter(
                                                filePath,
                                                StandardCharsets.UTF_8,
                                                StandardOpenOption.CREATE,
                                                StandardOpenOption.APPEND)
            ) {
                // Write to out here, perhaps outputting `str`?
            }
        }
        catch (Exception e) {
            new ErrorCheck().errorMsg("ERROR: GSW.SendEmail.Exception =>", e); // <== But surely this message is suspect? I don't see anything sending email here.
        }
    }
    

    原始答案

    您尚未显示实际失败的代码,即调用newBufferedWriterthis一个或this一个)。 newBufferedWriter需要OpenOption个,其标准集可从StandardOpenOption获得。确保您已指定StandardOpenOption.CREATEStandardOpenOption.CREATE_NEW

    如果您使用其中一个标记,并且 newBufferedWriter调用之前问题中的代码是,除非出现其他问题(权限),否则它应该有效:

    String fileName         = "/var/Emails_log/"+filename;
    Path filePath           = Paths.get(fileName);
    final Path tmp          = filePath.getParent();
    
    if (tmp != null) {      // <== Note: There's no point to this check, given
                            // your filename above, the path WILL have a parent.
                            // You could remove the `if` and just use
                            // `Files.createDirectories(tmp)` unless the `fileName`
                            // is actually coming from somewhere else and so could
                            // be a root (roots don't have parents)
        Files.createDirectories(tmp);
    }
    else {
        out.write(str);     // I assume this is for logging or display?
        out.write('\n');    // Specifically, that it's *not* trying to write
                            // to the file you're trying to create.
    }
    
    try (BufferedWriter writer = Files.newBufferedWriter(filePath, StandardOpenOption.CREATE)) {
    // ------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^
        // Write to the file here
    }