I am creating simple function to check weather I have write/delete permission to a folder
I want to know whether the operating system will allow writing into the folder or not ?
public static String PermissionCheck(String FilePath) {
//File f = new File(FilePath);
String actions = "read,write";
try
{
AccessController.checkPermission(new FilePermission(FilePath, actions));
return ("You have read/write permition to use : " + FilePath);
}
catch (SecurityException e)
{
return ("You don't have read/write permition to use : " + FilePath);
}
}
When I call either with correct path or incorrect path the method it always returns message from cathc.
I know its duplicate question I have already gone through many links but no luck !!
Similar Question
Similar Question 1
Example :
PreChecks.PermissionCheck("C:/TEST/G2");
PreChecks.PermissionCheck("C:/Program Files/SAP");
Both calls return the message from catch block where I have all permission on "C:/TEST/G2" and no write permission on "C:/Program Files/SAP".
I have also tried canWrite but it says I have write permissions to "C:/Program Files/SAP" but I know I don't have those.
The class java.io.File is limited in its capabilities. E.g.
File f=new File("C:\\Program Files\\Java");
System.out.println(f.canWrite());
prints true on my machine though a user process is not allowed to write at this location.
In contrast,
Path p=Paths.get("C:\\Program Files\\Java");
System.out.println(Files.isWritable(p));
correctly prints false.
So the solution is to use the NIO API.
The method AccessController.checkPermission has an entirely different purpose. It helps implementing security managers. It throws a SecurityException because you don’t have an explicitly granted permission to access that directory, but as long as you don’t have a SecurityManager installed, that is irrelevant.
Related
I'm trying to rename a file to add it extension. I'm detecting the type of the file, and want to append the extension to the file. It all works well, but I have a Sony Xperia Z2 for testing, and something weird happens. In other devices and emulators, works like a charm, but in this one... it's impossible.
It always return false, despite it has write permission in the parent folder, it's the same folder, and it only appends a ".jpg" or ".png" or something like that. As the File.renameTo function doesn't gives any error, just throw false, I can't know for sure if it's only me... but I start to believe it's something about how it manage the internal/external storage. The internal storage is actually sdcard0, and the external is sdcard1. Some apps, like ES File Manager, ask about where the root of my sdcard is, so it can rename, move, or copy files in my sdcard. Airdroid ask me to do the same thing. Why is that happening? How can I fix this?
Oh, and I have the pertinent permissions in the manifest, I've been searching a lot for a fix for this thing... and doesn't works in internal storage, as well. I'm totally lost. Here's the function I use to rename the file, if it helps someone... but I think it's a problem of the "internal sdcard" devices, or something.
private void setFixed(File f, String ext){
File parent = f.getParentFile();
try {
String name = f.getName();
String toName = (name+"."+ext).replace(" ", "");
//Lines that I added just to test. I saw before I call this function that the parent has write permission.
//Log.i("Pre", parent.getCanonicalPath()+name);
//Log.i("Post", parent.getCanonicalPath()+toName);
//File of = new File(parent.getCanonicalPath()+name);
//File nf = new File(parent.getCanonicalPath()+toName);
//Log.i("Converted", String.valueOf(of.renameTo(nf)));
File f1 = new File(parent.getAbsolutePath()+toName);
boolean success = f.renameTo(f1);
Log.i("File renamed?", String.valueOf(success));
} catch (Exception e) {
e.printStackTrace();
}
}
Thanks a lot!
Please read the documentation for renameTo(File) (click on the method and press ctrl + Q).
Renames this file to newPath. This operation is supported for both
files and directories. Many failures are possible. Some of the more
likely failures include: Write permission is required on the
directories containing both the source and destination paths. Search
permission is required for all parents of both paths. Both paths be on
the same mount point. On Android, applications are most likely to hit
this restriction when attempting to copy between internal storage and
an SD card. Note that this method does not throw IOException on
failure. Callers must check the return value.
As you can see, the search permission is required. Ensure that you add this to the manifest.
You also need to change
File f1 = new File(parent.getAbsolutePath()+toName);
to
File f1 = new File(parent.getAbsolutePath().toString()+ "/" +toName);
This is not actually a question, but I need explanation. I was trying to create directory under C:// drive. So;
try {
File f_paz = new File("c://Ekap_Pazarlik_xml" + file_currentDate + "//");
File parent_z = f_paz.getParentFile();
if (null != parent_z) {
parent_z.mkdirs();
}
if (!f_paz.exists()) {
f_paz.createNewFile();
}
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
I tried that and it gave me "Access Denied" error, so I tried all the solutions in the web. Nothing happened.
Strangely, I decided to put "space" after there;
File f_paz = new File("c://Ekap_Pazarlik_xml" + file_currentDate + "// ");
here
just after "// ", and it worked. I was able to crate directory like that. I have no idea why it worked like that. Please provide me some explanation. Thanks !
f_paz.createNewFile(); will try to create a new file, not a directory. Many Windows systems won't allow you to create files in directly in C: so that's why you get the exception.
Since you want to create a directory and not a file use f_paz.mkdir(); instead. You don't need the "//" at the end, btw.
What happens if you add the space, i.e. use path "C:/Ekap_xxx/ "? The system will see a path with a blank filename " " and a parent directory name "Ekap_xxx". Now parent_z will refer to "C:/Ekap_xxx" and thus parent_z.mkdirs(); will create directory "Ekap_xxx". Now f_paz.exists() will return true since the filesystem seems to decide a file with an invalid name still exists (I'd have to look for some information on why that is so, it's hidden in the native code).
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've created a simple program that would write a file with a directory using the following codes:
String nameProve = nameField.getText();
String employee = ("C:\\Users\\ALLEN\\workspace32bit\\RETRIEVE_CHECKER1\\RETRIEVE_CHECKED1" + nameProve + ".txt");
PrintWriter outputStream1 = null;
try
{
outputStream1 = new PrintWriter(employeeName);
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null, "Can not write to " + employeeName);
System.exit(0);
}
outputStream1.println("Employee Retrieve Executed");
outputStream1.close();
I've already exported my code to a .jar file and my code works just fine if i execute it in the computer were I've develop my program but when I copied the jar file to other computer and I also created the forlder (manually) that corresponds with the directory in my codes my program doesn't work and my catch block will show the message Can not write to "C:\Users\ALLEN\workspace32bit\RETRIEVE_CHECKER1\RETRIEVE_CHECKED1" + nameProve + ".txt"
Can anybody give me some advice on how to solve this error? Thanks!
Obviously you are the user ALLEN on your machine and run the program as that user, so everithing works fine, because you are the owner of the directory C:\Users\ALLEN.
Then you copy the jar to another machine, where the user ALLEN does not exist and you are logged in as antoher user let's say his name is Bob and create that directory unter C:\Users. You may have noticed that you when you wanted to create that directory as the user Bob windows has warned you that you need admin priviledges in order to compleate this action.
Now you try to run your program with the user Bob who has access only to his own directory C:\Users\Bob and try to write to ALLEN's own directory. So what happens is that you get an IOException telling you access denied which is good so!
You should not attepmt to write to other users private direcotries, this is a security issue.
In your code when dealing with filesystem, never hard code absolute path, always use relative paths, or if you need to defined a direcotry where all the data needed yb you program should be located, then pass ist as argument.
The simplest to do, ist use the following and work with the current working directory
String employee = "RETRIEVE_CHECKER1\\RETRIEVE_CHECKED1" + nameProve + ".txt";
You need to create the directory RETRIEVE_CHECKER1 either by hand in location where you run the program, or better yet in your program using File#mkdir and use it like this:
File employee = new File(dir, "RETRIEVE_CHECKED1" + nameProve + ".txt");
PrintWriter outputStream1 = new PrintWriter(employeeName);
Exception you catch will have all details- like access denied, directory not exist, etc. Currently you loose exception data (message, stacktrace) when catching it.
Please do something like
Do not catch just java.lang.Exception. This is too wide- will catch possible NullPointerException and present misleading message '"Can not write to'. Catch only specific exception instead- ones that are actually thrown from try block. In your case, that will be java.io.FileNotFoundException
Do not loose exception details. Print it to the standard error log, or even better use loging framework
catch block that adresses those issues:
catch(FileNotFoundException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
e.printStackTrace();
}
I am trying to check if a folder is readable in Java 1.6 with the following two manner:
1) Using canRead method of File class. But it's readable all the time (canRead() return always true):
final File folder = new File("file.xml");
if(folder.canRead()){
// The file is readable
}else{
// The file is not readable!!
}
2) Using FilePermission class and catch exception. But it catchs the exception all the time (when the folder is readable or not):
try {
FilePermission filePermission = new FilePermission(folder.getAbsolutePath(), "read");
AccessController.checkPermission(filePermission);
// The file is readable
} catch (AccessControlException pACE) {
// The file is not readable !!
}
I have found that there is an issue between Microsoft Windows OS and Java 1.6 for this case.
Bug: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6203387
Have you any solution?
This is quick and dirty,
File dir = new File("foo");
if (dir.exists()) {
if (dir.listFiles() == null) {
// directory not readable
}
}
all the IO errors are handled inside of listFiles().
What I would do is simply go ahead with a write to that folder. If it works, then all is great, and if not, you can catch the exception.
This is philosophically a Pythonic approach
"It's better to ask for forgiveness than to ask for permission"
but you don't seem to have a choice here.
Here's a good StackOverflow post on exactly this Philosophy: https://stackoverflow.com/questions/6092992/why-is-it-easier-to-ask-forgiveness-than-permission-in-python-but-not-in-java (See 'Update #3' in the question which is a really good example, and somewhat relates to your problem)