Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.nio.file.NoSuchFileException: why nio not creating file [closed]

Tags:

java

file-io

nio

I am using java.nio.file package and tried to create file with the following code.

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();
            }
        }           
    }

This throws following Exception:

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)

My question is why file is not created?

Please advise

Thanks in anticipation

like image 862
Raakh Avatar asked Dec 19 '22 03:12

Raakh


1 Answers

Updated Answer:

Now that you've shown the full code, there are two major problems:

  1. You're trying to open the file before ensuring that the directories leading up to it exist, and

  2. You're using StandardOpenOption.APPEND, but that won't create a file; it will append to an existing file.

...along with a large number of issues around best practices relative to the number of lines of actual code.

See comments:

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
}

But here's how I would suggest you write it:

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`?
    }
}

...and handle exceptions in the calling layer. Note that, again, because we're using try-with-resources, the close is automatic (both when there's an exception and when there isn't).

Or if you really want to do log-and-continue:

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.
    }
}

Original Answer:

You haven't shown the code that's actually failing, which is a call to newBufferedWriter (this one, or this one). newBufferedWriter takes OpenOptions, the standard set of which are available from StandardOpenOption. Make sure you've specified StandardOpenOption.CREATE or StandardOpenOption.CREATE_NEW,

If you use one of those flags, and the code in your question isbefore the newBufferedWriter call, barring some other problem (permissions) it should work:

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
}
like image 108
T.J. Crowder Avatar answered Apr 27 '23 16:04

T.J. Crowder