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)) {...
Related
I have a plugin. Within this plugin I have a view that creates some markers so that I can open the file and navigate automatically to a selected line. However where as this method has worked for me previously. it ceases to now? it only ever returns null as my IFile.
Here is my method of creating the markers NOTE: That this method is not located within the controlling class of the FXML file. it is located in another external file.
public static String openAbsoluteFileInEclipseEditor(String absoluteLocationP, int lineNumberP) {
File absolute = new File(absoluteLocationP);
if(absolute.isFile() && absolute.exists()) {
if(Globals.testing) {
try {
Desktop.getDesktop().open(absolute);
return null;
} catch (IOException e) {
ErrorHandling.reportErrors(e);
return "";
}
}else {
IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
IWorkbenchPage page = window.getActivePage();
IWorkspace workspace = ResourcesPlugin.getWorkspace();
try {
if(lineNumberP != 0) {
IPath location = Path.fromOSString(absolute.getAbsolutePath());
System.out.println("location " + location);
IFile iFile = workspace.getRoot().getFileForLocation(location);
System.out.println("iFile " + iFile);
IMarker marker = iFile.createMarker(IMarker.TEXT);
marker.setAttribute(IMarker.LINE_NUMBER, lineNumberP);
IDE.openEditor(page, marker);
marker.delete();
}else {
IFileStore fileStore = EFS.getLocalFileSystem().getStore(absolute.toURI());
IDE.openEditorOnFileStore( page, fileStore );
}
return null;
} catch (PartInitException e) {
ErrorHandling.reportErrors(e);
return "";
} catch (CoreException e) {
ErrorHandling.reportErrors(e);
return "";
}
}
}else {
return "File not found";
}
}
Here are the two prints values that you can see in the middle of the method.
location C:/SoftwareAG_Workspaces/workspace105/HOSPITAL/Natural-Libraries/HOSPITAL/Programs/XX021P01.NSP
iFile null
Can anyone point out to me why it might no longer work and why its only returning nulls? and if possible could you suggest an alternate method that will work? the file does exist within in that location I have made sure of that.
Thanks in advance.
The Javadoc for getFileForLocation says:
This method returns null when the given file system location is not
under the location of any existing project in the workspace.
So is that location in the current workspace, and in a valid project?
The Javadoc also says:
The result will also omit resources that are explicitly excluded from
the workspace according to existing resource filters.
So check any resource filters.
Finally the Javadoc says:
Warning: This method ignores linked resources and their children.
Since linked resources may overlap other resources, a unique mapping
from a file system location to a single resource is not guaranteed.
To find all resources for a given location, including linked
resources, use the method findFilesForLocation.
So check for linked resources
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.
My problem is, I need to delete all the files i.e. first, second, third. But as per below code only third file is getting deleted from path, not first and second. How to remove all files?
ArrayList<File> filesToAdd = new ArrayList<File>();
filesToAdd.add(first);
filesToAdd.add(second);
filesToAdd.add(third);
for (File file : filesToAdd) {
if(file!=null && file.isFile()){
file.delete();
}
}
when I run the app with debugger, if returns true for all files.
And I can't pass file.delete(path) because path is String.
The code you have try to delete files. There are few reasons why File.delete()
you don't have correct permissions to delete
the file the file represents a directory and the directory is not empty
the file is locked by another process, (or even by the same process in say an unclosed FileOutputStream)
the file doesn't exist
The method delete() return a boolean value that inform you about the state.
for (File file : filesToAdd) {
if(file!=null && file.isFile()){
if(file.delete() == false) {
//Add code what should happen
}
}
}
Note that your code is obsolete and use API from Java 6.
If it is possible switch to latest version 8, then you can
List<Path> paths = new ArrayList<>();
paths.add(first);
paths.add(second);
paths.add(third);
for (Path path : paths) {
if(Files.isRegularFile(path)) {
Files.delete(path);
}
}
The change is that Files.delete(path) will throw an exception that will tell you why you can not delete it.
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.
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).