I'm working on an application that will read in SystemOut.Log files and process them. Sometimes archived files may be named slightly differently, such as SystemOut_10:20_09/07/2021-10:45_09/07/2021.Log. It's always of the form SystemOut(Some more text here).Log.
I had a little read up and stumbled across wildcards and came to the conclusion that if I were to pass SystemOut*.Log into my application as the filename it would work. But I was wrong.
I originally get my filename through a properties file like so.
fileName=prop.getProperty("fileName");
I then just tried to concatenate *.Log on the end.
fileName=fileName+"*.Log";
When I print out fileName it is "SystemOut*.Log" but when I pass in this filename to my method that reads files it doesn't work as no file is found with that name.
Am I making an error in the code or have I just misunderstood how wildcards work? Thanks
Try FileUtils from Apache commons-io (listFiles and iterateFiles methods):
The code you need is
File dir = new File(".");
FileFilter fileFilter = new WildcardFileFilter("*.Log");
File[] files = dir.listFiles(fileFilter);
for (int i = 0; i < files.length; i++) {
System.out.println(files[i]);
}
I use this piece of code to find XML files that another part of my program creates in a given directory:
String fileName;
File folder = new File(mainController.XML_FILES_LOCATION);
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
fileName = listOfFiles[i].getName();
if (fileName.endsWith(".xml")) {
Document readFile = readFoundXmlFile(fileName);
if (readFile != null) {
boolean postWasSuccesful = mainController.sendXmlFile(readFile, fileName);
reproduceXmlFile(readFile, fileName, postWasSuccesful);
deleteXmlFile(fileName);
}
}
}
}
What it does is that it reads every XML file that gets placed in the given directory, it sends it to an URL and it copies it to a subdirectory (either 'sent' or 'failed' based on the boolean postWasSuccedful) and deletes the original so it won't be sent again.
In Windows this works as expected, but I've transferred the working code to a Linux machine and all of a sudden it get's in this loop of sending bla.xml and a second later sent\bla.xml and again a second later sent\sent\bla.xml followed by sent\sent\sent\bla.xml, etc.
Why is Linux deciding for itself that listFiles() is recursive?? And, better, how to prevent that? I can add an extra check in the if-statement looking for files ending with .xml that there isn't a directory-char allowed in the fileName, but that's a workaround I don't want as the amount of files in the pick-up directory will never be high whereas the amount of files in the sent subdirectory can get quite high after a while and I wouldn't want this piece of code to become slow
My psychic powers tell me that reproduceXmlFile() builds the target pathname using a hard-coded backslash ("\"), and therefore you're actually creating files with backslashes in their names.
You need to use File.separator rather than that hard-coded "\". Or use something like new File("sent", fileName).toString() to generate your output pathnames.
(Apologies if I'm wrong!)
I have looked through the documentation and I can't seem to find a function which does this. So, I assume that I should code it myself. Looking further into the documentation, I found a list() function which lists all the files in a working directory. How would I download all the files while preserving the directory structure?
After you connect to the server:
FTPClient client = new FTPClient();
client.connect(host);
client.login(user, pass);
You change to the desired folder
client.changeDirectory(ftpFolder);
and then you request the list of files:
FTPFile[] list = client.list();
Iterate the file array of results and download the file.
using:
FTPFile[] list = client.list();
for (int i = 0; i < list.length; i++)
{
//client.download("localFile", new java.io.File("remotefile);
client.download(list[i].getName(), new java.io.File(list[i].getName());
}
My application has an assets directory in which I've dumped a bunch of text files I need to load at runtime.
I have a directory full of assets of a particular type (i.e., "assets/subdir") and I want to load all of the files in this directory, one at a time.
I have code like this:
AssetManager assetMgr = getAssets();
String[] assetsIWant = assetMgr.list("subdir");
for(String asset: assetsIWant) {
doAssetyThing(asset);
}
I've tried a zillion different versions of the parameter to assetMgr.list() and am not getting anywhere.
If I use "/", I get back a list containing the "assets" directory, and a few random other items (META_INF, for example). If I pass any other string (like "assets" or "assets/" or "/assets" or "/assets/" or "mysubdir" or "/mysubdir" or "assets/mysubdir" or ...) then I get back an empty array.
The documentation is unfortunately fairly incoherent.
Does anybody know what the correct formula for that list() parameter is?
Passing an empty string seems to work for me. I get a list of the files in my assets directory when I do the following:
AssetManager aMan = appContext.getAssets();
String[] filelist = aMan.list("");
I ve use the following code to list the file name in assets/myFolder/:
String[] fileNames =getAssets().list("myFolder");
for(String name:fileNames){
System.out.println(name);
}
note that the parameter in the method list does not contains "/".
When you need to have access to a folder down deeper in your hierarchy use
String[] fileNames =getAssets().list("myFolder"+File.separator+"mysubfolder");
instead of "/" inside the String, which would give you an empty String array as result.
I'm not sure why it works this way, but when I list "/", I get root level stuff, not things from my "assets" directory. I actually found no way to properly list my assets folder in the short time I spent trying.
The workaround I'm using is to create a "subdir" directory inside of my "assets" directory. I put all the assets that I want to access in this "subdir", and do:
String[] assetsIWant = assetMgr.list("subdir");
I don't know why "/" lists the "assets" directory itself as one of it's files, yet you don't have to specify the "assets" directory when giving list a path. Maybe someone else knows, but I hope this tip will help you out anyway.
There are a lot of similar questions around this topic, I suspect you are using the assets folder in a library project. if you try to access assets in a library project on android you will get empty contents and the exact symptoms you have described here
from the android "projects" documentation
source : http://developer.android.com/tools/projects/index.html
Library projects cannot include raw assets
The tools do not support the use of raw asset files (saved in the assets/ directory) in
a library project. Any asset resources used by an application must be
stored in the assets/ directory of the application project itself.
However, resource files saved in the res/ directory are supported.
if this is the case, the answer is that you should only include Raw assets in the assets folder of your application project NOT in any project marked as a library (you can check this by right clicking your project and selecting properties, select the android entry on the left and look at the is library checkbox)
Let's say you have this folder set up: Assets->SubDir1. You have things in Subdir1 like A.txt, B.txt, C.txt. So from the Project's directory, it would be Assets/SubDir1/A.txt.
Taking that into account, the way to access that file is similar to what you're doing, adding one thing. That one thing is in your doAssetyThing function. You have to put the SubDir1 directory in front of it, even if you did a filter of "SubDir1" in the .list("");
Example:
AssetManager am = getResources().getAssets();
String [] list = am.list("SubDir1");
for (String s:list) {
doAssetyThing("SubDir1/" + s);
//I use this next line as the start of copying a pdf from one location
//to another. I wanted to give you a real function in use.
InputStream inStream = am.open("SubDir1/" + s);
//more code
}
I hope this is clear and helps you out!
I use the following two methods to ensure given asset is present:
protected boolean hasAsset(String id) {
return hasAsset(id,"");
}
protected boolean hasAsset(String id, String dir) {
int idx = id.indexOf('/');
if (idx > 0 && idx < id.length() - 1) {
if (dir.length() > 0) {
dir = dir + "/" + id.substring(0,idx);
} else
dir = id.substring(0,idx);
return hasAsset(id.substring(idx + 1), dir);
}
try {
return Arrays.asList(context.getAssets().list(dir)).contains(id);
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
For some reason, empty directories are not listed.
At least, in my experience, they are not listed.
That is, if you have some-dir/d1/f1 and some-dir/d2 in the assets area, and you list("some-dir"), d2 is not listed.
This solution seems working for me:
Keep a copy of each file you want to access from a sub directory in the assets directory too.
Use same convention. i.e. list("subdirectory")
It doesn't read the files in assets folder, but reads all "copied" files in its sub directory.
Weird!! But works!
What is the best way to upload a directory in grails ?
I try this code :
def upload = {
if(request.method == 'POST') {
Iterator itr = request.getFileNames();
while(itr.hasNext()) {
MultipartFile file = request.getFile(itr.next());
File destination = new File(file.getOriginalFilename())
if (!file.isEmpty()) {
file.transferTo(destination)
// success
}
else
{
// failure
}
}
response.sendError(200,'Done');
}
}
Unfortunately, I can only upload file by file.
I would like to define my directory, and upload all files directly.
Any ideas ?
There is one major misconception here. The code which you posted will only work if both the server and the client runs at physically the same machine (which won't occur in real world) and if you're using the MSIE browser which has the misbehaviour to send the full path along the filename.
You should in fact get the contents of the uploaded file as an InputStream and write it to any OutputStream the usual Java IO way. The filename can be used to create a file with the same name at the server side, but you'll ensure that you strip the incorrectly by MSIE sent path from the filename.
As to your actual functional requirement, HTML doesn't provide facilities to upload complete directories or multiple files by a single <input type="file"> element. You'll need to create a client application which is capable of this and serve this from your webpage, like a Java Applet using Swing JFileChooser. There exist 3rd party solutions for this, like JumpLoader.