Lock file/"folder" to a specific JVM and iterate if locked - java

I'm using multiple JVMs, but I need that each JVM to use a specific folder. What I'm trying to do is iterate through folders till it finds a file that is not locked and then lock it to use that specific folder.
Here I'm filtering the folders I want to use:
// Filter 'fran' folders
String dir = System.getProperty("user.dir");
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
String lowercaseName = name.toLowerCase();
if (lowercaseName.startsWith("fran")) {
return true;
} else {
return false;
}
}
};
File[] dirs = new File(dir).listFiles(filter);
Then I'm trying to go through the folders and check if it is locked or not with f.canWrite(). However it always appears to use only one folder and ignore the others.
// Find available folder
boolean lock = true;
String lock_folder = "";
FileChannel fileChannel = null;
FileLock lockfile = null;
File f = null;
while (lock) {
for (File folder : dirs) {
f = new File(folder + "\\lock.txt");
Boolean isnotlocked = f.canWrite();
if (isnotlocked) {
fileChannel = new RandomAccessFile(f, "rw").getChannel();
lockfile = fileChannel.lock();
lock = false;
lock_folder = folder.getAbsolutePath();
break;
}
}
}
I+ve previously tried to accomplish what I needed without FileLock, creating a file in the specific folder and then deleting after completed. If the folder did not have that file it would create and lock that JVM. However I think the JVMs were getting mixed cause the results were bad.
Hope u can understand what my problem is, would really appreciate some help.

Here are some ideas:
Assuming a process class - CustomProcess.java. This runs in a separate thread. The class has a constructor which takes a file folder as an argument. Lets assume the filePath1 is the folder's path and is accepted from a FileChooser.
(a) How the application works:
Put the selected folder filePath1 in a collection like List<File> or List<Path> - lets call it processFilesList; this is shared (perhaps a static member) by all the processes (this needs to be a concurrent collection from java.util.concurrent package). This list tracks the folders which are already being processed. Before the process starts check if the filePath1 is already in the processFilesList.
(b) Create and start the process:
CustomProcess p1 = new CustomProcess(filePath1);
p1.startProcess(); // here the application does whatever with the files in the folder.
Option 2:
Put all the folder file paths that need to be processed in a Queue collection. Process each folder (and its files as needed) one at a time or by multiple processes. The queue can be a first-in-first-out (FIFO) or a last-in-first-out (LIFO). One can consider these concurrent queue implementations based on the requirement: ConcurrentLinkedQueue, LinkedBlockingQueue, ConcurrentLinkedDeque or LinkedBlockingDeque.

Related

Java - wait for a file to download with partial filename

I'm trying to wait for a file to get downloaded using fluent wait. But since the file downloads with different date format. I want to validate with "Partial filename" of the file using fluentWait. For Eg: cancelled_07092019, cancelled_09_07_2019. So here the filename 'canceled_' remains constant
Below code works fine for the actual filename.
Downloaded_report= new File("DownloadPath");
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
wait.pollingEvery(1, TimeUnit.SECONDS);
wait.withTimeout(15, TimeUnit.SECONDS);
wait.until(x -> downloaded_report.exists());
Here, I want to check the startof the file name. How do I do this?
Thanks in Advance
I am not sure if I understood the question correctly but you can check if the file with the partial name exists in the given directory.
File dir = new File("DownloadPath");
String partialName = downloaded_report.split("_")[0].concat("_"); //get cancelled and add underscore
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
wait.pollingEvery(1, TimeUnit.SECONDS);
wait.withTimeout(15, TimeUnit.SECONDS);
wait.until(x -> {
File[] filesInDir = dir.listFiles();
for (File fileInDir : filesInDir) {
if (fileInDir.getName().startsWith(partialName)) {
return true;
}
}
return false;
});
In the above code, we list all files in the download path directory. Then, iterate over each file, get its name and check if it contains the partial name that we want.
It might be a problem if you have multiple reports in the directory. Then I would advise clearing DownloadPath from files that start with cancelled_ in some kind of #Before hook.

Java WatchService misses events, files

I want to monitor a folder for newly created subfolders for specific .csv files using Java WatchService API (Windows 7 x64, Java 8). I expect the final application like this: folders\files will be created somewhere else and loaded into a cloud (e.g. GDrive). From there I will synchronize them with a local folder (using stock software). This local folder I want to monitor and process files within minutes after they appear. Also very important is not to miss any new files.
I use WatchService as in many tutorials and questions here, but still it behaves strangely.
When the folder (already with files) is created it is both CREATED and MODIFIED - thus two events for a folder. I can live with it, but it sometimes misses files in it completely. (I suppose, files are copied so fast, that they are there even before this new folder is registered and monitored).
When I copy several folders with files at once (F1,F2,F3) then it:
registers F1, detects modified files in F1, processes them, registers F2, registers F3.
Again, the files in the last two folders are not detected anyhow.
Here is a simplified code that I use. I am looking for a cause of this issues and how to make it more robust.
I can cut and paste all files from every new folder and hope then it will detect them, but this is the worst case solution.
More general question - what happens between ws.take() and ws.pollEvents() and ws.reset()? Are there blind-moments, when events are not registered?
public static void main(String args[]) {
// SET UP LOGGER AND CONFIG VARIABLES HERE
// CREATE AN OBJECT AND DEFINE AN ABSTRACT startListening()
WatchServiceClass wsc = new WatchServiceClass() {
public void startListening(WatchService watchService) {
while (true) {
WatchKey queuedKey = watchService.take();
// DOESNT HELP: Thread.sleep(1000);
List<WatchEvent<?>> events = queuedKey.pollEvents();
for (WatchEvent<?> watchEvent : events) {
if (watchEvent.kind() == StandardWatchEventKinds.OVERFLOW) {
continue;
}
String action // create, modify or delete
String fileName // self explanatory
String fullPath
String fullPathParent
if (action.equals("create")) { // TRACK NEW FOLDERS
registerDir(Paths.get(fullPath), watchService);
}
if (new File(fullPath).isDirectory()) {
continue; // NOT DOING ANYTHING WITH DIRECTORIES
}
// IF HERE, THEN THIS IS THE FILE, DO SOMETHING
// TAKES SEVERAL MINUTES
}
if (!queuedKey.reset()) {
keyPathMap.remove(queuedKey);
}
if (keyPathMap.isEmpty()) {
break;
}
}
}
};
// END OF startListening() METHOD DEFINITION
while (true) { // MAIN INFINITE LOOP
try (WatchService watchService = FileSystems.getDefault().newWatchService()) {
wsc.registerDir(Paths.get(DATA_DIR), watchService);
wsc.startListening(watchService);
} catch (Exception e) {
e.printStackTrace();
}
}
}

Set last modified timestamp of a file using jimfs in Java

How can I set a last modified date of a file using jimfs?
I have smth. like this:
final FileSystem fileSystem = Jimfs.newFileSystem(Configuration.unix());
Path rootPath = Files.createDirectories(fileSystem.getPath("root/path/to/directory"));
Path filePath = rootPath.resolve("test1.pdf");
Path anotherFilePath = rootPath.resolve("test2.pdf");
After creating the stuff I then create a directory iterator like:
try (final DirectoryStream<Path> dirStream = Files.newDirectoryStream(rootPath, "*.pdf")) {
final Iterator<Path> pathIterator = dirStream.iterator();
}
After that I iterate over the files and read the last modified file, which I then return:
Path resolveLastModified(Iterator<Path> dirStreamIterator){
long lastModified = Long.MIN_VALUE;
File lastModifiedFile = null;
while (dirStreamIterator.hasNext()) {
File file = new File(dirStreamIterator.next().toString());
final long actualLastModified = file.lastModified();
if (actualLastModified > lastModified) {
lastModifiedFile = file;
lastModified = actualLastModified;
}
}
return lastModifiedFile.toPath();
}
The problem is that both files "test1.pdf" and "test2.pdf" have lastModified being "0" so I actually can't really test the behavior as the method would always return the first file in the directory. I tried doing:
File file = new File(filePath.toString());
file.setLastModified(1);
but the method returns false.
UDPATE
I just saw that File#getLastModified() uses the default file system. This means that the default local file system will be used to read the time stamp. And this means I am not able to create a temp file using Jimfs, read the last modified and then assert the paths of those files. The one will have jimfs:// as uri scheme and the another will have OS dependent scheme.
Jimfs uses the Java 7 file API. It doesn't really mix with the old File API, as File objects are always tied to the default file system. So don't use File.
If you have a Path, you should use the java.nio.file.Files class for most operations on it. In this case, you just need to use
Files.setLastModifiedTime(path, FileTime.fromMillis(millis));
i am newbie in this but here is my point of view if you choose 1 specific FOLDER and you want to extract the last file from it.
public static void main(String args[]) {
//choose a FOLDER
File folderX = new File("/home/andy/Downloads");
//extract all de files from that FOLDER
File[] all_files_from_folderX = folderX.listFiles();
System.out.println("all_files_from_folderXDirectories = " +
Arrays.toString(all_files_from_folderX));
//we gonna need a new file
File a_simple_new_file = new File("");
// set to 0L (1JAN1970)
a_simple_new_file.setLastModified(0L);
//check 1 by 1 if is bigger or no
for (File temp : all_files_from_folderX) {
if (temp.lastModified() > a_simple_new_file.lastModified()) {
a_simple_new_file = temp;
}
//at the end the newest will be printed
System.out.println("a_simple_new_file = "+a_simple_new_file.getPath());
}
}}

What is the right way to check if a file is in a directory?

I am not asking how to check if a file exists or how to check if a file is in a specific directory level. Rather I want to know how to check if an existing file is anywhere underneath a specified directory.
Obviously if a file is a direct child of a directory that is easy to check. But what I want to be able to do is efficiently check if an existing file is in a directory including any possible subdirectory. I'm using this in an Android project where I am keeping fine grain control over my cache and I want a utility method to check if a file I may be manipulating is in my cache folder.
Example:
cache dir
/ \
dir file1
/ \
file2 file3
isCacheFile(file2) should return true
Currently I have a method that does it like so
private static final File cacheDir = AssetManager.getInstance().getCacheDir(); // Not android.content.res.AssetManager
private static final String cacheDirName = cacheDir.getAbsolutePath();
public static boolean isCacheFile(File f) {
if (!f.exists()) return false;
return f.getAbsolutePath().startsWith(cacheDirName);
}
However, I am inclined to believe there is a better way to do this. Does anyone have any suggestions?
If you have a known path (in the form of File f), and you want to know if it is inside a particular folder (in the form of File cacheDir), you could simply traverse the chain of parent folders of your file and see if you meet the one you are looking for.
Like this:
public static boolean isCacheFile(File f) {
while (f.getParentDir()!=null) {
f = f.getParentDir();
if (f.equals(cacheDir)) {
return true;
}
}
return false;
}
boolean isContains(File directory){
File[] contents = directory.listFiles();
if (contents != null) {
for(int i = 0; i < contents.length; i++){
if(contents[i].isDirectory())
isContains(contents[i]);
else if(contents[i].getName().equals(*your_file_name*))
return true;
}
}
return false;
}
You could do it by recursion, by calling if the file exists in each sub-directory.
first check if the file exists in the root directory.
boolean exist = new File(rootDirectory, temp).exists();
then if the file wasn't in the root directory, then list all the files and call the method again in the sub-directoy files recursionally until you find the file or there are no more sub-directories.
public String getPathFromFileName(String dirToStart,Sring fileName){
File f = new File(dirToStart);
File[] list = f.listFiles();
String s="null";
for(int i=0;i<list.length;i++){
if(list[i].isFile()){
//is a file
if(fileName.equals(list[i])){
s=dirToStart+"/"+fileName;
break;
}
}else{
//is a directory search further.
getPathFromFileName(dirToStart+list[i]);
}
}
return s;
}
call this method by passing the parent directory name and the file name to search in subdirectories.
you check the return value if it is not equal to "null", then the files path is returned.

Locate a specific file in a directory by name plus saving a file to the local folder

I would like to locate a file named SAVE.properties. I have looked at different questions that seem like they would answer me, but I can't see that they do.
For example, I would like to check to see whether or not SAVE.properties exists within a directory (and its subfolders).
I would also like to know how I could save a .properties file (and then read it afterwards from this location) to the directory where my program is being run from. If it is run from the desktop, it should save the .properties file there.
Saving properties can easily be achieved through the use of Properties#store(OutputStream, String), this allows you to define where the contents is saved to through the use of an OutputStream.
So you could use...
Properties properties = ...;
//...
try (FileOutputStream os = new FileOutputStream(new File("SAVE.properties"))) {
properties.store(os, "Save");
} catch (IOException exp) {
exp.printStackTrace();
}
You can also use Properties#load(InputStream) to read the contents of a "properties" file.
Take a closer look at Basic I/O for more details.
Locating a File is as simple as using
File file = new File("SAVE.properties");
if (file.exists) {...
This checks the current working directory for the existence of the specified file.
Searching the sub directories is little more involved and will require you to use some recursion, for example...
public File find(File path) {
File save = new File(path, "SAVE.properties");
if (!save.exists()) {
save = null;
File[] dirs = path.listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
});
for (File dir : dirs) {
save = find(dir);
if (save != null) {
break;
}
}
}
return save;
}
Using find(new File(".")) will start searching from the current working directory. Just beware, under the right circumstances, this could search your entire hard disk.

Categories