Odd isDirectory behaviour - java

I've looked around at similar questions on here but none of the answers I have attempted have proven useful. I am attempting to load a directory that exists on the web. When I navigate to the path that my program is generating, it is definitely a directory. However, when I attempt to use isDirectory on the file object representing the path, it doesn't work.
Snippet where I Generate the file
if (sport == null || sport.trim().length() == 0) {
return null;
}
File dayDirectory = new File(aggregatorRootDirectory, new SimpleDateFormat("yyyy-MM-dd").format(date));
String sportDirectory = sport.replace(",", "");
return new File(dayDirectory + "\\" + sportDirectory + "\\");
The path that this is generating is valid, and is definitely a directory. The directory is a website link, if that makes a huge difference?
Snippet where I use the file
try {
if (directory == null || !directory.getCanonicalFile().isDirectory() ||
fileNamePattern == null || fileNamePattern.trim().length() == 0) {
return null;
}
} catch (IOException e) {
e.printStackTrace();
}
File[] files = directory.listFiles();
This attempt is throwing a java.io.IOException with the message:
The filename, directory name, or volume label syntax is incorrect.
The error is occuring in the if statement, when I attempt to call getCanonicalFile().
When I remove the getCanonicalFile() method call, it resolves to false when I call isDirectory.
If I remove the check all together, listFiles() resolves to null, which is making me think there's something more to this.
Is there a common issue with isDirectory and web links, or is there a way to force a file object to intepret a path as a directory?
Edit
Below is the Scala code that performed the desired functionality. The following function grabbed the list of files from the online directory:
private def getFiles(directory: File, fileNamePattern: String): Seq[Elem] = {
if(directory == null || ! directory.isDirectory
|| fileNamePattern == null || fileNamePattern.trim.length == 0) {
return Nil
}
val filesList = directory.listFiles( new FilenameFilter {
override def accept(dir: File, name: String) = { name.matches(fileNamePattern)
} } )
val sortedFilesList = filesList.sortBy(_.lastModified)
val feedsList = mutable.ListBuffer[Elem]()
for(file <- sortedFilesList) {
try {
feedsList += XML.loadFile(file) % new UnprefixedAttribute("original-filePath", file.getCanonicalPath, Null)
}
catch {
case _ => // TODO log
}
}
feedsList
}
And this function created a new File object from said directory.
private def getSportDirectory(sport: String, date: Date = new Date): File = {
if(sport == null || sport.trim.length == 0) {
return null;
}
val dayDirectory = new File(aggregatorRootDirectory, new SimpleDateFormat("yyyy-MM-dd").format(date))
val sportDirectory = sport.replace(",", "") // resolving sports like "HR,DG" to "HRDG". Not ideal but ...
new File(dayDirectory, sportDirectory)
}

The directory is a website link, if that makes a huge difference?
Yes, it absolutely does. File is intended for file systems - not HTTP.
Basically, you shouldn't be using File* classes if you're trying to do things with web resources. Just because various applications (e.g. Windows Explorer) try to hide the differences between the two doesn't mean you can always do so in code.
For example, I don't believe that there is a generic HTTP equivalent of "list files" for a directory. You request a specific resource - and that may return a directory listing, but it could equally give the default page for a directory.

Related

file.exists return false when folder is not empty

I am trying to access a file in remote shared location.
////hostname//data//upload//123//test.txt
File sourceFile=new File("////hostname//data//upload//123//test.txt");
sysout("sourceFile.exists()"+sourceFile.exists())//returning false
If a directory is empty file.exists() is returning true.
I am using Java 1.6
I don't understand what is this weird behavior.
First of all to come back to Erwin´s suggestion, this is not the right attempt. The character \ is used in Java as an escape sequence, usually to print out reserved characters. For example will
String s = "The weather is really "nice" today";
result in an error, as " is already reserved for strings. The correct version would be
String s = "The weather is really \"nice\" today";
Coming back to the question, you have to know that when you create a file and test if it exists Java will validate the abstract pathname of the file. That said, if your abstact path is a directory and it exists true will be returned.
Edit:
If you intend to check if an abstract pathname is a directory try the following:
// Check if a file is a directory
if(file.isDirectory()) {
}
// Check if a file contains something
if(file.list().length > 0) {
}
Check this example ,it checks the directory else creates a new one then your new file created.
File f = new File("D:/image_send");
File file = new File("D:/image_send/" + date + ".txt");
try {
if(!f.isDirectory()){
f.mkdirs();
}
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("File created Success");
public static boolean fileTransfer(String src, String des) throws Exception {
if (des == null || des.equals("") || src == null || src.equals("")) {
return false;
}
File fileExisting = new File(src);
File fileNew = new File(des+ fileExisting.getName());
if (fileExisting.exists() && !fileExisting.isDirectory()) {
if (fileExisting.renameTo(fileNew)) {
System.out.println("File is moved successful!");
} else {
System.out.println("File is failed to move!");
}
}
return fileNew.exists();
}
This is the code for file transfer as per your comment ,use src as sourcepath and des as destination path if you get a boolean false,that means path given is wrong.

Odd Bug , using File.RenameTo()

I have a program in which i must rename a set of folders. they are all in "ID [Name]" format, and I want to rename them to "Name [ID]". (Its more of a training for me, for learning java))
the problem is, if the number of folders it must rename go beyond 20-24 . the program won't work, and will give the files faulty names. (the renaming process succeeds, but names are wrong)
but if they are below 20 folders, it works perfectly.(tested with the same folders)
here's the whole code:
public class DirRename {
private String parentDir;
private DirectoryStream<Path> fileList;
public DirRename(final Path dir)
{
parentDir = dir.toString();
if(!Files.exists(dir) || !Files.isDirectory(dir) || !Files.isReadable(dir))
System.out.println("Directory Read Error!!!");
//filter to return only directories in parent folder
DirectoryStream.Filter<Path> dirOnlyFilter =
new DirectoryStream.Filter<Path>() {
public boolean accept(Path file) throws IOException {
return (Files.isDirectory(file));
}
};
try
{
fileList = Files.newDirectoryStream(dir,dirOnlyFilter);
}
catch(IOException | DirectoryIteratorException x)
{
System.err.println(x);
}
}
public void rename()
{
for(Path filepath : fileList)
{
String name = filepath.getFileName().toString();
File inFile = filepath.toFile();
if(!inFile.exists() || !inFile.isDirectory() || !inFile.canWrite())
{
System.out.println("Directory is not writeable");
return;
}
Pattern regex = Pattern.compile("((?:[\\w\\d]*(?:\\s|-){0,2}[\\w\\d]+)*)\\s*-*\\s*(?:\\[|\\Q(\\E)(.+)(?:\\]|\\Q)\\E)$");
Matcher match = regex.matcher(name);
while(match.find())
{
String gameID = match.group(1);
String gameName = match.group(2);
String rename = parentDir+File.separator+gameName+" ["+gameID+"]";
File toFile = new File(rename);
if(!Paths.get(rename).isAbsolute())
{
System.out.println("Cannot rename "+name+"to "+rename);
return;
}
if(inFile.renameTo(toFile))
System.out.println("Success!");
else
System.out.println("Renaming Failed!!! for "+rename);
}
}
}
}
I tried checking the names with "system.out.println(toFile.getName())" while deleting the line "inFile.renameTo(toFile)". all names were correct.
but when i added that line back, the same names were printed incorrectly.(although some that were printed correctly were renamed incorrectly)
I'm completely confused. and I'm new to java, and generally less than a noob programmer. can someone please tell me what's going on?
Many thanks
EDIT: I found the problem.the loop:
for(Path filepath : fileList){}
runs 116 times while i only have 64 folders. I can't find any explanation as to why this happens, I use the same loop to print folder names only in the following function and it runs exactly 64 times.( exactly the number of folders I have)
public void printFolders()
{
for(Path filepath : fileList)
System.out.println(filepath.getFileName());
}
okay I finally Fixed my own problem. here's my guess on why this happened (I don't know the inner working of DirectoryStream so its just a guess).
when the folders were more than a few, the stream would read the previously renamed folders and add them as new folders, thus they were getting renamed twice. either changing the name back to original, or deforming it (the renaming wasn't designed to be 100% re-applicable).
In case of a few folders, the loop would be over before the stream had the chance to refresh, thus no problems.
so here's how i fixed it. by adding the following method, and iterating through an array of paths instead of the stream.
private Path[] getVerifiedPaths()
{
ArrayList<Path> verifiedFilePaths= new ArrayList<>();
for(Path filepath : fileList)
verifiedFilePaths.add(filepath);
return verifiedFilePaths.toArray(new Path[0]);
}
Path[] filePaths = getVerifiedPaths();
for(Path filePath : filePaths) { ...rename...}
instead of:
for(Path filepath : fileList){...rename...}
thanks to "JB Nizet" for his suggestion (comment above).

Java thinks C:\ drive is hidden?

I think it's better if I explain the situation first.
Situation
I'm writing a bit of software that filters through a Set of Files.
The filter is the following: If the file is NOT hidden, then add it it to the new Set.
The problem is that the current behaviour of File.isHidden() is as follows:
File f = new File("C:\Documents and Settings\Administrator\Local Settings\Temp\REG28E.tmp");
System.out.println(f.isHidden());
The program will output false.
The file itself (REG28E.tmp) is NOT actually hidden. Rather, a certain folder in the path to it is hidden (Local Settings).
I want to create a bit of code that will check:
If, somewhere along the path to the file is hidden, then the file is marked as hidden.
I've come up with the following solution to check the file's path recursively:
boolean hidden = file.isHidden();
File parentFile = file.getParentFile();
while ((hidden == false) || (parentFile != null)) {
hidden = parentFile.isHidden();
parentFile = parentFile.getParentFile();
}
if (!hidden) {
acceptedFileList.add(file);
}
The Problem
And finally, we come to the problem. I can never get to the stage where I'm actually adding files. The problem is that Java thinks that the C:\ drive itself is hidden!
What can I do instead?
The solution involved adding a manual check to see whether the parentFile object is a root directory or not.
while ((hidden == false) && (parentFile != null)) {
// added the IF statement below:
if (FileSystemUtils.isRoot(parentFile)) {
hidden = false;
break;
}
hidden = parentFile.isHidden();
parentFile = parentFile.getParentFile();
}
Checking if Root directory
The above code makes use of a FileSystemUtils class. It contains the following method:
public static boolean isRoot(File file) {
File[] roots = File.listRoots();
for (File root : roots) {
if (file.equals(root)) {
return true;
}
}
return false;
}
Thanks to all who chimed in...
My guess is your while condition needs the && operator instead of || (It probably caused some NPE).
Try:
while (!hidden && (parentFile != null)) {...

File Directory and File Creation Problems

I have problems with the following code. I am trying to look at an existing directory to see if a file exists before creating a new one, but it doesnt seem to create a new file even though there are no existing ones in the directory. I have attached the two relevant methods, but the problem lies with the writeFile() method. I tried to use the existing 'dir' in writeFile, this didnt do the trick either. The rest of the program does seem to work, just the writeFile method has problems.
public void writeFile(String t) throws IOException {
File temp1 = new File(dateNow + File.separator + "Temperature.txt");
boolean check = temp1.exists();
if (!check)
newFiles();
}
public void newFiles() {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
dateNow = formatter.format(now.getTime());
System.out.println(dateNow);
// if (hour == 00 && mini == 00 && sec == 00) {
try {
dir = new File(dateNow);
boolean x = dir.mkdir();
// ....
} catch (Exception e) {
//
}
}
you need to specify the full path, not just the directory and the file name to create a file or even check it's existence,.
thank you for michael667, you remind me about the relative position is right,. :)
and there should be no problem with the above code,.

Determine which JAR file a class is from

I am not in front of an IDE right now, just looking at the API specs.
CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
if (src != null) {
URL jar = src.getLocation();
}
I want to determine which JAR file a class is from. Is this the way to do it?
Yes. It works for all classes except classes loaded by bootstrap classloader. The other way to determine is:
Class klass = String.class;
URL location = klass.getResource('/' + klass.getName().replace('.', '/') + ".class");
As notnoop pointed out klass.getResource() method returns the location of the class file itself. For example:
jar:file:/jdk/jre/lib/rt.jar!/java/lang/String.class
file:/projects/classes/pkg/MyClass$1.class
The getProtectionDomain().getCodeSource().getLocation() method returns the location of the jar file or CLASSPATH
file:/Users/home/java/libs/ejb3-persistence-1.0.2.GA.jar
file:/projects/classes
Checkout the LiveInjector.findPathJar() from Lombok Patcher LiveInjector.java. Note that it special cases where the file doesn't actually live in a jar, and you might want to change that.
/**
* If the provided class has been loaded from a jar file that is on the local file system, will find the absolute path to that jar file.
*
* #param context The jar file that contained the class file that represents this class will be found. Specify {#code null} to let {#code LiveInjector}
* find its own jar.
* #throws IllegalStateException If the specified class was loaded from a directory or in some other way (such as via HTTP, from a database, or some
* other custom classloading device).
*/
public static String findPathJar(Class<?> context) throws IllegalStateException {
if (context == null) context = LiveInjector.class;
String rawName = context.getName();
String classFileName;
/* rawName is something like package.name.ContainingClass$ClassName. We need to turn this into ContainingClass$ClassName.class. */ {
int idx = rawName.lastIndexOf('.');
classFileName = (idx == -1 ? rawName : rawName.substring(idx+1)) + ".class";
}
String uri = context.getResource(classFileName).toString();
if (uri.startsWith("file:")) throw new IllegalStateException("This class has been loaded from a directory and not from a jar file.");
if (!uri.startsWith("jar:file:")) {
int idx = uri.indexOf(':');
String protocol = idx == -1 ? "(unknown)" : uri.substring(0, idx);
throw new IllegalStateException("This class has been loaded remotely via the " + protocol +
" protocol. Only loading from a jar on the local file system is supported.");
}
int idx = uri.indexOf('!');
//As far as I know, the if statement below can't ever trigger, so it's more of a sanity check thing.
if (idx == -1) throw new IllegalStateException("You appear to have loaded this class from a local jar file, but I can't make sense of the URL!");
try {
String fileName = URLDecoder.decode(uri.substring("jar:file:".length(), idx), Charset.defaultCharset().name());
return new File(fileName).getAbsolutePath();
} catch (UnsupportedEncodingException e) {
throw new InternalError("default charset doesn't exist. Your VM is borked.");
}
}
Use
String path = <Any of your class within the jar>.class.getProtectionDomain().getCodeSource().getLocation().getPath();
If this contains multiple entries then do some substring operation.
private String resourceLookup(String lookupResourceName) {
try {
if (lookupResourceName == null || lookupResourceName.length()==0) {
return "";
}
// "/java/lang/String.class"
// Check if entered data was in java class name format
if (lookupResourceName.indexOf("/")==-1) {
lookupResourceName = lookupResourceName.replaceAll("[.]", "/");
lookupResourceName = "/" + lookupResourceName + ".class";
}
URL url = this.getClass().getResource(lookupResourceName);
if (url == null) {
return("Unable to locate resource "+ lookupResourceName);
}
String resourceUrl = url.toExternalForm();
Pattern pattern =
Pattern.compile("(zip:|jar:file:/)(.*)!/(.*)", Pattern.CASE_INSENSITIVE);
String jarFilename = null;
String resourceFilename = null;
Matcher m = pattern.matcher(resourceUrl);
if (m.find()) {
jarFilename = m.group(2);
resourceFilename = m.group(3);
} else {
return "Unable to parse URL: "+ resourceUrl;
}
if (!jarFilename.startsWith("C:") ){
jarFilename = "/"+jarFilename; // make absolute path on Linux
}
File file = new File(jarFilename);
Long jarSize=null;
Date jarDate=null;
Long resourceSize=null;
Date resourceDate=null;
if (file.exists() && file.isFile()) {
jarSize = file.length();
jarDate = new Date(file.lastModified());
try {
JarFile jarFile = new JarFile(file, false);
ZipEntry entry = jarFile.getEntry(resourceFilename);
resourceSize = entry.getSize();
resourceDate = new Date(entry.getTime());
} catch (Throwable e) {
return ("Unable to open JAR" + jarFilename + " "+resourceUrl +"\n"+e.getMessage());
}
return "\nresource: "+resourceFilename+"\njar: "+jarFilename + " \nJarSize: " +jarSize+" \nJarDate: " +jarDate.toString()+" \nresourceSize: " +resourceSize+" \nresourceDate: " +resourceDate.toString()+"\n";
} else {
return("Unable to load jar:" + jarFilename+ " \nUrl: " +resourceUrl);
}
} catch (Exception e){
return e.getMessage();
}
}
With Linux, I'm using a small script to help me find in which jar a class lies that can be used in a find -exec:
findclass.sh:
unzip -l "$1" 2>/dev/null | grep $2 >/dev/null 2>&1 && echo "$1"
Basically, as jars are zip, unzip -l will print the list of class resources, so you'll have to convert . to /. You could perform the replacement in the script with a tr, but it's not too much trouble to do it yourself when calling the script.
The, the idea is to use find on the root of your classpath to locate all jars, then runs findclass.sh on all found jars to look for a match.
It doesn't handle multi-directories, but if you carefully choose the root you can get it to work.
Now, find which jar contains class org.apache.commons.lang3.RandomUtils to you un-mavenize your project (...):
$ find ~/.m2/repository/ -type f -name '*.jar' -exec findclass.sh {} org/apache/commons/lang3/RandomUtils \;
.m2/repository/org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar
.m2/repository/org/apache/commons/commons-lang3/3.6/commons-lang3-3.6.jar
.m2/repository/org/apache/commons/commons-lang3/3.6/commons-lang3-3.6-sources.jar
$

Categories

Resources