Reputation: 559
I created a file checker that checks the file for changes every X sec. The problem is that if I check the file with WatchService it send modify event even if I do touch file
. I can check the file.lenght
, but what if my changes are not change the file size? is there any idea how can I detect the file changes?
This is my code( I'm using lastModified()
method for a while )
class Checker implements Runnable {
static Logger log = Logger.getLogger(Monitor.class.getName());
private static final long DEFAULT_CHECK_INTERVAL = 5000; //5 sec
private static SimpleDateFormat dataFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
private File file;
private long checkInterval;
public Checker(String path, long checkInterval) throws Exception {
this.file = new File(path);
this.checkInterval = checkInterval > 1000 ? checkInterval : DEFAULT_CHECK_INTERVAL;
}
private JSONObject loadConfig() {
JSONObject conf = null;
try(BufferedReader reader = new BufferedReader(new FileReader(this.file));) {
StringBuilder bldr = new StringBuilder((int) this.file.length());
String line = null;
while((line = reader.readLine()) != null) {
bldr.append(line);
}
conf = new JSONObject(bldr.toString());
Thread.sleep(this.checkInterval);
} catch (Exception e) {
log.error(e);
}
return conf;
}
@Override
public void run() {
long modDate = 0;
while (true) {
long lastModified = this.file.lastModified();
JSONObject conf = loadConfig();
if (lastModified != modDate) {
modDate = lastModified;
log.warn("File changed at " + dataFormat.format(lastModified));
log.info(conf.get("name") + ", " + conf.get("company"));
}
log.info("no chenges");
}
}
public class Monitor {
public static void main(String[] args) throws Exception {
new Thread(new Checker("/home/arno/test/config.json", 2000)).start();
}
}
Upvotes: 1
Views: 2494
Reputation: 779
You can check the MD5 checksum instead the file size:
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.MessageDigest;
public class Main {
public static byte[] getMD5Checksum(String filename) throws Exception {
InputStream fis = new FileInputStream(filename);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[1024];
int aux;
do {
aux = fis.read(buffer);
if (aux > 0) {
md.update(buffer, 0, aux);
}
} while (aux != -1);
fis.close();
return md.digest();
}
private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 2);
for (byte b : bytes)
sb.append(String.format("%02x", b & 0xff));
return sb.toString();
}
public static void main(String args[]) throws Exception {
System.out.println(toHexString(getMD5Checksum("/Users/irineuantunes/Desktop/testFile.txt")));
}
}
Upvotes: 0
Reputation: 489
Checksum file using MD5
public class MD5 {
public static String getMD5(String input) {
try {
byte[] thedigest = MessageDigest.getInstance("MD5").digest(input.getBytes("UTF-8"));
BigInteger number = new BigInteger(1, thedigest);
String hashtext = number.toString(16);
// Now we need to zero pad it if you actually want the full 32 chars.
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}
return hashtext;
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static boolean checksum(String filePath, String hashCode) {
try {
return getFileHash(filePath).equals(hashCode);
} catch (Exception ex) {
return false;
}
}
public static String getFileHash(String filePath) {
InputStream fis = null;
try {
fis = new FileInputStream(filePath);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
byte[] b = complete.digest();
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
} catch (IOException | NoSuchAlgorithmException ex) {
Logger.getLogger(MD5.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException ex) {
Logger.getLogger(MD5.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
Upvotes: 0
Reputation:
Maybe java NIO can help
BasicFileAttributes attr = Files.readAttributes(file, BasicFileAttributes.class); System.out.println("lastModifiedTime: " + attr.lastModifiedTime());
Upvotes: 1
Reputation: 5629
Maintain a duplicate of that file in some other directory.
For instance we have the file on the Desktop
, maintain the copy of the file in C:
and check for any difference.
File source = new File(""C://Desktop//filename.txt");
File dest = new File("C://temp//cache-filename.txt");
try {
FileUtils.copyDirectory(source, dest);
} catch (IOException e) {
e.printStackTrace();
}
And then maintain a timer, call your even everytime.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
if(comapreTwoFiles("C://temp//cache-filename.txt", "C://Desktop//filename.txt")){
System.out.println("File is changed");
//change your cache file
}
}
}, 2*60*1000, 2*60*1000);
public boolean compareTwoFiles(String path1, String path2)
throws IOException {
File file1 = new File(path1);
File file2 = new File(path2);
BufferedReader br1 = new BufferedReader(new FileReader(file1));
BufferedReader br2 = new BufferedReader(new FileReader(file2));
String thisLine = null;
String thatLine = null;
List<String> list1 = new ArrayList<String>();
List<String> list2 = new ArrayList<String>();
while ((thisLine = br1.readLine()) != null) {
list1.add(thisLine);
}
while ((thatLine = br2.readLine()) != null) {
list2.add(thatLine);
}
br1.close();
br2.close();
return list1.equals(list2);
}
Upvotes: 0