java.nio.file.NoSuchFileException: 为什么 nio 不创建文件
java.nio.file.NoSuchFileException: why nio not creating file
我正在使用 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)
我的问题是为什么没有创建文件?
请指教
感谢期待
更新答案:
现在您已经展示了完整的代码,还有两个主要问题:
您试图在确保指向该文件的目录存在之前打开该文件,并且
您正在使用 StandardOpenOption.APPEND
,但这不会 创建 文件;它将附加到 现有 文件。
...以及与实际代码行数相关的大量最佳实践问题。
查看评论:
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-resources
,close
是自动的(无论是在有异常还是没有异常时)。
或者,如果您真的想记录并继续:
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.
}
}
原答案:
您没有显示实际失败的代码,这是对 newBufferedWriter
的调用(this one, or this one). newBufferedWriter
takes OpenOption
s, the standard set of which are available from StandardOpenOption
. Make sure you've specified StandardOpenOption.CREATE
or StandardOpenOption.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
}
我正在使用 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)
我的问题是为什么没有创建文件?
请指教
感谢期待
更新答案:
现在您已经展示了完整的代码,还有两个主要问题:
您试图在确保指向该文件的目录存在之前打开该文件,并且
您正在使用
StandardOpenOption.APPEND
,但这不会 创建 文件;它将附加到 现有 文件。
...以及与实际代码行数相关的大量最佳实践问题。
查看评论:
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-resources
,close
是自动的(无论是在有异常还是没有异常时)。
或者,如果您真的想记录并继续:
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.
}
}
原答案:
您没有显示实际失败的代码,这是对 newBufferedWriter
的调用(this one, or this one). newBufferedWriter
takes OpenOption
s, the standard set of which are available from StandardOpenOption
. Make sure you've specified StandardOpenOption.CREATE
or StandardOpenOption.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
}