Can I do this on Java? I'm using windows...
http://java.sun.com/j2se/1.6.0/docs/api/java/io/File.html#setReadOnly%28%29
File file = new File("foo.bar");
if(file.setReadOnly()) {
System.out.println("Successful");
}
else {
System.out.println("All aboard the fail train.");
}
Before Java6, you could not undo this. To get around this, they put in File.setWritable(boolean) which can be used as so
File file = new File("foo.bar");
if(file.setWritable(false)) {
System.out.println("Successful");
}
else {
System.out.println("All aboard the fail train.");
}
if(file.setWritable(true)) {
System.out.println("Re-enabled writing");
}
else {
System.out.println("Failed to re-enable writing on file.");
}
public boolean setWritable(boolean writable)
final File f = new File(...);
f.setWritable(true);
Will change premissions to writable (not read-only).
Note: this may not work all the times, as the underlying FileSystem may deny the request. But it works on most files on your hard drives.
Related
I have an android app that needs to be able to delete large directories quickly. I know that when an app has a lot of data, the OS is able to clear the data app instantly (from app settings). However, when I manually try to delete a directory with a background task, looping through the folders and deleting the files takes a long time (several minutes) to complete. How does the OS delete data so quickly, but when it is done in code, it takes such a long time? Is there a faster way to do it?
private boolean deleteDirectory(String dir) {
Log.d(TAG, "deleteDirectory");
// If dir is not separated from the end of the character to the file, the file is automatically added delimiter
if (!dir.endsWith(File.separator))
dir = dir + File.separator;
File dirFile = new File(dir);
// If dir corresponding file does not exist or is not a directory, then exit
if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
return false;
}
boolean flag = true;
// delete all the files in the folder, including subdirectories
File[] files = dirFile.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
final int count = i;
// delete subfolders
if (files[i].isFile()) {
try {
FileUtils.forceDelete(files[count]);
} catch (IOException e) {
Log.e(TAG, e.getLocalizedMessage(), e);
}
} else if (files[i].isDirectory()) {
flag = deleteDirectory(files[i]
.getAbsolutePath());
}
if (dir == path) {
Log.d(TAG, "delete dir: " + dirFile);
curPosi++;
publishProgress(curPosi);
}
}
}
if (!flag) {
return false;
}
// delete the current directory
if (dirFile.delete()) {
return true;
} else {
return false;
}
}
I'm pretty sure that the OS deletes it at a lower level, by accessing the actual filesystem. Either way, you should try using the Apache Commons FileUtils library -- it has a deleteDirectory() method, which will save you a lot of recursion.
Alternatively, you can actually try to run "rm -rf" directly, using runtime.exec(), but I'm not sure that permissions it would require. Here's an example
I have two method - one to write, second to rename file:
public void writeToFile(File file, String content, boolean isLastLine) {
Optional<File> optionalFile = Optional.ofNullable(file);
if (!isLastLine)
content += System.lineSeparator();
try {
Files.write(
optionalFile.orElseThrow(() -> new RuntimeException("File couldn't be find")).toPath(),
content.getBytes(),
StandardOpenOption.APPEND, StandardOpenOption.SYNC);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void renameFile(File fileToRename, String newFileName) {
Optional<File> optionalFile = Optional.ofNullable(fileToRename);
File finalBikFileName = new File(newFileName);
if (!optionalFile.orElseThrow(() -> new RuntimeException("File couldn't be find or doesn't exist")).renameTo(finalBikFileName)) {
throw new RuntimeException("File couldn't be saved - already exists or some other issues");
}
}
public void renameFile(File fileToRename, String newFileName) {
Optional<File> optionalFile = Optional.ofNullable(fileToRename);
File finalBikFileName = new File(newFileName);
if (!optionalFile.orElseThrow(() -> new RuntimeException("File couldn't be find or doesn't exist")).renameTo(finalBikFileName)) {
throw new RuntimeException("File couldn't be saved - already exists or some other issues");
}
}
This is normal class, in application deployed on wildfly. I tested it in many ways. If I comment the write function then rename function is working proper. But if I first write something to file and then I want to rename then i got "action cannot be completed because the file is open in another program" Also i cant touch this file in windows explorer - i can't rename or delete. What can be a reason? How can I unlock it?
1) Is it different threads (or server requests) that call the writeToFile and the renameFile methods? Or both methods are calling one after other under same thread/request?
2) How much data (content.length I mean) are you writing? Just want to make sure SYNC is done before the RENAME.
Although there are many questions here that involve errors with naming files, the code below tries to implement those examples but fails to actually change the name of the file in the system for no apparent reason.
public static void main(String[] args)
{
File dir = new File("E:/Vglut2 pharmacology/60730/");
File[] directoryListing = dir.listFiles();
for (File filius : directoryListing) {
try
{
String oldName = filius.getName();
int imgNum = returnImageNumber(oldName);
double imgMag = returnImageMagnification(oldName);
String newName = oldName.substring(0, oldName.indexOf('_')).concat('_' + String.valueOf(imgNum)).concat('_' + String.valueOf(imgMag));
File nova = new File(newName);
filius.renameTo(nova);
System.out.println(newName);
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
The resulting string that I tested by printing offers the desired resulting final name, however, in the end, the filesystem remains unchanged. A similar example from a previous stack overflow question is as seen below-
File dir = new File("D:/xyz");
if (dir.isDirectory()) { // make sure it's a directory
for (final File f : dir.listFiles()) {
try {
File newfile =new File("newfile.txt");
if(f.renameTo(newfile)){
System.out.println("Rename succesful");
}else{
System.out.println("Rename failed");
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
As seen there are no significant differences that I can tell which would affect the viability of this process. Note I am running Windows 10 Home edition as an admin if this is related. Thanks for the help.
filius.getName() only gets the last part of the files path. renameTo on the other hand needs the full path. So in fact you end up trying to move your file into a different directory.
Use:
File nova = new File(dir, newName);
in order to rename the file in the original directory.
I have a simple updater for my application. In code i am downloading a new version, deleting old version and renaming new version to old.
It works fine on Linux. But doesn't work on Windows. There are no excepions or something else.
p.s. RemotePlayer.jar it is currently runned application.
UPDATED:
Doesn't work - it means that after file.delete() and file.renameTo(...) file still alive.
I use sun java 7. (because I use JavaFX).
p.s. Sorry for my English.
public void checkUpdate(){
new Thread(new Runnable() {
#Override
public void run() {
System.err.println("Start of checking for update.");
StringBuilder url = new StringBuilder();
url.append(NetworkManager.SERVER_URL).append("/torock/getlastversionsize");
File curJarFile = null;
File newJarFile = null;
try {
curJarFile = new File(new File(".").getCanonicalPath() + "/Player/RemotePlayer.jar");
newJarFile = new File(new File(".").getCanonicalPath() + "/Player/RemotePlayerTemp.jar");
if (newJarFile.exists()){
newJarFile.delete();
}
} catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
System.err.println("Cannot find curr Jar file");
return;
}
if (curJarFile.exists()){
setAccesToFile(curJarFile);
try {
String resp = NetworkManager.makeGetRequest(url.toString());
JSONObject jsresp = new JSONObject(resp);
if (jsresp.getString("st").equals("ok")){
if (jsresp.getInt("size") != curJarFile.length()){
System.out.println("New version available, downloading started.");
StringBuilder downloadURL = new StringBuilder();
downloadURL.append(NetworkManager.SERVER_URL).append("/torock/getlatestversion");
if (NetworkManager.downLoadFile(downloadURL.toString(), newJarFile)){
if (jsresp.getString("md5").equals(Tools.md5File(newJarFile))){
setAccesToFile(newJarFile);
System.err.println("Deleting old version. File = " + curJarFile.getCanonicalPath());
boolean b = false;
if (curJarFile.canWrite() && curJarFile.canRead()){
curJarFile.delete();
}else System.err.println("Cannot delete cur file, doesn't have permission");
System.err.println("Installing new version. new File = " + newJarFile.getCanonicalPath());
if (curJarFile.canWrite() && curJarFile.canRead()){
newJarFile.renameTo(curJarFile);
b = true;
}else System.err.println("Cannot rename new file, doesn't have permission");
System.err.println("last version has been installed. new File = " + newJarFile.getCanonicalPath());
if (b){
Platform.runLater(new Runnable() {
#Override
public void run() {
JOptionPane.showMessageDialog(null, String.format("Внимание, %s", "Установлена новая версия, перезапустите приложение" + "", "Внимание", JOptionPane.ERROR_MESSAGE));
}
});
}
}else System.err.println("Downloading file failed, md5 doesn't match.");
}
} else System.err.println("You use latest version of application");
}
}catch (Exception e){
e.printStackTrace();
System.err.println("Cannot check new version.");
}
}else {
System.err.println("Current jar file not found");
}
}
}).start();
}
private void setAccesToFile(File f){
f.setReadable(true, false);
f.setExecutable(true, false);
f.setWritable(true, false);
}
I found the solution to this problem. The problem of deletion occurred in my case because-:
File f1=new File("temp.txt");
RandomAccessFile raf=new RandomAccessFile(f1,"rw");
f1.delete();//The file will not get deleted because raf is open on the file to be deleted
But if I close RandomAccessFile before calling delete then I am able to delete the file.
File f1=new File("temp.txt");
RandomAccessFile raf=new RandomAccessFile(f1,"rw");
raf.close();
f1.delete();//Now the file will get deleted
So we must check before calling delete weather any object such as FileInputStream, RandomAccessFile is open on that file or not. If yes then we must close that object before calling delete on that file.
windows locks files that are currently in use. you cannot delete them. on windows, you cannot delete a jar file which your application is currently using.
Since you are using Java 7, try java.nio.file.Files.delete(file.toPath()), it'll throw exception if deletion fails.
There are several reasons:
Whether you have permissions to edit the file in windows.
The file is in use or not.
The path is right or not.
I don't know wich version of Java you are using.
I know when Java was sun property they publish that the Object File can't delete files correctly on windows plateform (sorry I don't find the reference no more).
The tricks you can do is to test the plateform directly. When you are on linux just use the classic File object.
On windows launch a command system to ask windows to delete the file you want.
Runtime.getRuntime().exec(String command);
I just want to make one comment. I learned that you can delete files in Java from eclipse if you run eclipse program as Administrator. I.e. when you right click on the IDE Icon (Eclipse or any other IDE) and select Run as Administrator, Windows lets you delete the file.
I hope this helps. It helped me.
Cordially,
Fernando
When I start my application I create a temp folder:
public static File createTempDir(String name) throws IOException {
File tempDir = File.createTempFile(name, "");
if (!(tempDir.delete())) {
throw new IOException("could not delete" + tempDir.getAbsolutePath());
}
if (!(tempDir.mkdir())) {
throw new IOException("could not create" + tempDir.getAbsolutePath());
}
tempDir.deleteOnExit();
return tempDir;
}
During a session a user might load a file. As a result the old temp dir is deleted and a new is created based on the ID of the file loaded.
During load where the old temp dir is deleted I sometimes get a:
java.io.IOException: Unable to delete file:
Here is how the old temp folder is deleted:
public void cleanup(String tmpPath) {
File tmpFolder = new File(tmpPath);
if (tmpFolder != null && tmpFolder.isDirectory()) {
try {
FileUtils.deleteDirectory(file);
} catch (IOException e) {
e.printStackTrace();
}
}
}
where FileUtils is: org.apache.commons.io.FileUtils. Typically the content of the temp folder is:
mytempfolder_uuid
|-> mysubfolder
|-> myImage.jpg
And the error is:
java.io.IOException: Unable to delete file: C:\Users\xxx\AppData\Local\Temp\mytempfolder_uuid\mysubfolder\myImage.jpg
I have tried to debug the application and before the delete operation is executed verified that the above image is actually located in the specified folder.
The nasty thing is that it only happens sometimes. I have made sure not to have the folder/files in the temp folder open in any other applications. Any ideas/suggestions?
You cannot delete files which are open and you can't delete a directory which contains a file. You have to ensure all files in the directory are closed.
I'd suggest you use the Guava library. It has a method Files.createTempDir() that does exactly what you seem to need:
Atomically creates a new directory somewhere beneath the system's
temporary directory (as defined by the java.io.tmpdir system
property), and returns its name. Use this method instead of
File.createTempFile(String, String) when you wish to create a
directory, not a regular file. A common pitfall is to call
createTempFile, delete the file and create a directory in its place,
but this leads a race condition which can be exploited to create
security vulnerabilities, especially when executable files are to be
written into the directory. This method assumes that the temporary
volume is writable, has free inodes and free blocks, and that it will
not be called thousands of times per second.
try deleting the files in the temp folder before deleting it. Try somethng like
private boolean deleteFolder(File path) {
if (path.exists()) {
File[] files = path.listFiles();
for (File f : files) {
if (f.isDirectory()) {
deleteFolder(f);
} else {
f.delete();
}
}
}
return path.delete();
}
also using deleteOnExit is not a very good idea...
cheers!
public static boolean deleteDir(String path)
{
java.io.File dir = new java.io.File(path);
if (dir.isDirectory())
{
String[] filesList = dir.list();
for(String s : filesList)
{
boolean success = new java.io.File(dir, s).delete();
if(!success)
{
return false;
}
}
}
return dir.delete();
}
and then you can use it like: deleteDir("C:\\MyFolder\\subFolder\\")