This question already has answers here:
How do I check if a file exists in Java?
(19 answers)
Closed 7 years ago.
I would like to know how to open a file in java for writing, but I only want to open it if it exists already. Is that possible? I've searched around and found two suggestions so far which both don't meet my needs. One was to open a file for appending. The problem there is that if the file doesn't exist it will create it. The second was to use file.exists() first. That of course is not a valid solution as the file may exist when I call file.exists() but then not exist when I go to open the file. I want something similar to the Windows API OpenFile() in which I can pass OPEN_EXISTING flag such that the call will fail is the file doesn't exists. Does anything like that exist in java?
Only editing question because it was marked duplicate. Not sure why. I thought I was pretty specific about the other answers and why they were not sufficient.
So I'll restate, I want to open a file for writing. I want the open to fail if the file doesn't already exist.
exists() returns true if the file path is a valid directory even if the file isn't there. You can get around this by using:
File f = new File(filePathString);
if(f.exists() && !f.isDirectory()) {/*Do whatever*/}
or use:
File f = new File(filePathString);
if f.isFile() {/*Do whatever*/}
Just catch the FileNotFoundException that is thrown:
try (FileInputStream fis = new FileInputStream(file))
{
// ...
}
catch (FileNotFoundException exc)
{
// it didn't exist.
}
Solutions involving File.exists() and friends are vulnerable to timing-window problems and therefore cannot be recommended. They also merely duplicate what the OS already has to do, but at the wrong time, so they are a waste of time and space. You have to deal with IOExceptions anyway, so do that.
No there is nothing like that In Java.... Core library
You should be able to wrap your logic in a if statement that names use of the file.exists() method. If you do the check just before opening the file the you would be extremely unlucky if someone has deleted the file in-between. The method that checks if the file exists and the code to open the file and lock it should run in milliseconds..
Eg
If (file.exists() {
//Your Code goes here..
} else {
System.out.Print("missing file");
}
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.
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.
This question already has answers here:
Test if file exists
(7 answers)
Closed 9 years ago.
I'm tried to implement following if condition to skip the downloading process if the file found. But the if condition doesn't seem to be working and without if condition this works fine. can someone please help to solve this. I think, I used the if condition improperly.
File file = new File( Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.sample.project/files/images/");
if(file.getPath().equals(false)){
String url = "http://www.sample.com/example.zip";
new DownloadTask().execute( url );
}
#Julien is right. Actually you may try using exists() function of File class.
if (file.exists()){
//true
}else{
//false
}
There are many similar questions which may help:
Test if file exists
Check if a file exists before calling openFileInput
Check if file exists on SD card on Android
Android how to check if file exist and else create one?
How to check file exist or not and if not create a new file in sdcard in async task
Hope it helps.
This question already has answers here:
How do I read a resource file from a Java jar file?
(9 answers)
Closed 9 years ago.
I'm writing a game in java and all is working more or less well, as you would expect when coding, but one issue I have come across is reading the image and sound files into the game. I wrote a method that works really well within Eclipse, but as soon as I try to test it in a runnable jar (exported using Eclipse) my game gets stuck on the loading screen because it can't read the files. I realized the problem there being that you cannot create File objects within a Jar, you have to use streams. This could work, but the images/sounds are located within folders and I'm not very sure how you can read files within a folder with streams(i.e not knowing the amount of files). Because of this I have tried to rewrite the method using the ZipInputStream (I found this as recommended when looking for solutions prior to posting this). This is what the method looks like now:
imageMap = new HashMap<String, BufferedImage>();
String imagebase = "/images";
CodeSource src = PlatformerCanvas.class.getProtectionDomain().getCodeSource();
if(src != null)
{
URL jar = src.getLocation();
try
{
ZipArchiveInputStream zip = new ZipArchiveInputStream(jar.openStream());
ZipArchiveEntry ze = null;
while((ze = zip.getNextZipEntry()) != null)
{
System.out.println(ze.getName());
if(ze.getName().startsWith(imagebase) && ze.getName().endsWith(".png"))
{
loading++;
imageMap.put(ze.getName().replaceAll(imagebase + "/", ""), ImageIO.read(this.getClass().getResource(ze.getName())));
}
}
zip.close();
System.out.println("Finished Loading Images");
}
catch (IOException e)
{
e.printStackTrace();
}
}
However, this completely skips over the while loop because getNextZipEntry return null. I tried using the base Zip archive libraries, but someone recommended the Apache Commons libraries, but neither worked. My Jar setup is this:
Jar
/game/gameClasses
/images/imageFiles
/sounds/soundFiles
/whateverOtherFoldersEclipseCreated
So my question is this: Why isn't this current method working and how do I fix it? Or, how can I load the images/sounds in a different way that works?
I have looked at many other questions and tried many different things, but none worked for me.
Or, how can I load the images/sounds in a different way that works?
One common technique is to include a list of resources in a known location in the Jar. Read the list, then iterate the lines (presuming one line per resource) & read the paths that way.
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().