List files from inside a packaged war - java

I have an .ear, a .jar and a .war packages. I am reading my servlet classes dinamically by inspecting the file system and registering the mappings.
The thing is it works for development, I am able to read the directories and the proper file names do be able to create the mappings. The problem is that if I package my ear It does not work:
Using new File( ... ).isDirectory()
to check if I am in a directory, returns always false for a valid directory path.
Using new File( ... ).listFiles()
to be able to list the files from a directory, returns always null for a valid directory path.
I have solved the directory checking issue by detecting an end path that does not end with an extension (for my purpose such verification is enough), but I am still not able to list the files from a given path.
Given this situation I have the question:
How can I list the file names at runtime from a package .war?
The current code:
private void addAllFiles( File dir, ArrayList<ConventionPath> list ) {
for ( File file : dir.listFiles() ) { // dir.listFiles() comes null here =/
String absolutePath = file.getAbsolutePath();
boolean isActionDir = ConventionFiles.isActionDir( absolutePath, fileSeparator );
boolean isActionFile = ConventionFiles.isActionFile( absolutePath );
if ( isActionDir ) {
addAllFiles( file, list );
}
if ( isActionDir || isActionFile ) {
ConventionPath conventionPath =
new ConventionPath( absolutePath, fileSeparator );
list.add( conventionPath );
}
}
}

Now I made it work.
Instead of accessing the file via the file system I used the servlet context (I suppose this is the correct way to go):
URL root = context.getResource( "/WEB-INF/classes/com/package/" );
// /default-host/WEB-INF/classes/
String rootPath = root.getPath();
// /WEB-INF/classes/
rootPath = rootPath.substring( rootPath.indexOf( "/WEB-INF" ), rootPath.length() );
And then recursively I get the information I want from the resources:
Set<String> resourcesPath = context.getResourcePaths( rootPath );

Related

group files after pathnames

i am trying to write a jave code that does the following, but atm have no clue how to realize this:
let us say: i have 7 files in different or equal paths on local system, that i want to copy somewhere else using as few pathnames in my shell command as possible
correctfiles are the files i want, somefiles i do not care about
for instance i do not want :
copy C:\tmp\folder1\subfolder12\correctfile3 && copy C:\tmp\folder1\subfolder12\correctfile4
instead i want the Uberfolder whenever possible:
copy C:\tmp\folder1\subfolder12\
and that demands that there is no somefile in copy C:\tmp\folder1\subfolder12
because i do not want to transfer somefile
e.g.
C:\tmp\folder1: somefile1, somefile2
C:\tmp\folder1\subfolder11: correctfile1, correctfile2
C:\tmp\folder1\subfolder12: correctfile3, correctfile4
C:\tmp\folder2\subfolder21: correctfile5
C:\tmp\folder2\subfolder22: correctfile6, correctfile7
so in this example i could use
copy C:\tmp\folder2
because alle files in that folder are correctfiles
and for the others i would have to
copy C:\tmp\folder1\subfolder11
copy C:\tmp\folder1\subfolder12
because there are somefiles in Uberfolder C:\tmp\folder1 that i do not want to transfer
how could i achieve this?
a java class that sort of groups the files according to pathnames, using as few pathnames as possible
This is actually quite simple. From a List<File> filesToCopy create a
Map<String,Set<String>> dir2names = new HashMap<>();
for( File f: filesToCopy ){
String name = f.getName();
// test name for null and do error handling
String dir = f.getParent();
// dir for null and do error handling
Set<String> names = dir2names.get( dir );
if( names == null ){
names = new HashSet<>();
dir2names.put( dir, names );
}
names.add( name );
}
mapping the directory parts to file names. Iterate the keys of this map
for( String dirname: dir2names.keySet() ){
File[] entries = new File( dirname ).listFiles();
if( entries.length > dir2names.get( dirname ).size() ){
// add list created from dirname + set of names to files to copy
for( String name: dir2names.get( dirname ){
String pathname = new File( dirname, name ).getAbsolutePath();
// add pathname to files to copy
}
} else {
// add directory identified by dirname to files to copy
}
}
I don't think it is worth doing this recursively.

Delete files type in directory java

How can I delete the file in the directory / folder
I am using this code:
private static final String FILE_DIR = "data\\session";
private static final String FILE_TEXT_EXT = ".cache";
private void DeleteCache(String folder, String ext){
GenericExtFilter filter = new GenericExtFilter(ext);
File dir = new File(folder);
File fileDelete;
String[] list = dir.list(filter);
for(String file : list){
String temp = new StringBuffer().append(File.separator).append(file).toString();
fileDelete = new File(temp);
boolean isDelete=fileDelete.delete();
System.out.println("File : "+temp+"is Delete : "+isDelete);
}
if(list.length == 0 ) return;
}
public class GenericExtFilter implements FilenameFilter{
private String ext;
public GenericExtFilter(String ext){
this.ext=ext;
}
public boolean accept (File dir, String name){
return (name.endsWith(ext));
}
}
but why yes if, cache do not want to be removed
example error
File : \31052012-TPBSDERG.cache -is Delete : false
Probably because the file does not exist.
Try using....
File[] list = dir.listFiles(filter);
Instead
UPDATE
There are many reasons why a file may not be deleted. The actual process is depended on the underlying OS, but the most common reasons are, the file is open by another process (or your program), you don't have the correct permissions to delete the file and/or the file doesn't exist.
There are a number of interesting issues with your code...
String temp = new StringBuffer().append(File.separator).append(file).toString();
This is appending a file separator to the file which now says, "look for the file in the root directory of the current drive", which is (probably) not where the file exists.
For example;
File dir = new File(System.getProperty("user.home"));
String[] list = dir.list(filter);
for(String file : list){
String temp = new StringBuffer().append(File.separator).append(file).toString();
System.out.println(temp + " - " + new File(temp).exists());
}
This outputs something like...
/.bash_history - false
/.CFUserTextEncoding - false
/.config - false
/.cups - false
Which is obviously wrong, these files don't live in the root folder
Equally if I do;
File dir = new File(System.getProperty("user.home"));
String[] list = dir.list(filter);
for(String file : list){
System.out.println(file + " - " + new File(file).exists());
}
This outputs something like...
.bash_history - false
.CFUserTextEncoding - false
.config - false
.cups - false
This is equally as useless, as these files don't exist in the current execution location either...
Now, however, if I do something like...
String folder = System.getProperty("user.home");
File[] list = new File(folder).listFiles();
for (File file : list) {
System.out.println(file + " - " + file.exists());
}
I get...
/path/to/home/.bash_history - true
/path/to/home/.CFUserTextEncoding - true
/path/to/home/.config - true
/path/to/home/.cups - true
Which is, obviously, far more useful.
You have to remember, Java is stupid, it doesn't know that when you specify a String value for a name where to look for that file, it makes an assumption based on your current location (unless you specify an absolute path of course)
You are iterating over a list of files in folder, but this is NOT where you attempt to delete the files from.
BTW: is that "31052012-TPBSDERG.cache -" the actual file name???
Use this file to delete (and do not prepend with File.separator, the parent folder is what matters):
fileDelete = new File( dir, file );
and it will work. dir.list(filter) only returns file names without path (e.g. directory name), and if dir is not the current working directory, new File( file ) will not point to the file it was included for, new File( dir, file ) will.

Get file case-sensitive name, with case-insensitive spelling

I am making an application where the user picks a file from:
FilePicker.PickFile(filename)
where filename is a string.
In the method, it will translate into:
File file = new File(filename);
and nothing is wrong with that. Next, I do,
if(file.exists()){
System.out.println(file.getName());
}
else{
System.out.println("Fail.");
}
and this is where the problem begins. I want to get the name of the file, say "HELLO.txt," but if filename is "hello.txt," it still passes the file.exists() check, and file.getName() returns as "hello.txt," not "HELLO.txt". Is there a way, to return file.getName() as the case-sensitive version as "HELLO.txt?" Thanks!
An example:
HELLO.txt is the real file
FilePicker.PickFile("hello.txt");
OUTPUT:
hello.txt
When you are using Windows, which is case preserving (FAT32/NTFS/..), you can use file.getCanonicalFile().getName() to get the canonical name of the selected file.
When you are using Linux or Android and you want to select a file based on a file name that does not necessarily match case, iterate through all files in the file's directory (file.getParent()), and pick the one that .equalsIgnoreCase the filename. Or see Case-insensitive File.equals on case-sensitive file system
/**
* Maps lower case strings to their case insensitive File
*/
private static final Map<String, File> insensitiveFileHandlerCache = new HashMap<String, File>();
/**
* Case insensitive file handler. Cannot return <code>null</code>
*/
public static File newFile(String path) {
if (path == null)
return new File(path);
path = path.toLowerCase();
// First see if it is cached
if (insensitiveFileHandlerCache.containsKey(path)) {
return insensitiveFileHandlerCache.get(path);
} else {
// If it is not cached, cache it (the path is lower case)
File file = new File(path);
insensitiveFileHandlerCache.put(path, file);
// If the file does not exist, look for the real path
if (!file.exists()) {
// get the directory
String parentPath = file.getParent();
if (parentPath == null) {
// No parent directory? -> Just return the file since we can't find the real path
return file;
}
// Find the real path of the parent directory recursively
File dir = Util.newFile(parentPath);
File[] files = dir.listFiles();
if (files == null) {
// If it is not a directory
insensitiveFileHandlerCache.put(path, file);
return file;
}
// Loop through the directory and put everything you find into the cache
for (File otherFile : files) {
// the path of our file will be updated at this point
insensitiveFileHandlerCache.put(otherFile.getPath().toLowerCase(), otherFile);
}
// if you found what was needed, return it
if (insensitiveFileHandlerCache.containsKey(path)) {
return insensitiveFileHandlerCache.get(path);
}
}
// Did not find it? Return the file with the original path
return file;
}
}
Use
File file = newFile(path);
instead of
File file = new File(path);
It's backed by a cache so it shouldn't be too slow. Did a few test runs and it seems to work. It recursively checks the the parent directories to see if they do have the correct letter cases. Then it lists for each directory all files and caches their correct letter casing. In the end it checks if the file with the path has been found and returns the file with the case sensitive path.
Looks like in Java 7 and above on Windows, you can use Path#toRealPath(NOFOLLOW_LINKS) and it would be more correct than getCanonicalFile() in the presence of symlinks.

Java. Files and folders. Can't define the type

Good Day!
I wrote the method in Java which must search files in folders and do some operations with them.
So the problem is that when I try to check what I have (file or dir) I receive nothing in both cases! But as i can see paths look correct.
How can I fix this problem?
Here is the code:
public void searchInDir(){
File inputFile = new File( this.fileName );
String[] namesOfFilesDir = inputFile.list();
for ( int i = 0; i < namesOfFilesDir.length; i++ )
{
String normalPath = this.getNormalPath(inputFile.getCanonicalPath()); //C:\User -> C:\\User
// Two separators for correcting path to file
String pathToCurrentFile = normalPath + File.separator + File.separator + namesOfFilesDir[i];
File f = new File( pathToCurrentFile, namesOfFilesDir[i] );
System.out.printf("FileName=%s, Path=[%s]\n", namesOfFilesDir[i], pathToCurrentFile);
System.out.println(f.isDirectory());//False
System.out.println(f.isFile());//False too
//Some other code
}
}
For example this.fileName consists path to folder ( and this folder consists one folder and 2 files).
I got next:
FileName=Readme.txt, Path=[C:\\workspace\\Grep\\t\\Readme.txt]
false
false
FileName=t2, Path=[C:\\workspace\\Grep\\t\\t2]
false
false
FileName=test.txt, Path=[C:\\workspace\\Grep\\t\\test.txt]
false
false
Ok. Program says that.
Lets print next code as an example.
File f = new File("C:\\workspace\\Grep\\t\\Readme.txt");
System.out.println(f.isFile());
Program will print ”True”.
This part makes no sense:
String pathToCurrentFile = normalPath + File.separator + File.separator + namesOfFilesDir[i];
File f = new File( pathToCurrentFile, namesOfFilesDir[i] );
Even if we forget about the double separator for the time being, it makes no sense to first construct the file name by adding namesOfFilesDir[i], then construct a File() object using the two-argument constructor which basically adds namesOfFilesDir[i] once more. Try printing f.getAbsolutePath() and you'll see what I mean. It should have probably been something like:
File f = new File( normalPath, namesOfFilesDir[i] );
Probably the file doesn't exist, so it is neither a file nor a directory. Try printing the output of f.exists() as well.
Did you notice the duplicate file separator in your path?
I think that perhaps your paths are not correct. Both isFile() and isDirectory() only return true if the file/directory actually exists. Have you tried calling exists() on the file? Also, I'm suspicious of what your getNormalPath() method is doing - I think it might be mangling the filenames.
The 1st System.out.println is missleading!
It would have been better to output the path of f.
Anyway, according the output:
FileName=Readme.txt, Path=[C:\workspace\Grep\t\Readme.txt]
f will be C:\workspace\Grep\t\Readme.txt\Readme.txt
that is, namesOfFilesDir[i] is being appended twice!
It would be easier/better to work just with instances of File directly:
File inputFile = new File(this.fileName);
File[] files = inputFile.listFiles();
for (File f : files) {
System.out.printf("FileName=%s, Parent=[%s]\n", f.getName(), f.getParent());
System.out.println(f.isDirectory());
System.out.println(f.isFile());
//Some other code
}

How do I refer to a directory in Java?

I'm running Windows and I'm trying to refer to a directory. My function starts off like this:
File file = new File("C:\\somedir\\report");
if (!file.exists()) {
file.mkdirs();
}
doStuffWith(file);
I got a NullPointerException within the doStuffWith function, when I tried to call listFiles. Well I looked in C:\somedir and what did I find - there is a file called "report" with no extension, and also a directory called "report"! What seemed to happen was that the file object was referring to the report file rather than the directory. How do I make sure that I am referring to the directory and not the file?
one way to go about is to pass the file object corresponding to "C:\somedir" to the method and inside the method, do a listFiles() and walk through the contents, each time checking for file name and if it is "report", do a isDirectory(). proceed with actual processing when this returns true.
i think there is a isDirectory() method that will tell you if it is a directory
--EDIt
that's what I get for being up so early. I ran your code locally and it works fine for me. Was able to create new files, read directory contents, etc. What else are you trying to do?
I don't understand the problem this works fine for me:
public class MkDir {
static void doStuff(File dir) {
if ( dir.isDirectory() ) {
File[] listFiles = dir.listFiles();
for ( File f : listFiles ) {
System.out.println( f.getName() );
}
}
}
public static void main(String[] args) {
File file = new File( "C:\\dev\\rep2\\rep" );
if ( !file.exists() ) {
file.mkdirs();
}
doStuff( file );
}
}
Check if your file system has had case sensitivity enabled (HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\kernel\ dword:ObCaseInsensitive in the registry.)
If so, you may be getting bitten by a case-related issue. One way to check:
String someName = "./nameNotUsedYet";
boolean first = new File(someName).mkdirs();
boolean second = new File(someName.toUpperCase()).mkdirs();
System.out.println("first = " + first + ", second = " + second);
If both mkdirs() calls succeeded, you know you have a case related complication. If so, ensure that you get the case for "C:\somedir\report" exactly right.

Categories

Resources