I have a method that writes to a log file. If the file exists it should append to it, if not then I want it to create a new file.
if (!file.exists() && !file.createNewFile()) {
System.err.println("Error with output file: " + outFile
+ "\nCannot create new file.");
continue;
}
I have that to check that a file can be created. file is a java.io.File object. createNewFile is throwing an IOException: No such file or directory. This method has been working perfectly since I wrote it a few weeks ago and has only recently starting doing this although I don't know what I could have changed. I have checked, the directory exists and I have write permissions for it, but then I thought it should just return false if it can't make the file for any reason.
Is there anything that I am missing to get this working?
try to ensure the parent directory exists with:
file.getParentFile().mkdirs()
Perhaps the directory the file is being created in doesn't exist?
normally this is something you changed recently, first off your sample code is if not file exists and not create new file - you are trying to code away something - what is it?
Then, look at a directory listing to see if it actually exists and do a println / toString() on the file object and getMessage() on the exception, as well as print stack trace.
Then, start from zero knowledge again and re factor from the get-go each step you are using to get here. It's probably a duh you stuck in there somewhere while conceptualizing in code ( because it was working ) - you just retrace each step in detail, you will find it.
I think the exception you get is likely the result from the file check of the atomic method file.createNewFile(). The method can't check if the file does exist because some of the parent directories do not exist or you have no permissions to access them. I would suggest this:
if (file.getParentFile() != null && !file.getParentFile().mkDirs()) {
// handle permission problems here
}
// either no parent directories there or we have created missing directories
if (file.createNewFile() || file.isFile()) {
// ready to write your content
} else {
// handle directory here
}
If you take concurrency into account, all these checks are useless because in every case some other thread is able to create, delete or do anything else with your file. In this case you have to use file locks which I would not suggest doing ;)
According to the [java docs](http://java.sun.com/j2se/1.5.0/docs/api/java/io/File.html#createNewFile() ) createNewFile will create a new file atomically for you.
Atomically creates a new, empty file named by this abstract pathname if and only if a file with this name does not yet exist.
Given that createNewFile is atomic and won't over-write an existing file you can re-write your code as
try {
if(!file.createNewFile()) {
System.out.println("File already exists");
}
} catch (IOException ex) {
System.out.println(ex);
}
This may make any potential threading issues, race-conditions, etc, easier to spot.
You are certainly getting this Exception
'The system cannot find the path specified'
Just print 'file.getAbsoluteFile()' , this will let you know what is the file you wanted to create.
This exception will occur if the Directory where you are creating the file doesn't exist.
//Create New File if not present
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
Log.e(TAG, "File Created");
}
This could be a threading issue (checking and creating together are not atomic: !file.exists() && !file.createNewFile()) or the "file" is already a directory.
Try (file.isFile()) :
if (file.exists() && !file.isFile()){
//handle directory is there
}else if(!file.createNewFile()) {
//as before
}
In my case was just a lack of permission:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Use
yourAppsMainActivityContext.getExternalCacheDir()
instead of
Environment.getExternalStorageDriectory()
to get the file storage path.
Alternatively, you can also try getExternalFilesDir(String type), getExternalCacheDir(), getExternalMediaDirs().
Related
I'm trying to check does file exist but it doesn't work.
FileSystem fs = FileSystems.getDefault();
Path p = fs.getPath(fileName);
if(!Files.exists(p)) {
create(fileName);
} else {
throw new ConflictException(String.format("File already exist."));
}
The problem is that even the file exist with same fileName it goes inside if statement and goes to create method and when it came to part to create file then it returns exception that file already exists.
What could be the problem and possible solution to check does file/directory exists if I'm using FileSystem?
You're doing it wrong.
The general principle when working in environments subject to external change, such as file systems, you just cannot do check-and-act. That entire principle is broken in such an environment, and you're doing it here:
You check if the file exists, and then depending on the result of that, you choose an action. That's check-and-act and doesn't work.
After all, what if the 'answer' to your check changes in between the check and the act? It doesn't even have to be another thread within your own VM, it can be another process. You can't synchronize on anything to get this job done 'safely' either.
No, the right principle is act-then-check. Do the operation 'make this file but only if it is not already there', atomically, and deal with the fallout, that is, deal with the error afterwards if the file already existed.
Java's nio has support for this, fortunately (the old File API does not, don't use that). Lastly, there is no need to go via the FileSystem stuff, not as long as you are using the default filesystem. However, if that was just there for the purposes of simplifying the question, this works just as well with a custom filesystem:
Path p = Paths.get(fileName);
try {
try (var out = Files.newOutputStream(p, StandardOpenOption.CREATE_NEW)) {
// write your file here
}
} catch (FileAlreadyExistsException e) {
throw new ConflictException(String.format("File already exists", e);
}
// CREATE_NEW is the magic voodoo here: That tells java:
// do this ONLY if you make a new file, otherwise don't do it, atomically.
though note that FAEException is fine as is, so I'm not sure you should neccessarily wrap that into a conflictexception - that only makes sense if this API has abstracted away the notion that you are doing this thing to the filesystem (you did not include a method name or javadoc in your paste, so I can't tell).
If you don't need to write anything to the file, you don't need newOutputStream, you can just go with:
Path p = Paths.get(fileName);
try {
Files.createFile(p);
} catch (FileAlreadyExistsException e) {
throw new ConflictException(String.format("File already exists", e);
}
// Files.createFile implies CREATE_NEW already; it either makes
// the file and returns, or doesn't and throws FAEEx.
The problem I am having is that when I attempt to create the folder, it doesn't create. It might have something to do with the directory, but honestly I don't know. I tried using this:
File f = new File(javax.swing.filechooser.FileSystemView.getFileSystemView().getHomeDirectory() + "/Levels/First Folder/Levels");
try{
if(f.mkdir()) {
System.out.println("Directory Created");
} else {
System.out.println("Directory is not created");
}
} catch(Exception e){
e.printStackTrace();
}
But it didn't work for me.
And this is the directory I put in the File, but I want the program to work on any computer: C:\Users\(My name)\Desktop\Levels\First Folder\Levels
You said only the Desktop directory exists, so you'll need to use mkdirs to construct the whole directory tree:
File f = new File(javax.swing.filechooser.FileSystemView.getFileSystemView().getHomeDirectory() + "/Levels/First Folder/Levels");
try{
if(f.mkdirs()) { //< plural
System.out.println("Directory Created");
Keep in mind: you may want to check whether this directory exists before you try to create it, as it presumably isn't an error and is permissible to continue if your program has created it once before.
Recommending Files.createDirectories() instead of File.mkdirs() because handling errors is more straightforward.
Thus:
Files.createDirectories(Paths.get(System.getProperty("user.home"), "/Levels/First Folder/Levels"));
With mkdirs() it is difficult to determine if it failed, why it failed, or if it did not create the directory because it already existed.
I need to write a custom batch File renamer. I've got the bulk of it done except I can't figure out how to check if a file is already open. I'm just using the java.io.File package and there is a canWrite() method but that doesn't seem to test if the file is in use by another program. Any ideas on how I can make this work?
Using the Apache Commons IO library...
boolean isFileUnlocked = false;
try {
org.apache.commons.io.FileUtils.touch(yourFile);
isFileUnlocked = true;
} catch (IOException e) {
isFileUnlocked = false;
}
if(isFileUnlocked){
// Do stuff you need to do with a file that is NOT locked.
} else {
// Do stuff you need to do with a file that IS locked
}
(The Q&A is about how to deal with Windows "open file" locks ... not how implement this kind of locking portably.)
This whole issue is fraught with portability issues and race conditions:
You could try to use FileLock, but it is not necessarily supported for your OS and/or filesystem.
It appears that on Windows you may be unable to use FileLock if another application has opened the file in a particular way.
Even if you did manage to use FileLock or something else, you've still got the problem that something may come in and open the file between you testing the file and doing the rename.
A simpler though non-portable solution is to just try the rename (or whatever it is you are trying to do) and diagnose the return value and / or any Java exceptions that arise due to opened files.
Notes:
If you use the Files API instead of the File API you will get more information in the event of a failure.
On systems (e.g. Linux) where you are allowed to rename a locked or open file, you won't get any failure result or exceptions. The operation will just succeed. However, on such systems you generally don't need to worry if a file is already open, since the OS doesn't lock files on open.
// TO CHECK WHETHER A FILE IS OPENED
// OR NOT (not for .txt files)
// the file we want to check
String fileName = "C:\\Text.xlsx";
File file = new File(fileName);
// try to rename the file with the same name
File sameFileName = new File(fileName);
if(file.renameTo(sameFileName)){
// if the file is renamed
System.out.println("file is closed");
}else{
// if the file didnt accept the renaming operation
System.out.println("file is opened");
}
On Windows I found the answer https://stackoverflow.com/a/13706972/3014879 using
fileIsLocked = !file.renameTo(file)
most useful, as it avoids false positives when processing write protected (or readonly) files.
org.apache.commons.io.FileUtils.touch(yourFile) doesn't check if your file is open or not. Instead, it changes the timestamp of the file to the current time.
I used IOException and it works just fine:
try
{
String filePath = "C:\sheet.xlsx";
FileWriter fw = new FileWriter(filePath );
}
catch (IOException e)
{
System.out.println("File is open");
}
I don't think you'll ever get a definitive solution for this, the operating system isn't necessarily going to tell you if the file is open or not.
You might get some mileage out of java.nio.channels.FileLock, although the javadoc is loaded with caveats.
Hi I really hope this helps.
I tried all the options before and none really work on Windows. The only think that helped me accomplish this was trying to move the file. Event to the same place under an ATOMIC_MOVE. If the file is being written by another program or Java thread, this definitely will produce an Exception.
try{
Files.move(Paths.get(currentFile.getPath()),
Paths.get(currentFile.getPath()), StandardCopyOption.ATOMIC_MOVE);
// DO YOUR STUFF HERE SINCE IT IS NOT BEING WRITTEN BY ANOTHER PROGRAM
} catch (Exception e){
// DO NOT WRITE THEN SINCE THE FILE IS BEING WRITTEN BY ANOTHER PROGRAM
}
If file is in use FileOutputStream fileOutputStream = new FileOutputStream(file); returns java.io.FileNotFoundException with 'The process cannot access the file because it is being used by another process' in the exception message.
I had some new code using the commons-io FileUtils.openOutputStream(File) method, for a file that doesn't exist at the point of the call. This was failing with a "FileNotFoundException". I first thought this was a bug in commons-io, but then I realized that it's just calling "new FileOutputStream(file, append)", which is also supposed to create the file if it doesn't exist.
I then added code right before my call to FileUtils.openOutputStream(File) like the following:
if (!file.exists()) {
logger.info("Parent file exists: " + file.getParentFile().exists());
try {
file.createNewFile();
}
catch (Exception ex) {
logger.error("Creating file failed", ex);
}
}
This prints "true" for the parent file, and then "java.io.IOException: The system cannot find the path specified". I googled for this situation, and some people were hitting this if they went past the supposed 260 character limit for a file path on Windows. I thought that might be relevant, but my file path is only 230 characters long.
I also tried an experiment of trying to "touch" the same file path in my Cygwin bash shell, and it had no trouble doing that.
Update:
So I took the partial advice of trying to use Paths & Files to do this instead of just "File". My incoming parameter is a "File", so I can't do anything about that. I added the following code:
try {
Path path = Paths.get(file.getAbsolutePath()).toAbsolutePath();
if (!Files.exists(path.getParent())) {
Files.createDirectories(path);
}
file = Files.createFile(path).toFile();
}
catch (Exception ex) {
logger.error("Failed to create file");
}
What's curious is that this doesn't give me a better error message. In fact, it doesn't give me any error message, because it doesn't fail. It appears that NIO is taking a very different path to creating the file than the regular File object.
Update:
What is now working fine is the following:
file = Paths.get(file.getAbsolutePath()).toAbsolutePath().toFile();
try {
Path path = file.toPath();
if (!Files.exists(path.getParent())) {
Files.createDirectories(path);
}
if (!file.exists()) {
file = Files.createFile(path).toFile();
}
}
catch (Exception ex) {
logger.error("Failed to create file");
}
What's curious is that I should be able to remove that first line, which is essentially converting a relative path to an absolute path. My test run creates 50 or so files in the process. I tried commenting out that line and then clearing out my output tree and running the test. It got the following exception attempting to create the first file:
java.nio.file.AccessDeniedException: build\gen1\org\opendaylight\yang\gen\v1\urn\opendaylight\params\xml\ns\yang\pcep\types\rev131005\vs\tlv\vs\tlv\VendorPayload.java
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83)
What the heck?
Also note that I never did remove the older code that uses "File.createNewFile()", I just put the "Files" code before that, and the old code checks for "!file.exists()", so theoretically the old code would only execute if the new code somehow didn't create the file. On this first file, since the NIO creation failed, the file still didn't exist, and it went through the old creation code, which SUCCEEDED.
And even stranger, I let the test case run to the next file, and that failed in the NEW code with:
java.nio.file.FileAlreadyExistsException: build\gen1\org\opendaylight\yang\gen\v1\urn\opendaylight\params\xml\ns\yang\pcep\types\rev131005\vs\tlv\VsTlv.java
Note that the only way that block could have gotten that exception is if it executed the "Files.createFile(path).toFile()" line, and the only way it could have gotten to that line is if "!file.exists()" was TRUE, which means that the file did not exist. my brain is starting to melt. Also note that while I'm sitting at this breakpoint, I examined the file system, and that file does not exist.
This is 2015 and you say that you use Java 7.
Don't use File. Use this instead:
final Path path = Paths.get("....").toAbsolutePath();
// use Files.exists(path.getParent()) to check for the existence;
// if it doesn't exist use Files.createDirectories() on it
Files.createFile(thePath);
If the operation fails, you will at least get a meaningful exception telling you why it fails.
This is 2015. Drop. File. Now.
How can I check whether a file exists, before opening it for reading in Java (the equivalent of Perl's -e $filename)?
The only similar question on SO deals with writing the file and was thus answered using FileWriter which is obviously not applicable here.
If possible I'd prefer a real API call returning true/false as opposed to some "Call API to open a file and catch when it throws an exception which you check for 'no file' in the text", but I can live with the latter.
Using java.io.File:
File f = new File(filePathString);
if(f.exists() && !f.isDirectory()) {
// do something
}
I would recommend using isFile() instead of exists(). Most of the time you are looking to check if the path points to a file not only that it exists. Remember that exists() will return true if your path points to a directory.
new File("path/to/file.txt").isFile();
new File("C:/").exists() will return true but will not allow you to open and read from it as a file.
By using nio in Java SE 7,
import java.nio.file.*;
Path path = Paths.get(filePathString);
if (Files.exists(path)) {
// file exist
}
if (Files.notExists(path)) {
// file is not exist
}
If both exists and notExists return false, the existence of the file cannot be verified. (maybe no access right to this path)
You can check if path is a directory or regular file.
if (Files.isDirectory(path)) {
// path is directory
}
if (Files.isRegularFile(path)) {
// path is regular file
}
Please check this Java SE 7 tutorial.
Using Java 8:
if(Files.exists(Paths.get(filePathString))) {
// do something
}
File f = new File(filePathString);
This will not create a physical file. Will just create an object of the class File. To physically create a file you have to explicitly create it:
f.createNewFile();
So f.exists() can be used to check whether such a file exists or not.
f.isFile() && f.canRead()
There are multiple ways to achieve this.
In case of just for existence. It could be file or a directory.
new File("/path/to/file").exists();
Check for file
File f = new File("/path/to/file");
if(f.exists() && f.isFile()) {}
Check for Directory.
File f = new File("/path/to/file");
if(f.exists() && f.isDirectory()) {}
Java 7 way.
Path path = Paths.get("/path/to/file");
Files.exists(path) // Existence
Files.isDirectory(path) // is Directory
Files.isRegularFile(path) // Regular file
Files.isSymbolicLink(path) // Symbolic Link
Don't. Just catch the FileNotFoundException. The file system has to test whether the file exists anyway. There is no point in doing all that twice, and several reasons not to, such as:
double the code
the timing window problem whereby the file might exist when you test but not when you open, or vice versa, and
the fact that, as the existence of this question shows, you might make the wrong test and get the wrong answer.
Don't try to second-guess the system. It knows. And don't try to predict the future. In general the best way to test whether any resource is available is just to try to use it.
You can use the following: File.exists()
first hit for "java file exists" on google:
import java.io.*;
public class FileTest {
public static void main(String args[]) {
File f = new File(args[0]);
System.out.println(f + (f.exists()? " is found " : " is missing "));
}
}
For me a combination of the accepted answer by Sean A.O. Harney and the resulting comment by Cort3z seems to be the best solution.
Used the following snippet:
File f = new File(filePathString);
if(f.exists() && f.isFile()) {
//do something ...
}
Hope this could help someone.
I know I'm a bit late in this thread. However, here is my answer, valid since Java 7 and up.
The following snippet
if(Files.isRegularFile(Paths.get(pathToFile))) {
// do something
}
is perfectly satifactory, because method isRegularFile returns false if file does not exist. Therefore, no need to check if Files.exists(...).
Note that other parameters are options indicating how links should be handled. By default, symbolic links are followed.
From Java Oracle documentation
It's also well worth getting familiar with Commons FileUtils https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/FileUtils.html
This has additional methods for managing files and often better than JDK.
Simple example with good coding practices and covering all cases :
private static void fetchIndexSafely(String url) throws FileAlreadyExistsException {
File f = new File(Constants.RFC_INDEX_LOCAL_NAME);
if (f.exists()) {
throw new FileAlreadyExistsException(f.getAbsolutePath());
} else {
try {
URL u = new URL(url);
FileUtils.copyURLToFile(u, f);
} catch (MalformedURLException ex) {
Logger.getLogger(RfcFetcher.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(RfcFetcher.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Reference and more examples at
https://zgrepcode.com/examples/java/java/nio/file/filealreadyexistsexception-implementations
Don't use File constructor with String.
This may not work!
Instead of this use URI:
File f = new File(new URI("file:///"+filePathString.replace('\\', '/')));
if(f.exists() && !f.isDirectory()) {
// to do
}
You can make it this way
import java.nio.file.Paths;
String file = "myfile.sss";
if(Paths.get(file).toFile().isFile()){
//...do somethinh
}
There is specific purpose to design these methods. We can't say use anyone to check file exist or not.
isFile(): Tests whether the file denoted by this abstract pathname is a normal file.
exists(): Tests whether the file or directory denoted by this abstract pathname exists.
docs.oracle.com
You must use the file class , create a file instance with the path of the file you want to check if existent . After that you must make sure that it is a file and not a directory . Afterwards you can call exist method on that file object referancing your file . Be aware that , file class in java is not representing a file . It actually represents a directory path or a file path , and the abstract path it represents does not have to exist physically on your computer . It is just a representation , that`s why , you can enter a path of a file as an argument while creating file object , and then check if that folder in that path does really exist , with the exists() method .
If spring framework is used and the file path starts with classpath:
public static boolean fileExists(String sFileName) {
if (sFileName.startsWith("classpath:")) {
String path = sFileName.substring("classpath:".length());
ClassLoader cl = ClassUtils.getDefaultClassLoader();
URL url = cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path);
return (url != null);
} else {
Path path = Paths.get(sFileName);
return Files.exists(path);
}
}