I am currently implementing my own version of WatchService API in Java.
(You can refer to this example to understand what file WatchService does.)
I have implemented code for the following cases :
Whenever a file has been created inside the directory or its sub-directory.
Whenever a file has been deleted from the directory or its sub-directory.
Whenever a file has been modified inside the directory or its sub-directory. (based on the comparison of the last-modified date of files)
I am facing a problem, whenever a file has been renamed, I don't understand how to track it.
This link contains the gist of my code at high level: click here
Whenever a file has been renamed, I get 2 results
FILE DELETED : {old filename}
FILE ADDED : {new filename}
But what I want the actual result to be is :
FILE RENAMED: FROM {old filename} TO {new filename}
How do I tackle this challenge ?
I have provided a psuedo-code (which I think is enough to understand the problem at hand), If required I can provide the whole code too :)
You can store hash for each file.
When you detect that some files are deleted and some added compare hashes and if they match you found renamed/moved file.
Whenever a file is renamed, watcher service generate delete + create events. You should some how merge these two events as rename event.
You can create a unique id and assign it to the file. Refer this link. Whenever you see a create event on a file and it has already some id, that mean it is renamed, else it is new creation. For newly created files, you should set the random unique id to keep track rename events.
JNotify supports JNotify.FILE_RENAMED event. As far as I understand this is a wrapper over native inotify API and it can catch file renaming at system level (changing name without changing file descriptor).
Related
I am using talend to pickup file from source folder and transfer to the destination folder,however i want to pickup the file for processing only if the file is completely written in the source or not during/when the file is actively being copied into the source folder.
I realize that in talend when trying to move the file from source to dest. when the file is being still written into source folder-it shows an error message that "file is still being used by another proces" however i dont want that error to be triggered for each every run,i would want to skip and move to the next file in the iteration folder.
Can i use a twait or twaitforfile between components or add java code to handle it such that
"presenttime(sysdate)-filetime(arrivaltimeinto the folder)>timedifference(lets say around 3-5 minutes)"
Only if the condition is satisfied move the file to destination folder.
Please suggest which is the best efficient way to handle this.
In advanced settings of tWaitForFile, you have an option "WAIT_RELEASE" : you can set it, and when a file is detected, it will perform a 2d check XXXms after the first one, to make sure that the file is released (so that it is not actively being copied to the repository). When the file is fully copied, you are then able to use it.
I want to compare or get delta of two files that means if a file or directory has just been renamed or moved or changed into another folder will handle these operations like a deletion and subsequent file (re)creation, resulting in re-transmitting the entire file or even directory to the mirror location at the new location or with the new name or a file that made changes then how can i get that changes not the whole file.
How can i achieve this in java or android.
It sounds like you need something like rsync. There is a Java implementation
http://sourceforge.net/projects/jazsync/ so you might want to look into that. I'm not sure how stable it is or how well it works with Android.
I want to sync a folder like Dropbox. If in my Folder is changed a file or a folder, I want to get an Event, which starts my synchronisation Class. How can I get such an Event without scanning this folder by an Intervall?
You have at least two options. You can either reinvent the wheel as Arpit suggested or you can also use the WatchService API.
You can find a WatchService tutorial here.
Some start for you:
get the list of all files : yourdir.listFiles()
now for each file in filelist:
file.getLastModified()
if it is equal to current time or differ from lastSynctime(you need to maintain it in your sync class) then sync it.
I'm using a method to generate XML files dynamically for a research project, they get put into a loader that reads from a file path, I don't have any control over how the loader handles things (otherwise I'd pass the internal XML representation instead of monkeying with temp files), I'm using this code to save the file:
File outputs = File.createTempFile("lvlFile", ".tmp.xml");
FileWriter fw = new FileWriter(outputs);
fw.write(el.asXML());
fw.close();
// filenames is my list of file paths which gets returned and passed around
filenames.add(outputs.getAbsolutePath());
Now, I'm sure that the file in question is written to directly. If I print outputs.getAbsolutePath() and navigate there via terminal to check the files, everything is generated and written properly, so everything is correct on the filesystem. However, this code:
URL url = this.getClass().getClassLoader().getResource(_levelFile);
Where _levelFile is one of my filenames generated above, causes url to be null. The path isn't getting corrupted or anything, printing verifies that _levelFile points to the correct path. The same code has succeeded for other files. Further, the bug doesn't seem related to whether or not I use getPath(), getCanonicalPath(), or getAbsolutePath(), further setting outputs.isReadable(true) doesn't do anything.
Any ideas? Please don't offer alternatives to the Url url = structure, I don't have any control over this code*, I'm obligated to change my code so that the url is set correctly.
(*) At least without SIGNIFICANT effort rewriting a large section of the framework I'm working with, even though the current code succeeds in all other cases.
Edit:
Again, I can't use an alternative to the URL code, it's part of a loader that I can't touch. Also, the loading fails even if I set the path of the temp file to the same directory that my successfully loaded files come from.
I assume that the ClassLoader will only look for resources within the class path - which probably doesn't include /tmp. I'm not sure if it actually supports absolute path names. It might just interpret them as relative to the root of the individual class path.
How about using _levelFile.toURI().toURL() instead?
Your are creating file in file system and then trying to read it as a resource. Resource is where JVM takes its classes, i.e. the classpath. So this operation will work only if your are writing file into your classpath.
And even if this is correct be careful: if for example you are running from eclipse your process will not probably "see" the new resource until you refresh your workspace.
Now my question is: Are your really sure that you want to read files as resources. It seems that your just should create new FileInputStream(_levelFile) and read from it.
Edit
#Anonymouse is right. You are creating temporary file using 2-arg version of createTempFile(), so your file is created in your temporary directory. The chance that it is into your classpath is very low... :)
So, if you want to read it then you have to get its path or just use it when creating your input stream:
File outputs = File.createTempFile("lvlFile", ".tmp.xml");
..........................
InputStream in = new FileInputStream(ouptuts);
// now read from this stream.
I am developing a Java Desktop Application. This app needs a configuration to be started. For this, I want to supply a defaultConfig.properties or defaultConfig.xml file with the application so that If user doesn't select any configuration, then the application will start with the help of defaultConfig file.
But I am afraid of my application crash if the user accidentally edit the defaultConfig file. So Is there any mechanism through which I can check before the start of the application that whether the config file has changed or not.
How other applications (out in the market) deal with this type of situation in which their application depends on a configuration file?
If the user edited the config file accidentally or intentionally, then the application won't run in future unless he re-installs the application.
I agree with David in that using a MD5 hash is a good and simple way to accomplish what you want.
Basically you would use the MD5 hashing code provided by the JDK (or somewhere else) to generate a hash-code based on the default data in Config.xml, and save that hash-code to a file (or hardcode it into the function that does the checking). Then each time your application starts load the hash-code that you saved to the file, and then load the Config.xml file and again generate a hash-code from it, compare the saved hash-code to the one generated from the loaded config file, if they are the same then the data has not changed, if they are different, then the data has been modified.
However as others are suggesting if the file should not be editable by the user then you should consider storing the configuration in a manner that the user can not easily edit. The easiest thing I can think of would be to wrap the Output Stream that you are using to write the Config.xml file in a GZIP Output Stream. Not only will this make it difficult for the user to edit the configuration file, but it will also cause the Config.xml file to take up less space.
I am not at all sure that this is a good approach but if you want to go ahead with this you can compute a hash of the configuration file (say md5) and recompute and compare every time the app starts.
Come to think of it, if the user is forbidden to edit a file why expose it? Stick it in a jar file for example, far away from the user's eyes.
If the default configuration is not supposed to be edited, perhaps you don't really want to store it in a file in the first place? Could you not store the default values of the configuration in the code directly?
Remove write permissions for the file. This way the user gets a warning before trying to change the file.
Add a hash or checksum and verify this before loading file
For added security, you can replace the simple hash with a cryptographic signature.
From I have found online so far there seems to be different approaches code wise. none appear to be a 100 hundred percent fix, ex:
The DirectoryWatcher implements
AbstractResourceWatcher to monitor a
specified directory.
Code found here twit88.com develop-a-java-file-watcher
one problem encountered was If I copy
a large file from a remote network
source to the local directory being
monitored, that file will still show
up in the directory listing, but
before the network copy has completed.
If I try to do almost anything non
trivial to the file at that moment
like move it to another directory or
open it for writing, an exception will
be thrown because really the file is
not yet completely there and the OS
still has a write lock on it.
found on the same site, further below.
How the program works It accepts a ResourceListener class, which is FileListener. If a change is detected in the program a onAdd, onChange, or onDelete event will be thrown and passing the file to.
will keep searching for more solutions.