Java 7 glob issue - java

As much I want, I can't truly understand how to deal with glob in java.
below a short program:
public class Test{
public static void main(String args[]) throws IOException{
Path p1 = Paths.get("C:\\Users\\all\\Test\\cool.jpg");
Path p2 = Paths.get("cool.jpg");
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**/*.jpg")
System.out.println(matcher.matches(p1));
System.out.println(matcher.matches(p2));
}
}
The result is TRUE / FALSE
Running with "glob: *.jpg" the result is FALSE
/ TRUE
So it looks like first time it search outside of the folder were is located the project (java file) and second time in the folder were is locate the java file.
If I change the second path to any other location (other than my java project is located) the result is: for glob:**/*.jpg -> TRUE/TRUE and for glob: *.jpg -> FALSE/FALSE.
So my question is: I understood well that using glob:*.??? it search in the folder were java project is located and using glob:**/*.??? it search to a specific path other than the folder were java project is located. Because in the documentation is written:
A glob pattern is specified as a string and is matched against other strings, such as directory or file names. Glob syntax follows several simple rules:
An asterisk, *, matches any number of characters (including none).
Two asterisks, **, works like * but crosses directory boundaries. This syntax is generally used for matching complete paths.
But nowhere is mentioned that the directory boundaries referring to the directory where Java project is located.

Change the glob pattern to this:
"glob:**.jpg"
Your pattern matches only file paths containing at least one directory.
For example following pattern matches only paths with at least two directories (ex path: a/b/image.jpg)
"glob:**/**/*.jpg"
And just FYI it does not search the files, it only tests whether given path matches the pattern.

Related

Error message: The file "countries.geo.json" is missing or inaccessible

I am taking the Coursera OOP in Java class. In the module 4 assignment, I run the code that the course provides in EarthquakeCityMap.java,
and I get an error as "The file "countries.geo.json" is missing or inaccessible, make sure the URL is valid or that the file has been added to your sketch and is readable.
Exception in thread "Animation Thread" java.lang.NullPointerException"
I tried to set countryFile as
"../data/countries.geo.json",
"data/countries.geo.json",
and the complete path of countries file,
but still didn't solve the problem.
//this error points to the code
private String countryFile = "countries.geo.json";
List<Feature> countries = GeoJSONReader.loadData(this, countryFile);"
//the countries file is saved in data folder.
Poject folder listing
"countries.geo.json" (unless changed in GeoJSONReader manipulates this path) will be relative to the compiled java .class files in the IntelliJ's project out folder.
If this in GeoJSONReader.loadData(this, countryFile); is a PApplet instance you can use sketchPath() to make that path relative to the folder from which the sketch runs:
List<Feature> countries = GeoJSONReader.loadData(this, this.sketchPath("data"+File.separator+countryFile));
The above snippet is based on an assumption so the syntax in your code might be slightly different, but hopefully this illustrates how you'd use sketchPath().
Additionally there's a dataPath() as well which you can test from your main PApplet in setup() as a test:
String fullJSONPath = dataPath("countries.geo.json");
println("fullJSONPath: " + fullJSONPath);//hopefully this prints the full path to the json file on your machine
println(new File(fullJSONPath).exists());//hopefully this prints true
If you specified the full path and it didn’t work, you probably forgot to escape the \ character with another backslash. The backslash character is special and needs to be doubled for windows path to be interpreted properly. For instance “c:\\users\\...”. You can also specify / instead of \ and it would work : “c:/users/...”
That said, the path resolution of a file when relative (IE not being absolute to the file system root) is relative to the working directory of the executed app. Typically, in an IDE without any special configuration, the working directory would be the root path of the project. So in order to get the relative file path resolved properly, you would have to specify the path as “data/countries.geo.json”.
You can also find out what path you are in when you run the app by doing a System.out.println(new java.io.File(“.”).getAbsolutePath()) and craft the relative path according to this folder.

Build relative path between two file path

I would like to compare two paths in the same workspace folder, and get the relative path between them :
String firPath = "C:/toto/tata/test1/test2/img/1.jpg" // test example
String secPath = "C:/toto/tata/test1/img/1.jpg" // test example
And return firstPath relative path from secondPath
example = "../../img/"
I found lots of example in different language (python, .net, c++ ...) :
How to get relative path from absolute path
compare path and get relative path between two files with javascript
...but no solution with java.
Most of the time, what is use are libraries methods, and I was wondering if java had the same methods I could use.
Thank you for your help.
What about added in Java 7 Path.relativize?
Path first = Paths.get(firstPath); Path second = Paths.get(secondPath);
System.out.println(first.relativize(second));
System.out.println(second.relativize(first));

get file list from glob without specifying base directory

There are previous questions about checking if a file matches a glob pattern (here is one). However, I would like to get a list of files that match a glob pattern without having to specify the base directory to search. I need to accept both relative and absolute directories (I resolve the relative ones to a specified directory), and it needs to be cross-platform compatible.
Given a string such as "C:/users/foo/", "/user/foo/.txt" or "dir/*.txt", how do I get the list of matching paths?
Yes, you'll need a programmatic way to find out if a glob pattern is absolute. This can be done as follows:
for (String glob : new String[] { "../path/*.txt", "c:/../path/*.txt", "/../path/*.txt" }) {
System.out.println(glob + ": is " + (new File(glob).isAbsolute() ? "absolute" : "relative"));
}
On Windows this will output
../path/*.txt: is relative
c:/../path/*.txt: is absolute
/../path/*.txt: is relative
On unix the last is absolute. If you know the glob pattern is relative, prepend the special directory to it. After that you'll have an absolute path for all glob patterns and can use that to specify it for the search.
EDIT 1
As per you comment, you can do the following. But you can also mix and match nio and io. You should know that java.io.File.isAbsolute() only checks the file path FORMAT, not if the file actually exists, to determine if it's in absolute or relative form. It does that in a platform specific manor.
String baseDir = "c:/BaseDir/";
for (String glob : new String[] { "../path/*.txt", "c:/../path/*.txt", "/../path/*.txt" }) {
File file = new File(glob);
if (!file.isAbsolute()) {
file = new File(baseDir, glob);
}
System.out.println(file.getPath() + ": is " + (file.isAbsolute() ? "absolute" : "relative"));
}
this will print
c:\BaseDir\..\path\*.txt: is absolute
c:\..\path\*.txt: is absolute
c:\BaseDir\..\path\*.txt: is absolute
you will still have to do the globbing yourself or use any methods described in the post you mentioned (How to find files that match a wildcard string in Java?)

How to get the file path of a file

If I already have an existing file and I want to know its path using only its name, how can I do this?
I have the following code, but it return the name of the file even when it does not exists:
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:**.{java,class}");
Path filename = Paths.get("Go,mvDep.java");
if (matcher.matches(filename)) {
System.out.println(filename);
}
Thank you for your help!
I think the core of your confusion is that a Path does not necessarily represent a file on your computer. It is simply a Java object that represents a conceptual object in a file system. In the same way that you could construct a new Person("John", "Smith") without actually knowing anyone named 'John Smith', you can construct a Path regardless of whether or not a file exists at the given location.
Once you have a Path there are a number of things you can do with it, including check if it exists via Files.exists(), or create it with Files.createFile(). Generally speaking, the Files class lets you inspect and work with the actual file system objects a Path represents.
The intent of a PathMatcher is similarly disconnected from the actual file system; it exists to to determine if a given Path fits the PathMatcher's pattern - it's basically a Path-specific regular expression engine.
So what your code is actually doing is:
Creating a glob that will match any path which ends in .java or .class (regardless of whether such a path exists anywhere).
Constructing a relative Path to a file called Go,mvDep.java. Implicitly this path is relative to the current working directory, but you could pass it to Path.resolve() to create a new Path referring to a file in a different location.
Checking if the path Go,mvDep.java matches your glob, which it does since it ends in .java, so it prints the path.
It sounds like what you actually want is to find an existing file with the name Go,mvDep.java. If so, you want to use Files.find() to search a directory and return a stream of the files that match a BiPredicate<Path, BasicFileAttributes> matcher you define. Your matcher might look something like this:
new BiPredicate<Path, BasicFileAttributes>() {
public boolean test(Path path, BasicFileAttributes attributes) {
return matcher.matches(path);
}
}
Or in Lambda syntax simply:
(p, a) -> matcher.matches(p)

Why the JVM is not able to detect some invalid paths

I want to know why the JVM doesn't throw any exception when it is asked to create an invalid path such "C:invalidPath".
For example :
public static void main(String[] args) {
File f = new File("C:invalidPath");
f.mkdir();
}
The previous example create a folder named "invalidPath" in the current folder. I think that this is not normal .
The path you have specified is a legal path on Microsoft Windows. It is specified as path relative to the current working directory on the volume C. On Windows, as on DOS before it, each volume has a separate working directory associated with it, and additionally there is the notion of the current working volume.
This is not the JVM's fault or responsibility.
It is up to the underlying filesystem to convert a path specification (i.e. string) into the actual logical files that the name represents. The JVM just passes through this string to the filesystem, which determines how to handle it.
So the real question is "why does NTFS [assuming that's what you're using] interpret 'C:invalidPath' as creating that file in the current directory?". And the reason is simply, that's how paths are defined for this filesystem.
From the documentation:
If a file name begins with only a disk designator but not the backslash after the colon, it is interpreted as a relative path to the current directory on the drive with the specified letter. Note that the current directory may or may not be the root directory depending on what it was set to during the most recent "change directory" operation on that disk. Examples of this format are as follows:
"C:tmp.txt" refers to a file named "tmp.txt" in the current directory on drive C.

Categories