I've been using Java 7's ZipFS support.
https://gist.github.com/stain/5591420
shows the behaviour, which I find a bit odd. Basically you can create a ZIP file system, make a file with a given name, and then also make a folder with the same name.
The reason for this seems to be that internally the folder gets "/" appended to its name - however this new name is not returned, therefore you end up in a strange situation where Files.isDirectory() returns false immediately after a successful Files.createDirectory().
try (FileSystem fs = tempZipFS()) {
Path folder = fs.getPath("folder");
Files.createFile(folder);
assertTrue(Files.isRegularFile(folder));
assertFalse(Files.isDirectory(folder));
// try {
Files.createDirectory(folder);
// } catch (FileAlreadyExistsException ex) {
// Is not thrown!
// }
// but a second createDirectory() fails correctly
try {
Files.createDirectory(folder);
} catch (FileAlreadyExistsException ex) {
}
// Look, it's both a file and folder!
Path child = folder.resolve("child");
Files.createFile(child);
// Can this be tested?
assertTrue(Files.isRegularFile(folder));
// Yes, if you include the final /
assertTrue(Files.isDirectory(fs.getPath("folder/")));
// But not the parent
// assertTrue(Files.isDirectory(child.getParent()));
// Or the original Path
// assertTrue(Files.isDirectory(folder));
}
So as long as you have the "/" as the suffix, you can even work with both, and that's how they are listed if you do a directory listing of the root.
Now the ZIP format itself allows this as it only deals with entries in a ZIP file (even allowing multiple entries with the same name), however normal use of a "FileSystem" would normally not allow multiple entries with the same name ; as can be seen when I try to create the folder twice.
The produced ZIP file can be browsed correctly with infozip, 7Zip and Windows 8; but trying to unzip will obviously fail because the native file system don't support such duality.
So is this a feature, bug or something in between?
Related
private void copyFile() throws IOException {
Path destination;
String currentWorkingDir = System.getProperty("user.dir");
File fileToCopy = component.getArchiveServerFile();
if (path.contains(File.separator)) {
destination = Paths.get(path);
} else {
destination = Paths.get(currentWorkingDir + File.separator + path);
}
if (!Files.exists(destination)) {
try {
Files.createDirectories(destination);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
FileUtils.copyFileToDirectory(fileToCopy, new File(destination.toString()));
}
}
Basically what I'm trying to do here is copying a file in some location using the path provided in the class's constructor. The logic is like this:
If the path has file separator, I consider it a full path and copy the file at the end.
If the path doesn't have file separator, I copy the file in the working directory from which the .exe file was launched.
So far, only the first option works (the full path). For some reason, the working directory option is not working and I can't figure out why.
UPDATE: If I just change the following line:
String currentWorkingDir = System.getProperty("user.dir");
to
String currentWorkingDir = System.getProperty("user.home");
It works. So I'm guessing the problem is coming from user.dir? Maybe at runtime, the folder is already being used and as a result, it can't copy the file into it?
The weird thing is, I don't have any exceptions or error, but nothing happens as well.
UPDATE 2: I think the problem here is that I'm trying to copy a file which is embedded in the application (.exe file) that I'm executing during runtime, and java can't copy it while the current working directory is being used by the application.
UPDATE 3:
Since this copy method is used in an external library, I had to come up with another way (other than logs) to see the content of system property user.dir. So I wrote I little program to create a file and write in it the value return by the property.
To my surprise, the path is not where my application was launched. It was in:
C:\Users\jj\AppData\Local\Temp\2\e4j1263.tmp_dir1602852411
Which is weird because I launched the program from :
C:\Users\jj\workspace\installer\product\target\
Any idea why I'm getting this unexpected value for user.dir?
I just did a little project in java, packed the .jar and application.properties to my VPS and wanted to test it there. The tool reads logfiles.
I specified the path to the logfile within the application.properties as follows:
LOGPATH=/folder1/folder2/logs/thelogIwant.log
The path is parsed as follows:
public String makePath(String path) {
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream("application.properties");
prop.load(input);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return prop.getProperty(path);
}
Path logFile = Paths.get(makePath("LOGPATH"));
It even seems to to this right, as the ErrorMessage states:
SEVERE: /folder1/folder2/logs/thelogIwant.log (No such file or directory)
The logfile is being created by another application and therefore in another directory than the .jar I am running.
The path exists on my VPS and I can navigate to and through it.
Can someone point me in the right direction? What's going wrong here?
Things I tried:
Specify path with "~/folder1/..."
Specify path with "folder1/..."
I can think of a few possible explanations:
The pathname in your config file is wrong; e.g. there is a typo or some other discrepancy that you didn't notice.
You are loading a different property file to the one that you think.
There is a mismatch between the property name in the file and the name that your tool uses.
The other application didn't create the log file
Permissions: your tool may be running as a user that isn't permitted to read one of the directories on the path.
SELinux in enforcing mode can prevent an application (e.g. running as a service) from accessing files.
Homoglyphs, either in the property file1, your source code or the name of the file in the file system.
The things that you tried are unlikely to work. A correct absolute pathname is more robust than a relative pathname, and Paths.get doesn't know how to deal with ~. (The expansion of ~ is a shell feature ....)
I would try this:
Modify your tool to output the value of the "LOGPATH" property ... enclosed in quote characters so that you can see any spurious whitespace characters at the beginning / end of the value.
Run the tool.
Using copy-and-paste, see if you can open the file using exactly the pathname that your tool uses.
In short, verify that the pathname you are actually using is what you expect it to be.
1 - In practice, classic format property files are encoded in LATIN-1, so this is impossible.
I was able to fix this, thanks #Steven for your help!
I used the pwd command when in the directory the files are in and recognized that the true absolute path starts with /home/myusername/folder1/...
Works fine now.
I have written a java program to push to a git repository where I am pushing specific files at a time instead of pushing all files.
try {
git.add().addFilePattern("files\\file1.txt").call();
} catch (Exception e) {
e.printStackTrace();
}
But if file1.txt is not present, the catch block is not entered.
If I do the same thing with CLI Git, it gives exception as
fatal: pathspec 'D:\mygit\files\\file1.txt' did not match any files
I want to catch this exception in Java using JGit.
JGit version 4.6.0, Java 1.8, Windows 10
JGit does not consider it as an error to pass a non-existing path addFilepatern(). The reason, therefore, could be that the method also accepts a file name pattern. And such a pattern may or may not match files.
You will have to check the existence of the file yourself. Either with the Java file API, for example
boolean fileExists = new File( repository.getWorkTree(), "file.txt" ).isFile();
Or through the DirCache returned from AddCommand::call(), for example
DirCache dirCache = git.add().addFilePattern( "file.txt" ).call();
boolean fileExists = dircache.findEntry( "file.txt" ) >= 0;
I have created a simple java program that in a nutshell takes two directories and then moves one to another. The program works fine unless I try to move files across different drives, then in causes java.nio.file.DirectoryNotEmptyException even though it doesn't mind non-empty directories otherwise (in fact I need it to move everything inside of it).
try {
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e1) {
System.out.println("Something went wrong");
e1.printStackTrace();
}
Files.move(file, cgbaFile.getParent(), StandardCopyOption.REPLACE_EXISTING);
For the target, you're providing the directory you want to move the file into. This is incorrect. The target should be the new pathname that you want the file to have--the new directory plus the filename.
For example, suppose you wanted to move /tmp/foo.txt to the /var/tmp directory. You're calling Files.move("/tmp/foo.txt", "/var/tmp") when you should be calling Files.move("/tmp/foo.txt", "/var/tmp/foo.txt").
You're getting that specific error because the JVM is trying to delete the target directory in order to replace it with the file.
One of these ought to generate the correct target path:
Path target = cgbaFile.resolveSibling(file.getFileName());
Path target = cgbaFile.getParent().resolve(file.getFileName());
This is not actually a question, but I need explanation. I was trying to create directory under C:// drive. So;
try {
File f_paz = new File("c://Ekap_Pazarlik_xml" + file_currentDate + "//");
File parent_z = f_paz.getParentFile();
if (null != parent_z) {
parent_z.mkdirs();
}
if (!f_paz.exists()) {
f_paz.createNewFile();
}
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
I tried that and it gave me "Access Denied" error, so I tried all the solutions in the web. Nothing happened.
Strangely, I decided to put "space" after there;
File f_paz = new File("c://Ekap_Pazarlik_xml" + file_currentDate + "// ");
here
just after "// ", and it worked. I was able to crate directory like that. I have no idea why it worked like that. Please provide me some explanation. Thanks !
f_paz.createNewFile(); will try to create a new file, not a directory. Many Windows systems won't allow you to create files in directly in C: so that's why you get the exception.
Since you want to create a directory and not a file use f_paz.mkdir(); instead. You don't need the "//" at the end, btw.
What happens if you add the space, i.e. use path "C:/Ekap_xxx/ "? The system will see a path with a blank filename " " and a parent directory name "Ekap_xxx". Now parent_z will refer to "C:/Ekap_xxx" and thus parent_z.mkdirs(); will create directory "Ekap_xxx". Now f_paz.exists() will return true since the filesystem seems to decide a file with an invalid name still exists (I'd have to look for some information on why that is so, it's hidden in the native code).