Java and file list - java

I should get a list of file contained in a directory.
What I do is:
File file = new File(PATH);
for (File index:file.listFiles)
System.out.println(index.toString());
The matter is that doing this I get printed also files I shouldn't see, temporary, for example.
In my test directory I have to file: ciao and test, but when I run my code I see ciao, ciao~, test~, and also other stuff if I modify a file (I suppose they are buffer file).
So, how can I get only true file, as if I was browsing my fileSystem?

If you want to list only files whose attributes (name included) obey a set of conditions, you need to use another version of .listFiles() which takes a FileFilter as an argument. This interface has a sole accept() method which returns true if the file can be listed.
This simple example will filter out files whose name end with a ~:
file.listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return !pathname.getName().endsWith("~");
}
})
If your FileFilter is more complex than the one above, consider exernalizing it to a variable (private static final if the filter will never change).

Files you don't see are probably hidden, you can check that:
File file = ...;
if(file.isHidden()){...}

use
if (!index.isHidden()) {
System.out.println(index.toString());
}
to suppress hidden files.
you further can check for
index.isDirectory()
if you dont want subdirectory to be listed.
But dont expect an method that can read your thougts what you call an real (or clean, or nice) file.
You could write yourself a filter for that, once you now what files to exclude.
See java.io.FileFilter for more.

Related

How to treat java package as a File folder?

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.

How to one-way synchronize files in two directory structures in java?

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();

How do I distinguish between a file and a folder when renaming a file/folder in java

I am currently programming a file name normaliser. Files have a format and folders dont. When I rename a file I need to make sure that I do not affect the format therefore I did
fileName.substring(fileName.lastIndexOf("."),fileName.length)
thereby if I want to replace all the periods in a fileName it does not affect the format, when a folder with periods in its name goes through this process, the last instance of the period is still part of its name, therefore it does not replace all the dots in the folders name. I need to know how to distinguish between a file and a folder so I can fix this.
You can use
someFile.isDirectory();
It returns true if the file is a folder, and false if not.
You can use File.isDirectory() to test whether the file denoted by this abstract pathname is a directory. You can also use File.isFile() to test 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.
File f = new File(fileName);
if (f.isFile()) {
// it's a file.
} else if (f.isDirectory()) {
// it's a directory.
}

Java fails in moving (renaming) a file when the resulting file is on another filesystem

A program we have erred when trying to move files from one directory to another. After much debugging I located the error by writing a small utility program that just moves a file from one directory to another (code below). It turns out that while moving files around on the local filesystem works fine, trying to move a file to another filesystem fails.
Why is this? The question might be platform specific - we are running Linux on ext3, if that matters.
And the second question; should I have been using something else than the renameTo() method of the File class? It seems as if this just works on local filesystems.
Tests (run as root):
touch /tmp/test/afile
java FileMover /tmp/test/afile /root/
The file move was successful
touch /tmp/test/afile
java FileMover /tmp/test/afile /some_other_disk/
The file move was erroneous
Code:
import java.io.File;
public class FileMover {
public static void main(String arguments[] ) throws Exception {
boolean success;
File file = new File(arguments[0]);
File destinationDir = new File(arguments[1]);
File destinationFile = new File(destinationDir,file.getName() );
success = file.renameTo(destinationFile);
System.out.println("The file move was " + (success?"successful":"erroneous"));
}
}
Java 7 and above
Use Files.move(Path source, Path target, CopyOption... opts).
Note that you must not provide the ATOMIC_MOVE option when moving files between file systems.
Java 6 and below
From the docs of File.renameTo:
[...] The rename operation might not be able to move a file from one filesystem to another [...]
The obvious workaround would be to copy the file "manually" by opening a new file, write the content to the file, and delete the old file.
You could also try the FileUtils.moveFile method from Apache Commons.
Javadoc to the rescue:
Many aspects of the behavior of this method are inherently
platform-dependent: The rename operation might not be able to move a
file from one filesystem to another, it might not be atomic, and it
might not succeed if a file with the destination abstract pathname
already exists. The return value should always be checked to make sure
that the rename operation was successful.
Note that the Files class defines the move method to move or rename a
file in a platform independent manner.
From the docs:
Renames the file denoted by this abstract pathname.
Many aspects of the behavior of this method are inherently
platform-dependent: The rename operation might not be able to move a
file from one filesystem to another, it might not be atomic, and it
might not succeed if a file with the destination abstract pathname
already exists. The return value should always be checked to make sure
that the rename operation was successful.
If you want to move file between different file system you can use Apache's moveFile
your ider is error
beause /some_other_disk/ is relative url but completely url ,can not find the url
i have example
java FileMover D:\Eclipse33_workspace_j2ee\test\src\a\a.txt D:\Eclipse33_workspace_j2ee\test\src
The file move was successful
java FileMover D:\Eclipse33_workspace_j2ee\test\src\a\a.txt \Eclipse33_workspace_j2ee\test\src
The file move was erronous
result is url is error

Java isFile(), isDirectory() without checking for existence

I want to check if a given String is a file or a directory, i've tried the methods isFile() and isDirectory() of the File class but the problem is that if the directory or file doesn't exist these methods returns false, because as stated in the javadoc :
isFile() :
true if and only if the file denoted by this abstract pathname exists
and is a normal file; false otherwise
isDirectory() :
true if and only if the file denoted by this abstract pathname exists
and is a directory; false otherwise
Basically i need two methods without the exist clause ...
So i want to test if the given string complies to a directory format or complies to a file format, in a multiplatform context (so, should work on Windows, Linux and Mac Os X).
Does exist some library that provide these methods ? What could be the best implementation of these methods ?
UPDATE
In the case of a string that could be both(without extension) by default should be identified as directory, if a file with that path does not exist.
So i want to test if the given string complies to a directory format or complies to a file format, in a multiplatform context (so, should work on Windows, Linux and Mac Os X).
In Windows, a directory can have an extension and a file is not required to have an extension. So, you can't tell just by looking at the string.
If you enforce a rule that a directory doesn't have an extension, and a file always has an extension, then you can determine the difference between a directory and a file by looking for an extension.
Why not just wrap them in a call to File#exists()?
File file = new File(...);
if (file.exists()) {
// call isFile() or isDirectory()
}
By doing that, you've effectively negated the "exists" portion of isFile() and isDirectory(), since you're guaranteed that it does exist.
It's also possible that I've misunderstood what you're asking here. Given the second part of your question, are you trying to use isFile() and isDirectory() on non-existent files to see if they look like they're files or directories?
If so, that's going to be tough to do with the File API (and tough to do in general). If /foo/bar/baz doesn't exist, it's not possible to determine whether it's a file or a directory. It could be either.
Sounds like you know what you want, according to your update: if the path doesn't exist and the path has an extension it's a file, if it doesn't it's a directory. Something like this would suffice:
private boolean isPathDirectory(String myPath) {
File test = new File(myPath);
// check if the file/directory is already there
if (!test.exists()) {
// see if the file portion it doesn't have an extension
return test.getName().lastIndexOf('.') == -1;
} else {
// see if the path that's already in place is a file or directory
return test.isDirectory();
}
}
There are rules for what is invalid in a file and/or folder name. For example, Windows doesn't allow *, ?, and a few other characters. Based on what's invalid, you could build a regex expression or some other process/checking system to see if it looks like a file or folder.
This could get complex as you want it to work for many different OS's. Also, as previously posted, there would be no way to tell a file from a folder unless you artificially enforced a convention. For example, directories must end in a front-slash / in Windows.
Having the IF EXISTS check first would help. If IF EXISTS = true, then running the existing File.isDirectory() or File.isFile() code would simplify a lot of this. You would only have to write code for when IF EXISTS = false.

Categories

Resources