Can't delete file after being renamed (file is opened) - java

I am using icefaces to upload files to relative path in my web app (mywebapp/audio), then after the file is getting uploaded I rename it to save its extension as follows:
public static File changeExtToWav(FileInfo fileInfo,
StringBuffer originalFileName) {
log.debug("changeExtToWav");
int mid = fileInfo.getFile().getName().lastIndexOf(".");
String fileName = fileInfo.getFile().getName().substring(0, mid);
originalFileName.append(fileName);
log.debug("originalFileName: " + originalFileName);
String newFileName = fileName + "_" + new Date().getTime() + "."
+ "wav";
File newFile = new File(fileInfo.getFile().getParent() + "/"
+ newFileName);
log.debug("newFileName: " + newFile.getName());
fileInfo.getFile().renameTo(newFile);
return newFile;
}
after the file is getting uploaded, sometimes I want to delete it from UI button as follows:
try {
File fileToDelete = new File(filePath); // correct file path
log.debug("file exists: " + fileToDelete.exists()); // true
fileToDelete.delete();
} catch (Exception e) {
e.printStackTrace();
}
the file path is correct, and I get no exceptions, but the file is not deleted (I am using java 6 btw).
please advise how to fix this issue.
UPDATE: using the following useful method, I can get that the file is opened, any ideas how to close it ?
public String getReasonForFileDeletionFailureInPlainEnglish(File file) {
try {
if (!file.exists())
return "It doesn't exist in the first place.";
else if (file.isDirectory() && file.list().length > 0)
return "It's a directory and it's not empty.";
else
return "Somebody else has it open, we don't have write permissions, or somebody stole my disk.";
} catch (SecurityException e) {
return "We're sandboxed and don't have filesystem access.";
}
}

Well if the file is open, then there is two solutions :
You have a stream in your program open on this file. Note that afaik it's a problem on Windows, with Unix I can delete a File even if a stream is opened on it.
You have an other process using this file. So in this case you can't do anything from Java.
In the log it tells also that it can be a permission problem, are you sure you have enough privileges?
You can also use Files#delete(Path path) (jdk7) to have more details about the issue.

Related

How to differentiate between an empty file that has no extension and a directory in java?

Let's suppose I have a zip file containing two elements: elem1 (created by linux command touch elem1) and elem2 (created by linux command mkdir elem2)
Now, in java, I use the following code to extract the content of the zip
// ...
// Suppose we have a valid inputStream on a zip file
// ...
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
int entrySize = (int) entry.getSize();
File file = Paths.get(extractPath).resolve(entry.getName()).toFile();
if (/*Condition to detect a directory*/) {
System.out.println("This is a directory");
FileUtils.forceMkdir(file);
} else if (/*Condition to detect an empty file*/) {
System.out.println("This is an empty file");
} else {
System.out.println("This is something else");
}
entry = zipInputStream.getNextEntry();
}
I would like to specify the right conditions to detect whether entry is a directory, or an empty file without extension. Knowing that these entries are still in memory and do not exist on the filesystem, the command file.isDirectory() always returns false; so I cannot not use it to check for directory.
Any ideas please ?
I created both an empty folder and an empty file without extension and evaluated them with the code below:
public static void main(String[] args) {
String path = System.getProperty("user.home") + File.separator + "Desktop" + File.separator;
File file = new File(path + "EmptyFile");
File folder = new File (path + "EmptyFolder");
System.out.println("Is 'folder' a folder? " + (Files.isDirectory(folder.toPath())? "Yes" : "No" ));
System.out.println("Is 'file' a folder? " + (Files.isDirectory(file.toPath())? "Yes" : "No" ));
}
The (not surprising) result:
Is 'folder' a folder? Yes
Is 'file' a folder? No
The reason why this works is because the function Files.isDirectory(...) looks in the file attributes set by the Operating System to determine whether the item being examined is a "File folder" or simply a "file". My assumption is that Zip programs do not contain such metadata (not even Windows zip). Therefore, "isDirectory" test cannot be performed using the Files.isDirectory(...) function. My quick research discovered that, the way to do this (and I am kind of shocked) is by examining the file name and check to see if the name ends with the file separator. In fact, this is how ZipEntry.isDirectory() works.
Attempting to zip an empty folder is not allowed for Windows zip (maybe allowed with other software?). However, I was able to include empty directories with 7-zip. That wasn't the only difference. The isDirectory() test failed when the zip was created with Windows zip because the file was skipped altogether. So, in order for this to work, create the zip file with zip software other than the one that comes with Windows. Then,
public static void main(String[] args) throws IOException {
String path = System.getProperty("user.home") + File.separator + "Desktop" + File.separator;
FileInputStream inputStream = new FileInputStream(path + "Desktop.zip");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
File file = Paths.get(entry.getName()).toFile();
if (entry.isDirectory()) {
System.out.println(entry.getName() + " is a directory");
} else if (file.getName().endsWith(".lnk")) {
System.out.println(file.getName() + " is a shortcut");
} else {
System.out.println(entry.getName() + " is a file");
}
entry = zipInputStream.getNextEntry();
}
zipInputStream.close();
}
Outputs for me:
EmptyFile is a file
EmptyFolder/ is a directory
How We Test Wireless Routers _ PCMag_files/ is a directory
How We Test Wireless Routers _ PCMag_files/00hSyhn9j5PNrcOot1tMzz9.1578945749.fit_lim.size_100x100.png is a file
...
etc
One last note... obviously, if a ZipEntry is not a directory, it is a file. Therefore, no else if is needed. That is, unless you would like to make a distinction between file types. In the example above, I wanted to check if a particular file was a shortcut. Just keep in mind that this is not necessary. The logic should only test entries for isDirectory and if the test fails, it is simply a file.

Deleting a txt File [duplicate]

This is currently what I have to delete the file but it's not working. I thought it may be permission problems or something but it wasn't. The file that I am testing with is empty and exists, so not sure why it doesn't delete it.
UserInput.prompt("Enter name of file to delete");
String name = UserInput.readString();
File file = new File("\\Files\\" + name + ".txt");
file.delete();
Any help would be GREATLY appreciated!
I now have:
File file = new File(catName + ".txt");
String path = file.getCanonicalPath();
File filePath = new File(path);
filePath.delete();
To try and find the correct path at run time so that if the program is transferred to a different computer it will still find the file.
The problem could also be due to any output streams that you have forgotten to close. In my case I was working with the file before the file being deleted. However at one place in the file operations, I had forgotten to close an output stream that I used to write to the file that was attempted to delete later.
Be sure to find out your current working directory, and write your filepath relative to it.
This code:
File here = new File(".");
System.out.println(here.getAbsolutePath());
... will print out that directory.
Also, unrelated to your question, try to use File.separator to remain OS-independent. Backslashes work only on Windows.
I got the same problem! then realized that my directory was not empty. I found the solution in another thread: not able to delete the directory through Java
/**
* Force deletion of directory
* #param path
* #return
*/
static public boolean deleteDirectory(File path) {
if (path.exists()) {
File[] files = path.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteDirectory(files[i]);
} else {
files[i].delete();
}
}
}
return (path.delete());
}
Try closing all the FileOutputStream/FileInputStream you've opened earlier in other methods ,then try deleting ,worked like a charm.
I suspect that the problem is that the path is incorrect. Try this:
UserInput.prompt("Enter name of file to delete");
String name = UserInput.readString();
File file = new File("\\Files\\" + name + ".txt");
if (file.exists()) {
file.delete();
} else {
System.err.println(
"I cannot find '" + file + "' ('" + file.getAbsolutePath() + "')");
}
If you want to delete file first close all the connections and streams.
after that delete the file.
In my case it was the close() that was not executing due to unhandled exception.
void method() throws Exception {
FileInputStream fis = new FileInputStream(fileName);
parse(fis);
fis.close();
}
Assume exception is being thrown on the parse(), which is not handled in this method and therefore the file is not closed, down the road, the file is being deleted, and that delete statement fails, and do not delete.
So, instead I had the code like this, then it worked...
try {
parse(fis);
}
catch (Exception ex) {
fis.close();
throw ex;
}
so basic Java, which sometimes we overlook.
As other answers indicate, on Windows you cannot delete a file that is open. However one other thing that can stop a file from being deleted on Windows is if it is is mmap'd to a MappedByteBuffer (or DirectByteBuffer) -- if so, the file cannot be deleted until the byte buffer is garbage collected. There is some relatively safe code for forcibly closing (cleaning) a DirectByteBuffer before it is garbage collected here: https://github.com/classgraph/classgraph/blob/master/src/main/java/nonapi/io/github/classgraph/utils/FileUtils.java#L606 After cleaning the ByteBuffer, you can delete the file. However, make sure you never use the ByteBuffer again after cleaning it, or the JVM will crash.

copyFile works in IDE but not in production

I need to copy a file from a working directory to an archiving directory, so I use the following code:
private void copyToArchive(Date today) {
try {
File source = new File("final.txt");
String msg = "getting source file " + source;
displayMessage(msg, good); // good points to a sound file
File destination = new File("archives\\final." + today + ".txt");
msg = "getting destination file " + destination;
displayMessage(msg, good);
FileUtils.copyFile(source, destination);
msg = "finished trying to copy file";
displayMessage(msg, good);
} catch (IOException ex) {
String message = "archiving failed";
displayMessage(message, bad);
Logger.getLogger(FileManagerController.class.getName()).log(Level.SEVERE, null, ex);
}
}
The thing is, this works fine in the IDE, but in production it only succeeds as far as the declaration of "destination." In the IDE I get the "finished trying to copy file" notification (as well as the copied file in the subdirectory "archives"), but in production I get NEITHER the confirmation NOR the "archiving failed" notification from the IOException catch (and no copied file in the subdirectory).
Help?
(I run NetBeans 7.4 and the program runs on JDK version 1.7.0_55 (can't upgrade because another java program we run will not run on later java versions)).
I am not sure if it is your problem or not, but
File destination = new File("archives\\final." + today + ".txt");
should probably be
File destination = new File("archives","final." + today + ".txt");
for portability to file systems where \\ is not the directory separator.
You can try to use the Java Working Directory. It can be retrieved with:
String workingDir = System.getProperty("user.dir");
This will return your project's path.
So, on your case, your code would look like:
private void copyToArchive(Date today) {
try {
File source = new File("final.txt");
String msg = "getting source file " + source;
displayMessage(msg, good); // good points to a sound file
File destination = new File(workingDir + "archives\\final." + today + ".txt");
msg = "getting destination file " + destination;
displayMessage(msg, good);
FileUtils.copyFile(source, destination);
msg = "finished trying to copy file";
displayMessage(msg, good);
} catch (IOException ex) {
String message = "archiving failed";
displayMessage(message, bad);
Logger.getLogger(FileManagerController.class.getName()).log(Level.SEVERE, null, ex);
}
}
IMPORTANT: maybe you would need as well writing file permissions. Here you have a very good example of how to read/set rights: http://www.mkyong.com/java/how-to-set-the-file-permission-in-java/

Can't delete file in java on windows ....?

I am trying to use file.delete() but it does not delete file ? I tested it on linux it delete files but on windows it does not delete file why..?
code :
private File getFiletobeUpload(File foto) {
boolean errorRename = true;
File uploadFile = null;
File testFile = foto;
String subdirname = this.checkDir(foto);
if (testFile.canWrite()) {
uploadFile = new File(AppConstants.PHOTOPATH + "/" + subdirname + "/" + testFile.getName());
try {
FileInputStream origStream = new FileInputStream(testFile);
FileOutputStream outStream = new FileOutputStream(uploadFile);
origStream.getChannel().transferTo(0, testFile.length(), outStream.getChannel());
origStream.close();
origStream = null;
outStream.close();
outStream = null;
} catch (Exception e) {
this.errorString += "error while writing to orig dir";
logger.error(e);
}
errorRename = !testFile.delete();
if (errorRename) {
this.errorString += "error while deleting the file";
}
}
testFile = null;
return uploadFile;
}
your code seems a bit odd, you are checking "testFile" for write access but then actually reading from it (FileInputStream). Is the first try/catch block running without exception? Maybe you should check if the file even exists:
System.out.println("File exists: "+testFile.exists());
errorRename = !testFile.delete();
Also if you just want to rename a file, use:
file.renameTo(File dest)
A general suggestion: consider using the classes in the java.nio package to your file IO if you can (not sure which version of Java you're running with) because the error handling is improved and you should be able to find a more specific reason for the failure based on the type of exception thrown and the exception message.
As per API, the disk-drive specifier - "/" for the UNIX root directory, and "\\" for a Microsoft Windows UNC pathname.
so for windows:
uploadFile = new File(AppConstants.PHOTOPATH + "\\" + subdirname + "\\" + testFile.getName());

Why am I having nondeterministic file deletion errors when using DiskFileItem?

My upload servlet keeps throwing me an exception saying that the file that I'm trying to replace (near the end of my code) could not be deleted at (seemingly) random. I don't know what's causing this since I'm not using any streams and the file isn't open in my browser. Does anyone know what could be causing this? I'm completely clueless on this one as the code seems correct to me. This is the first time I've used DiskFileItem so I'm not sure if there are any nuances to handle there.
Keep in mind that it sometimes works, sometimes doesn't. I'm lost on that.
Problem Area:
File destination = new File(wellnessDir + File.separator + fileName + ".pdf");
System.out.println("destination file exists: " + destination.exists());
System.out.println("file to be moved exists: " + uploadedFile.exists());
if(destination.exists()){
boolean deleted = destination.delete();
if(!deleted)
throw new Exception("Could not delete file at " + destination);
}
My System outs always say that both file and destination exist. I'm trying to get the upload to overwrite the existing file.
Full code: (& pastebin)
private void uploadRequestHandler(ServletFileUpload upload, HttpServletRequest request)
{
// Handle the request
String fileName = "blank";
try{
List items = upload.parseRequest(request);
//Process the uploaded items
Iterator iter = items.iterator();
File uploadedFile = new File(getHome() + File.separator + "temp");
if(uploadedFile.exists()){
boolean tempDeleted = uploadedFile.delete();
if(!tempDeleted)
throw new Exception("Existing temp file could not be deleted.");
}
//write the file
while (iter.hasNext()) {
DiskFileItem item = (DiskFileItem) iter.next();
if(item.isFormField()){
String fieldName = item.getFieldName();
String fieldValue = item.getString();
if(fieldName.equals("fileName"))
fileName = fieldValue;
//other form values would need to be handled here, right now only need for fileName
}else{
item.write(uploadedFile);
}
}
if(fileName.equals("blank"))
throw new Exception("File name could not be parsed.");
//move file
File wellnessDir = new File(getHome() + File.separator + "medcottage" + File.separator + "wellness");
File destination = new File(wellnessDir + File.separator + fileName + ".pdf");
System.out.println("destination file exists: " + destination.exists());
System.out.println("file to be moved exists: " + uploadedFile.exists());
if(destination.exists()){
boolean deleted = destination.delete();
if(!deleted)
throw new Exception("Could not delete file at " + destination);
}
FileUtil.move(uploadedFile, new File(wellnessDir + File.separator + fileName + ".pdf"));
writeResponse();
} catch (Exception e) {
System.out.println("Error handling upload request.");
e.printStackTrace();
}
}
edit: to add, getHome() and "home" aren't really in the code, that's just to protect my home path
After much testing and aggravation, finally tried it on a different machine, same code, worked great. Has something to do with me transferring domains on my work machine and it messing with permissions.

Categories