Say I have a list of folders' names within a directory that has the path
C:\Users\Desktop\Application\('folder_names')
How would I delete certain folders within this directory and keep the ones I have stored in a list.
ie. I have a String List:
String[] deleteList = "folder 1, folder 2, folder 3";
and in the directory:
C:\Users\Desktop\Application\ I only want to delete folder 2
How might I do this using the String List instead of explicitly call out that folder?
So far I have:
UPDATED:
File[] deleteList = directory.listFiles(fileFilter);
for (File file : deleteList) {
if (file.isDirectory()) {
System.out.println(file.getPath());
if (file.getPath()
.equals("C:\\Users\\Desktop\\Application\\folder 2")) {
System.out.println("got folder");
FileUtils.deleteDirectory(file);
} else {
System.out.println("Didn't get it.");
}
}
}
Output
C:\Users\U201165\Desktop\Newfolder\Newfolder(2)
got folder
C:\Users\U201165\Desktop\Newfolder\Newfolder(3)
Didn't get it.
C:\Users\U201165\Desktop\Newfolder\Newfolder(4)
Didn't get it.
C:\Users\U201165\Desktop\Newfolder\Newfolder(5)
Didn't get it.
You are probably getting a relative path from the getPath(). To be sure that you are getting the absolute path from the File object, use:
if (file.getAbsolutePath().equals("C:\\Users\\Desktop\\Application\\folder2")) ...
instead of getPath().
Your System.out is showing the file object, but in your equals method you are using file.getPath(). Put file.getPath() in your system.out so you can see what you are actually comparing. The File object has a method like getExplicitPath() method. You might need to be using that instead of path. In some cases I think path just shows the file name, or the relative path not the expect one.
Related
I am currently getting to grips with file management in Java. As far as i've read, java.nio.file.Path is the preferred way of doing so.
Say I want to copy the contents of oldDir to the, currently empty, newDir. Every time I copy a file, I need this loong line just to get the Path of newFile:
Path newDir = FileSystems.getDefault().getPath("new");
Path oldDir = FileSystems.getDefault().getPath("old");
for (Path oldFile : oldDir) {
Path newFile = FileSystems.getDefault().getPath("new", oldFile.getFileName().toString()); // Why so complicated? :(
Files.copy(oldFile, newFile);
}
Is there something like newDir.getChild(oldFile.getFileName()) to do what I want, or is there really no shorter way of doing it?
There are a couple things you can do to make the code simpler:
Use Path#of(String,String...) or Paths#get(String,String...) to create your Path instances. Both methods delegate to the default FileSystem. The former was added in Java 11 and is now the preferred approach.
Use Path#resolve(Path) to append a relative path to some absolute path.
But there's also an error in your code. You are iterating over oldDir which works because Path implements Iterable<Path>. However, that iterates over the names of the path, not the children of the path. In other words, this:
Path path = Path.of("foo", "bar", "file.txt");
for (Path name : path) {
System.out.println(name);
}
Will output:
foo
bar
file.txt
If you want to iterate over the children of a directory you need to use something like Files#list(Path) or Files#newDirectoryStream(Path) (the latter has two overloads). Both those methods only return the immediate children of the directory. There are other methods available to recursively iterate a directory and its sub-directories; browse the Files documentation to see what's provided.
So your code should instead look something like:
Path oldDir = Path.of(...);
Path newDir = Path.of(...);
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(oldDir)) {
for (Path oldFile : dirStream) {
Path newFile = newDir.resolve(oldFile.getFileName());
Files.copy(oldFile, newFile);
}
}
I want to be able to iterate through a package of files as if the package were a folder.
Something like the below (scripts being the java package):
File scriptFolder = new File("scripts").getAbsoluteFile();
The packages appear are not being treated like folders. If I hardcode the path C:\Users\...\project_folder\...\scripts the File.isFile() method returns false for the package. If I do new File (C:\Users\...\project_folder\...\scripts\script).isFile() I get true.
I want to get a File of the folder so I can get a list of the files in the folder and iterate through it.
The .isFile() method returns true only if you are referencing a plain jane normal file. If you're referencing a directory, it'd return false. Try .isDirectory() or possibly .exists().
Or don't; there's no real need:
File[] filesInDir = new File("C:\\Users\\....\\scripts").listFiles();
if (filesInDir == null) {
// this means it wasn't a directory or didn't exist or isn't readable
} else {
for (File child : filesInDir) {
// called for each file in dir
}
}
The official javadocs say this about File#isFile():
Tests whether the file denoted by this abstract pathname is a normal file. A file is normal if it is not a directory and, in addition, satisfies other system-dependent criteria. Any non-directory file created by a Java application is guaranteed to be a normal file.
You can check if it is a directory with File#isDirectory(), then if it is, you can list its contents with File#listFiles().
Unless I'm missing something in your question C:\Users...\project_folder...\scripts is a directory so isFile() will return false because it is not a file.
I have two folders, source and target, with files and possible subfolders(directory structure is assumed to be the same, subfolders and files can go into any depth) in them. We want to synchronize the target so that for all files:
Exists in source, but not in target -> new, copy over to target
Exists in target, but not in source -> deleted, delete from the target
Exists in both, but binary unequal -> changed, copy over from source
Exists in both, and is binary equal -> unchanged, leave be
One problem I have with this is checking for existence of a file(the return value of listFiles() doesn't seem to have contains() defined), but a far bigger obstacle is referencing the other directory structure. For example, how would I check if target folder contains file "foo.txt" while iterating through the source folder and finding it there? Here's what I have so far:
public void synchronize(File source, File target) {
//first loop; accounts for every case except deleted
if (source.isDirectory()) {
for (File i : source.listFiles()) {
if (i.isDirectory()) {
synchronize(i, /**i's equivalent subdirectory in target*/);
}
else if (/**i is new*/) {
/**Copy i over to the appropriate target folder*/
}
else if (/**i is different*/) {
/**copy i over from source to target*/
}
else {/**i is identical in both*/
/**leave i in target alone*/
}
}
for (File i : target.listFiles()) {
if (/**i exists in the target but not in source*/) {
/**delete in target*/
}
}
}
}
EDIT(important): I thank you guys for all the answers, but the main problem remains unsolved: referring to the other directory, i.e. the stuff in the comments. h22's answer seem to be somewhere in the ballpark, but it's not sufficient, as explained in the comment below it. I'd be very grateful if someone could explain this in even smaller words. From experience, this is exactly the kind of problem that someone more java-savvy could solve in five minutes, whereas I would spend two frustrating weeks rediscovering America.
As wero points out, you can use aFile.exists() to see if a given path exists. You should also combine it with aFile.isFile() to check whether the path is a normal file (and not, say, a folder).
Checking content-equals is more tricky. I propose the following:
boolean sameContents(File fa, File fb) throws IOException {
Path a = a.toPath();
Path b = b.toPath();
if (Files.size(a) != Files.size(b)) return false;
return Arrays.equals(
Files.readAllBytes(a), Files.readAllBytes(b));
}
But only if the files are expected to be small; otherwise you could run out of memory trying to compare them in one go (required to use Arrays.equals). If you have large files in there, this answer proposes Apache Commons IO's FileUtils.contentEquals().
Note that both the above code and contentEquals only compare files, and not folders. To compare folders, you will need to use recursion, calling sameContents or equivalent on each same-named, same-sized file, and erroring out if no match is found for a particular pathname either in source or in destination.
Only visit the source folder recursively. Strip the folder root and address the target location directly:
String subPath = sourceFile.getAbsolutePath().substring(sourceRoot.length);
File targetFile = new File(targetRoot + File.separator + subPath);
if (targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
// copy, etc
Otherwise you may have difficulties if the target location is missing the required hierarchical folder structure that may go many directories in depth.
If you have a target directory File targetDir and a source file File sourceFile in a source directory you can check the existence of the corresponding target file by writing:
File targetFile = new File(targetDir, sourceFile.getName());
boolean exists = targetFile.exists();
This should be a really simple question but Google + my code isn't working out.
In Eclipse on Windows, I want my program to look inside a certain folder. The folder is directly inside the Project folder, on the same level as .settings, bin, src, etc. My folder is called surveys, and that's the one I want my File object to point at.
I don't want to specify the full path because I want this to run on both of my computers. Just the path immediately inside my Project.
I'm trying this code but it isn't working - names[] is coming back null. And yes I have some folders and test junk inside surveys.
File file = new File("/surveys");
String[] names = file.list();
for(String name : names)
{
if (new File("/surveys/" + name).isDirectory())
{
System.out.println(name);
}
}
I'm sure my mistake is within the String I'm passing to File, but I'm not sure what's wrong?
In your question you didn't specify what platform you are running on. On non-Windows, a leading slash signifies an absolute path. Best to remove the leading slash. Try this:
File file = new File("surveys");
System.out.println("user.dir=" + System.getProperty("user.dir"));
System.out.println("file is at: " + file.getCanonicalPath());
String[] names = file.list();
for(String name : names)
{
if (new File(file, name).isDirectory())
{
System.out.println(name);
}
}
Make sure the in your run configuration, the program is running from the projects directory (user.dir = <projects>)
Make sure that your file is a directory before using file.list() on it, otherwise you will get a nasty NullPointerException.
File file = new File("surveys");
if (file.isDirectory()){
...
}
OR
if (names!=null){
...
}
If you checked the full path of your file with
System.out.println(file.getCanonicalPath())
the picture would immediately become clear. File.getCanonicalPath gives you exactly the full path. Note that File normalizes the path, eg on Windows "c:/file" is converted to "C:\file".
Basically, I have a directory with some files in it. In run configurations I am trying to put the directory as an arguement like so: \(workspacename\directory. Then, the following code should create a list of all the files in that directory:
String directory = args[1];
File folder = new File(directory);
File[] allFiles = folder.listFiles();
ArrayList<File> properFiles = null;
for (File file: allFiles) {
if(file.getName().endsWith(".dat")){
properFiles.add(file);
}
}
the problem i'm facing is that for some reason allFiles is null.
I'll take a guess at what your problem might be:
If your argument is a relative path (as opposed to an absolute path, staring with "/" or "c:/" for example), keep in mind that files will be relative to the working directory of the application.
So new File(directory) will be relative to wherever the application is started. In Eclipse the default working directory is in the project. So if your project is in the top level of the workspace, it will be something like workspacename/project.
You can try printing out folder.getAbsolutePath(), folder.exists() and folder.isDirectory() to help diagnose your problem.
The javadocs say listFiles() will return null if the directory does not actually exist (among other things):
Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs.
Debug by verifying (debugger or printf) the args[1] value.
Also, it looks like you might be trying to use a substitution variable to insert the workspace location in the path. If so, again, you need to verify (via debugger or printf) that the placeholder is getting replaced properly.