I am listing all the files names in a given directory( recursively). That includes showing the file names in sub-directories also.
File file = new File(FILE_PATH);
// Recursively search for all the resource files.
Collection files = FileUtils.listFiles(file, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
for (Iterator iterator = files.iterator(); iterator.hasNext();)
{
File fileIter = (File) iterator.next();
System.out.println("File = " + fileIter.getPath());
}
Where File is the parent directory ("C:\Users\sd\Desktop\sdsd)
Now the code above works file and list me all the files in the that directory and sub directory, like
C:\Users\sd\Desktop\sdsd\TagCategory\healthoutcomes_queries\Neurological.txt
but I want to show only (the path inside of the parent path)
TagCategory\healthoutcomes_queries\Neurological.txt
How can I do that.
Use Path.relativize()
Constructs a relative path between this path and a given path.
Relativization is the inverse of resolution. This method attempts to
construct a relative path that when resolved against this path, yields
a path that locates the same file as the given path. For example, on
UNIX, if this path is "/a/b" and the given path is "/a/b/c/d" then the
resulting relative path would be "c/d".
So you just need to create a relative path from the parent path by invoking parentPath.relativize(filePath) and do it for each file :
Path parentPath = Paths.get(FILE_PATH);
for (Iterator<File> iterator = files.iterator(); iterator.hasNext();){
Path filePath = iterator.next().toPath();
Path relativePath = parentPath.relativize(filePath);
System.out.println("File = " + relativePath );
}
Note that you should use a generic collection to avoid casts : Collection<File>, and the modern idiom for looping through iterators using the "enhanced for loop" is cleaner to read:
for (File file : files) {
System.out.println("File = " +
parentPath.relativize(file.toPath()));
}
Just add substring:
fileIter.getPath().substring(file.length())
You can use the substring command to get that value as per the below..
If that parent directory is going to remain the same length then it would simply be
fileIter.getPath().substring(25);
This will get all of the characters after the 25th character in the string, if you wanted to omit the .txt for example you can specify where the substring will end, the below takes three off the total length.
fileIter.getPath().substring(25, fileIter.getPath().length() - 3);
For more details on the substring method see https://beginnersbook.com/2013/12/java-string-substring-method-example/
What's the point of complicating your code by using old third-party libraries? Just use plain Java: it does exactly the same thing as your multi-line method:
Path root = Paths.get(FILE_PATH);
Files.walk(root).forEach(path -> System.out.println("File = " + root.relativize(path)));
Related
Windows 10
Java 8
When I call getCanonicalPath on a File object, I get a string like this
C:\data\processed\Test.xml
How do I get the same string but without C:\ and if possible also with / instead of \?
You can use NIO.2 API and its objects Path and Paths which is a abstraction over a file system.
Path path = Paths.get("C:\\data\\processed\\Test.xml");
You can also get Path from File using File::toPath. Actually, you need to get all the names in the path:
File file = new File("C:\\data\\processed\\Test.xml");
Path path = file.toPath();
int count = path.getNameCount(); // the count of names
path = path.subpath(0, count); // all the names
Alternatively (thanks to #Holger) using Path:relativize (you find a relative path to the root C:/ which is all the names.
File file = new File("C:\\data\\processed\\Test.xml");
Path path = file.toPath();
path = path.getRoot().relativize(path);
Here are some relevant methods:
path.getRoot() returns C:\
path.getNameCount() returns the number of name elements in the path (3 in this case)
path.getName(0) returns data, path.getName(1) returns processed etc...
path.subpath(fromInclusive, toExclusive) returns a relative Path that is a subsequence of the name elements of this path.
path.relativize(path) returns a relative path to a parameter.
The object Path represents an abstraction of the actual path. If you want to replace \ with / as a String, you might need to use String::replace.
String stringPath = path.toString().replace('\\', '/');
System.out.println(path); // data\processed\Test.xml
System.out.println(stringPath); // data/processed/Test.xml
Here is a short answer:
File file = new File("c:\\tmp\\abc.txt"); //file =C:\tmp\abc.txt
String filePath= file.getCanonicalPath(); //path= C:\tmp\abc.txt
String str=filePath.replace('\\', '/'); //str= C:/tmp/abc.txt
java.net.URI uri= new java.net.URI(str); //uri= C:/tmp/abc.txt
uri.getPath(); //uri.getPath() = /tmp/abc.txt
I'm trying to see how many of these text files exist, but even with them there, the program always says the numFiles = 0. I have the files in a folder called Levels within the src folder. Thanks
int numFiles = 0;
for(int i = 0; i < 24; i++){
File file = new File("/Levels/level" + (i+1) + ".txt");
if(file.exists()){
numFiles++;
}
}
System.out.println(numFiles);
Edited
I overlooked that DirectoryStream doesn't support count()
You could go with an absolute path and make use of Stream API and lambdas. Like so:
String dirString = "..." //absolute Path
Path dir = Paths.get(dirString);
int numFiles = dir.getNameCount();
System.out.println(numFiles);
One advantage is that you can rename the files at will as long as they stay in the same directory. If you only want to work with specific files you can use filter() like so:
Files.newDirectoryStream(dir).filter(Predicate);
or add the filter directly when creating the DirectoryStream like so:
Files.newDirectoryStream(dir, RegEx);
To do something with each File you can use the consumer forEach() or have a look at Stream JavaDoc for other consumers/intermediate operations. Also double check if the DirectoryStream supports the Stream operation you want to use.
Your path is incorrect - if you are referring to an absolute location only then start with a /.
Also if you are using an editor remember your Java files are in src but but you don't run Java File you run class files and the class files may be in your bin/build directory most likely - check if the text file are in the build or bin directory.
Your path is incorrect, if you are referring to a local file(like something in your project folder) use
File file = new File("Levels/level" + (i+1) + ".txt");
the slash you used in front of the name makes it look in the root of the drive, not the local directory.
I have a HashSet of Strings, which are names of files that I want to copy from the working direcorory to the "path" directory. I find that the following piece of code should be working, however, I get a java.nio.file.NoSuchFileException: /commits/1/hello.txt exception.
Hashset<String> stagedQueue = HashSet<String>();
stagedQueue.put("hello.txt");
stagedQueue.put("bye.txt");
String path = "/commits/" + commitID;
for (String file : stagedQueue) {
Files.copy((new File(file).toPath()),
(new File(path + "/" + file).toPath()));
What can I do to fix this? I can't figure out why I am getting these exceptions. Please note that I am moving these into an empty directory.
Don't go through File; you use java.nio.file.
Your problem here is that you try and copy your initial file into a directory which does not exist yet:
String path = "/commits/" + commitID;
First of all, this is the destination directory, so call it dstdir, for instance. Then create the base directory and copy the files into it:
final Path basedir = Paths.get("/commits", commitId);
Files.createDirectories(basedir);
for (final String file: baseQueue)
Files.copy(Paths.get(file), basedir.resolve(file));
This question has been brought up before, and I have searched many of the answers. It always ends in "You want getResourceAsStream". This is not what I am looking for.
My issue is , for a game object, I am using a folder structure to keep sprite strips rather than having one large sprite. This results in :
Media/
CharacterName/
AnimationName/
image.extension
the programming object just holds it's folder as a string, and I pass the getResource() URL to an object to fill the map of images. there can be {n} number of AnimationName/ sub directories. My error comes from this code:
dir = new File(s.toURI());
I take the directory, and call listFiles and pass the file names found to the sprite loader. Here is a code snippet:
dir = new File(s.toURI());
File[] chld = dir.listFiles();
//get a list of files in the image/character folder
for(File f:chld)
{
//get a list of the files for each dir
File[] grandChild = f.listFiles();
for(File t:grandChild)
{
String fname = t.getAbsolutePath();
System.out.println(fname);
String temp = fname;
temp = temp.substring(temp.lastIndexOf("/") + 1,temp.lastIndexOf("."));
String animName = temp.replaceAll("\\d*$", "");
int numPics = 0;
Pattern p = Pattern.compile("[0-9]+");
Matcher m = p.matcher(temp);
while(m.find()){
numPics = Integer.parseInt(m.group());
}
System.out.println("animation name: " + animName);
System.out.println("file name: " + fname);
System.out.println("number of pictures: " + numPics);
Animations.put(animName, sl.loadStripImageArray(fname, numPics));
}
}
Excuse the poor naming and temp variables, it's still being worked on.
sl is the sprite loader, and Animations is a hash map. This works fine until I package the project. I don't want to write a bunch of convoluted code that only works if I have a jar file, and not when I'm working in netbeans with the source folders.
I have considered having an application data folder, but I'd like to stay with a jar package if I can.
You do still want to use getResourceAsStream. Nothing here requires that all resources must be kept at the same folder within the JAR. You can use relative paths, or absolute paths to the root of the JAR by prefixing your path with /.
You can't make File work with resources within the JAR - even if instantiated with a URL that points to a resource contained within a JAR.
You may have to rework some other things, as the classpath is not really meant to be enumerated against (as you're currently listing files from the parent directory). It is designed to retrieve a resource by name. So one possibility (that I would recommend) is to have a "manifest" file that contains the files you want to load from each directory. (Read this file, then load the additional resources by name.)
Alternatively, if you can find the name of the JAR file you're loading from, you can create a Jarfile from it, then call its entries() method to find all of the contained resources. But even then, they aren't returned in a "tree structure", so ideally, you'd read this one, create your own tree structure from it (possibly as a series of Maps), then use it to retrieve the "directory listings" as needed.
If you are absolutely sure that the sprites are located in a jar - you could try using the JarFile class. There is a method entries. I didn't try it but it seems to return all resources located in the whole jar file. You would have to filter out which resources are in the right path.
If a file exists in the same directory where a Java application is running and I create a File object for that file the Java File methods for the path of the file include the filename as well. Code and output are below.
If this was a bug in the JDK version I'm using someone would surely have seen it by now.
Why do File.getAbsolutePath() and File.getCanonicalPath() include the file name? The Javadocs indicate that the directory name should be returned.
import java.io.File;
import java.io.IOException;
public class DirectoryFromFile {
private void getDirectoryOfFile(String fileName) throws IOException{
File f = new File(fileName );
System.out.println("exists(): " + f.exists());
System.out.println("getPath(): " + f.getPath());
System.out.println("getAbsolutePath(): " + f.getAbsolutePath());
System.out.println("getParent(): " + f.getParent() );
System.out.println("getCanonicalPath(): " + f.getCanonicalPath() );
System.out.println("getAbsoluteFile().getCanonicalPath(): " + f.getAbsoluteFile().getCanonicalPath() );
String dirname = f.getCanonicalPath();
System.out.println("dirname: " + dirname);
File dir = new File(dirname);
System.out.println("dir: " + dir.getAbsolutePath());
if (dirname.endsWith(fileName))
dirname = dirname.substring(0, dirname.length() - fileName.length());
System.out.println("dirname: " + dirname);
File dir2 = new File(dirname);
System.out.println("dir2: " + dir2.getAbsolutePath());
}
public static void main(String[] args) {
DirectoryFromFile dff = new DirectoryFromFile();
try {
dff.getDirectoryOfFile("test.txt");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here' the output:
exists(): true
getPath(): test.txt
getAbsolutePath(): C:\dean\src\java\directorytest\directory.from.file\test.txt
getParent(): null
getCanonicalPath(): C:\dean\src\java\directorytest\directory.from.file\test.txt
getAbsoluteFile().getCanonicalPath(): C:\dean\src\java\directorytest\directory.from.file\test.txt
dirname: C:\dean\src\java\directorytest\directory.from.file\test.txt
dir: C:\dean\src\java\directorytest\directory.from.file\test.txt
dirname: C:\dean\src\java\directorytest\directory.from.file\
dir2: C:\dean\src\java\directorytest\directory.from.file
So far the only way I've found to get the directory in this case is to manually parse off the file name.
Does the File class have a way to get the directory name in this case (where a File that exists in the current directory is created without specifying a directory)?
Why do File.getAbsolutePath() and File.getCanonicalPath() include the
file name? The Javadocs indicate that the directory name should be
returned.
No, they don't. If you'd care to point out why you think they do, someone can probably identify the mistake in your reasoning. Also, if you specify exactly what you'd like to see for output given some particular input, we can help you out there, too. Your question title seems strange, too, since your problem seems to be that it is returning the full path to a file.
Edit: I think I understand the source of your confusion. A File represents a file system path in a platform-agnostic way. It can be a path to a file or to a directory. It also always represents the same path, though not necessarily the same absolute path. This is a very fine distinction but a very important one. A File object representing a relative path is always relative. Given a File representing a relative path, you can get the current corresponding absolute path using getAbsolutePath(). This doesn't, however, alter the fact that the File represents a relative path. Further invocations of getAbsolutePath() on the same File object may return different values. Consider, for example:
// A relative file
File foo = new File("foo.txt");
// Resolve relative file against CWD
System.out.println(foo.getAbsolutePath());
// Output: D:\dev\projects\testbed\foo.txt
System.setProperty("user.dir", "C:\\somewhere");
// Resolve relative file against new CWD
System.out.println(foo.getAbsolutePath());
// Output: C:\somewhere\foo.txt
// Get an absolute file
File absoluteFoo = foo.getAbsoluteFile();
// Show absolute path
System.out.println(absoluteFoo.getAbsolutePath());
// Output: C:\somewhere\foo.txt
System.setProperty("user.dir", "D:\\somewhere-else");
// An absolute path doesn't change when the CWD changes
System.out.println(absoluteFoo.getAbsolutePath());
// Output: C:\somewhere\foo.txt
It should be clear now that the path a File represents is only that: a path. Further, a path can be composed of zero or more parts, and calling getParent() on any File gives back the path of that File with the last path element removed unless there isn't a "last path element" to remove. Thus the expected result of new File("foo").getParent() is null since the relative path "foo" has no parent.
From the example and explanation above, you should be able to see that the way to get the containing directory when you've created relative-path File object is with
String absoluteParentDirPath = someRelativeFile.getAbsoluteFile().getParent();
with the caveat that the "absolute path" depends on your environment at the time.
Additional note: Since File is Serializable, you could write a relative-path file to disk or send it across a network. That File, when deserialized in another JVM, will still represent a relative path and will be resolved against whatever the current working directory of that JVM happens to be.
The behaviour is expected. The documentation does not mention that the filename is not included.
Perhaps you are confused by the difference between getAbsolutePath() and getAbsoluteFile(). It's that the latter returns a File instance.
I'm not sure why you think the Javadoc says that it returns the directory name.
Here is the Javadoc --
An abstract representation of file and directory pathnames.
User interfaces and operating systems use system-dependent pathname strings to name files and directories. This class presents an abstract, system-independent view of hierarchical pathnames. An abstract pathname has two components:
An optional system-dependent prefix string, such as a disk-drive specifier, "/" for the UNIX root directory, or "\\" for a Microsoft Windows UNC pathname, and
A sequence of zero or more string names.
The first name in an abstract pathname may be a directory name or, in the case of Microsoft Windows UNC pathnames, a hostname. Each subsequent name in an abstract pathname denotes a directory; the last name may denote either a directory or a file. The empty abstract pathname has no prefix and an empty name sequence.
http://download.oracle.com/javase/6/docs/api/java/io/File.html#getAbsolutePath%28%29
Returns the absolute pathname string of this abstract pathname.
In addition to the existing answers with regards to getAbsolutePath and getCanonicalPath, please also note, that File.getParent() does not mean "parent directory" it merely refers to the parent file object that was used to create the file.
For example, if the file object can be created as such:
File dir = new File("/path/to/a/directory");
File f1 = new File(dir, "x.txt");
File f2 = new File(dir, "../another/y.txt");
File f3 = new File("z.txt");
f1 would refer to /path/to/a/directory/x.txt, it's parent is dir (/path/to/a/directory)
f2 would refer to /path/to/a/directory/../another/y.txt, it's canonical path would be /path/to/a/another/y.txt, but it's parent is still the reference to dir (/path/to/a/directory)
f3 would refer to z.txt in the current directory. It does not have a parent file object, so f3.getParent() or f3.getParentFile() would return null.
path is the full path
if you only want the directory you need to call file.getParent()