I have a situation where I need to run a "pre-check" to see if a directory is "createable". This is not a problem, just run a file.mkdirs() and see if it returns true.
The problem is that I would like to clean up after this check. This is a bit tricky, because I want to delete only those folders and subfolder that mkdirs() actually created.
Can anyone think of a clever way to do this?
I think this method does the job without you having to call mkdirs:
public static boolean canMkdirs(File dir) {
if(dir == null || dir.exists())
return false;
File parent = null;
try {
parent = dir.getCanonicalFile().getParentFile();
while(!parent.exists())
parent = parent.getParentFile();
} catch(NullPointerException | IOException e) {
return false;
}
return parent.isDirectory() && parent.canWrite();
}
Keep one array which holds name of that dirs. so when you want to delete dir you can take that array content/string/dir-name to delete.
A bit dangerous:
if (file.mkdirs()) {
long t0 = file.lastModified();
for (;;) {
long t = file.lastModified();
if (t < t0 - 1000L) { // Created longer than it's child minus 1 s?
break;
}
t0 = t;
file.delete();
file = file.getParentFile();
}
}
If my assumption that permissions are inherited in the file structure is correct, something like this should do it:
File f = new File("C:\\doesntExist\\Nope\\notHere");
File tempFile = f;
while (!tempFile.exists())
tempFile = tempFile.getParentFile();
if (!tempFile.canWrite()
&& tempFile.isDirectory()) // Copied this line from Lone nebula's answer (don't tell anyone, ok?)
System.out.println("Can't write!");
else
{
f.mkdirs();
...
}
Judging by the mkdirs() source code:
public boolean mkdirs() {
if (exists()) {
return false;
}
if (mkdir()) {
return true;
}
File canonFile = null;
try {
canonFile = getCanonicalFile();
} catch (IOException e) {
return false;
}
File parent = canonFile.getParentFile();
return (parent != null && (parent.mkdirs() || parent.exists()) &&
canonFile.mkdir());
}
If I hadn't missed something you have two options:
remeber the state of the files on the disk before calling the mkdirs(), compare it with the state after the mkdirs(), handle if necessary
extend the File class and override mkdirs() method to remember exactly which files were created. If any are created, handle them.
The latter seems like a more elegant solution which will yield less code.
UPDATE:
I strongly recommend to take in consideration david a. comment.
Related
I have a list of plans, each plan has a PDF in ("/web/managed/")
I wasn't deleting the files when I delete the plan, so now I'm trying to add a function to delete all files that are not have the ids in my plan list.
Files name always has the id.
Example: 6365_Test-LVLD.pdf
list of the object:
#Transaction
public List<StorePlan> getPlans() {
List<StorePlan> list = getCurrentSession().createCriteria(StorePlan.class).list();
return list;
}
then I'll get all the files from my folder:
protected File[] getPDFs() {
return new File("/web/managed/").listFiles();
}
here's my purge function:
protected void getPlanIds() {
int count = 0;
for(StorePlan plan : storePlanDao.getPlans()) {
for (File file : getPDFs()) {
String planFileId = file.getName().substring(0, 4);
if(plan.getId() != Integer.valueOf(planFileId)) {
file.delete();
count++;
}
}
}
}
with my code: it will delete everything from my folder. when I want to keep the files that will still have ids in the other list.
If I understood your question then this should work:
List<Integer> planIds = Lists.newArrayList();
for(StorePlan plan : storePlanDao.getPlans()){
planIds.add(plan.getId());
}
for (File file : getPDFs()) {
Integer planFileId = Integer.valueOf(file.getName().substring(0, 4))
if(!ids.contains(planFileId)) {
file.delete();
count++;
}
}
I think I see the problem. Instead of deleting the problem within the second loop have it set a Boolean to true and break out of the loop. Outside of the second loop have an if statement that, if true, deletes the file. So:
protected void getPlanIds() {
int count = 0;
for(StorePlan plan : storePlanDao.getPlans()) {
Boolean found = false;
for (File file : getPDFs()) {
String planFileId = file.getName().substring(0, 4);
if(plan.getId() == Integer.valueOf(planFileId)) {
found = true;
break;
} else {
count++;
}
}
if (!found) {
file.delete();
}
}
}
I apologize for bad formatting. I'm on mobile and passing time at work. xD
I'm writing a quick Java recursion method that, given a root folder and filename, searches your files for said file name.
import Java.io.File;
public static String searchForFile(File currentFolder, String filename)
{
try
{
File[] path = currentFolder.listFiles();
for (int i = 0; i < path.length; i++)
{
if (path[i].isDirectory())
{
System.out.println("Directory: " + path[i].toString());
searchForFile(path[i], filename);
}
else
{
System.out.println("File: " + path[i].toString());
if(path[i].getName().equals(filename))
{
System.out.println("Your file has been found!";
return path[i].toString();
}
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return null; // Omitting this line yields compiling errors, not sure why?
}
public static void main(String[] args)
{
System.out.println("Hello, enter the root folder and file name.");
String rootFolder = "Desktop";
String fileName = "Hello.txt";
File f = new File("C:\\Users\\Me\\" + rootFolder);
searchForFile(f, fileName);
}
The program itself technically works, however searchForFile() keeps iterating even after the requested file is found. For example, I'd get an output such as:
File: C:\Users\Me\Desktop\My Stuff\NotHello.txt
**File: C:\Users\Me\Desktop\My Stuff\Hello.txt**
Your file has been found!
File: C:\Users\Me\Desktop\My Stuff\AlsoNotHello.txt
File: C:\Users\Me\Desktop\My Stuff\StillNotHello.txt
File: C:\Users\Me\Desktop\My Stuff\WhyIsThisMethodStillRunning.txt
I've been scratching my head at this for awhile now. I thought return always exits the method, so why does the recursion continue even after it returns a value? I haven't found any similar questions asked, so any help would be much appreciated!
(Also, how could I edit the method so that it returns a blank "" string if the requested file is not found?)
You are returning from the innermost call, when you've found the file. But when you are scanning a directory, you are not using the return value.
Change this:
searchForFile(path[i], filename);
to:
String result = searchForFile(path[i], filename);
if (result != null) {
return result;
}
The return null; in the bottom of your method is there because all methods needs to return a value. No matter if the file is found or not. If the file is not found within the current directory (or one of its subdirectories), you can return null; to indicate that it wasn't found.
Side suggestion: Use Optional in Java 8 instead of null.
Maybe it's just me that stupid, but i can't get this to work in, only if i try it in a file where i haven't writen anything but this:
boolean runOnce = true;
File temp = new File("myPath/tempX.txt");
File test = new File("myPath/xCordLayout.txt");
if (runOnce) {
if (test.delete()) {
System.out.println("Success");
} else {
System.out.println("Failed");
}
runOnce = false;
}
if (temp.renameTo(test)) {
System.out.println("File has been renamed!");
} else {
System.out.println("ERROR");
}
The program syestem.out.println says Failed, so its the deleting part that doesn't seem to work.
if i have it in the same way, but you have to press a buttom or somethinh else, i doesn't seem to work ( i have tested the other statements, to check if there is something wrong with them but idk). Can someone help me, or tell me how to overwrite another file?
I am trying to output a list of files within a directory recursively (not including the name of the name of the directory that I am starting with (just the contents of it and all files recursing down the tree after that)
here is what I have at the minute. It Might have errors here and there, but the idea is that it will print all the names of every file in the tree recursively. My problem is that I don't want it to print the name of the directory in which they live.
I think my problem is that I am using System.out.println at the start of the recursive method, which means it gets used every time. Which is desirable behavior for every directory BELOW the first one. Its an annoying little problem that I could use some help on. Thanks in advance.
public static void listFiles(String path)
{
File basedir = new File(path);
System.out.println(path.getName());
try
{
File[] files = basedir.listFiles();
for (File file : files)
{
// If Dealing with a directory, call recursively to the function
if (file.isDirectory())
{
listFiles(file.getPath());
}
else
{
System.out.println(file.getName());
}
}
}
catch(IOException ex)
{
System.out.println(ex);
}
}
public static void listFiles(String path, boolean firstCall)
{
File basedir = new File(path);
if(!firstCall)
{
System.out.println(path.getName());
}
try
{
File[] files = basedir.listFiles();
for (File file : files)
{
// If Dealing with a directory, call recursively to the function
if (file.isDirectory())
{
listFiles(file.getPath(), false); //false here because it is not the first call
}
else
{
System.out.println(file.getName());
}
}
}
catch(IOException ex)
{
System.out.println(ex);
}
}
Add a boolean parameter that specifies if it is the first call. When you call the method pass true to the parameter. Also path.getName() is not valid String doesn't have a function getName() maybe you meant basedir.getName()...also remove try catch block IOException can't occur there.
I tried to wrote a function who returns all of the txt files from some directory, that in the main I wrote:
File file = new File(dir);
listFiles(file.listFiles());
and the function is:
private static void listFiles(File[] files) {
if (null == files)
return;
for (File file : files) {
if (!file.isDirectory()) {
if (file.getName().endsWith("txt") && file != null) {
queue.add(file);
fileCounter++;
}
} else {
listFiles(file.listFiles());
}
}
}
and every time it throw "java.lang.NullPointerException" in the "`queue.add(file);"
what is the problem?
You must instantiate your queue (queue = new ...) before you can actually add anything to it.
This means queue is null - probably you didn't initialize it.