java. nio. file. Nosuchfileexception: why NiO did not create a file
I'm using Java nio. File package and try to create a file using 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(); } } }
Throw the 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 not create a file?
Please give me some advice
Thank you for your expectation
Solution
Update answer:
Now that you have shown the complete code, there are two main problems:
>You are trying to open the file, then make sure that the directory that caused it exists, and > you are using standardopenoption Append, but this does not create a file; It will be attached to an existing file
... and a number of best practice questions related to the actual number of lines of 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,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 that's how I 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,StandardOpenOption.APPEND) ) { // Write to out here,perhaps outputting `str`? } }
... and handle exceptions in the call layer Note that, again, because we are using try with resources, close is automatic (when there are exceptions and when there are no exceptions)
Or, if you really want to record 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,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 actually failed, that is, calling newbufferedwriter (this one or this one) Newbufferedwriter adopts openoptions, and its standard set can start from standard openoption Ensure that standardopenoption. Is specified Create or standardopenoption CREATE_ NEW,
If you use one of these flags and the code in your problem is called before newbufferedwriter, it should work in addition to some other problems (permissions):
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 }