ฉันต้องการรับการแจ้งเตือนเมื่อไฟล์มีการเปลี่ยนแปลงในระบบไฟล์ ฉันไม่พบอะไรเลยนอกจากเธรดที่สำรวจคุณสมบัติ lastModified File และเห็นได้ชัดว่าโซลูชันนี้ไม่เหมาะสม
ฉันต้องการรับการแจ้งเตือนเมื่อไฟล์มีการเปลี่ยนแปลงในระบบไฟล์ ฉันไม่พบอะไรเลยนอกจากเธรดที่สำรวจคุณสมบัติ lastModified File และเห็นได้ชัดว่าโซลูชันนี้ไม่เหมาะสม
คำตอบ:
ในระดับต่ำวิธีเดียวในการสร้างโมเดลยูทิลิตี้นี้คือการมีเธรดการโพลในไดเร็กทอรีและคอยเฝ้าดูคุณลักษณะของไฟล์ แต่คุณสามารถใช้รูปแบบเพื่อพัฒนาอะแดปเตอร์สำหรับยูทิลิตี้ดังกล่าวได้
ตัวอย่างเช่นแอปพลิเคชันเซิร์ฟเวอร์ j2ee เช่น Tomcat และอื่น ๆ มีคุณสมบัติการโหลดอัตโนมัติโดยที่ในทันทีที่ตัวบอกการปรับใช้เปลี่ยนแปลงหรือคลาส servlet เปลี่ยนแอปพลิเคชันจะรีสตาร์ท
คุณสามารถใช้ไลบรารีจากเซิร์ฟเวอร์ดังกล่าวได้เนื่องจากโค้ดส่วนใหญ่ของ tomcat สามารถใช้ซ้ำได้และโอเพนซอร์ส
ฉันเคยเขียนการตรวจสอบไฟล์บันทึกมาก่อนและพบว่าผลกระทบต่อประสิทธิภาพของระบบในการสำรวจคุณลักษณะของไฟล์เดียวสองสามครั้งต่อวินาทีนั้นน้อยมาก
Java 7 ซึ่งเป็นส่วนหนึ่งของ NIO.2 ได้เพิ่มWatchService API
WatchService API ได้รับการออกแบบมาสำหรับแอปพลิเคชันที่ต้องได้รับการแจ้งเตือนเกี่ยวกับเหตุการณ์การเปลี่ยนแปลงไฟล์
ฉันใช้ VFS API จาก Apache Commons นี่คือตัวอย่างวิธีการตรวจสอบไฟล์โดยไม่ส่งผลกระทบต่อประสิทธิภาพมากนัก:
"คุณสมบัติอื่น ๆ ของ NIO" มีฟังก์ชันการเฝ้าดูไฟล์โดยการใช้งานจะขึ้นอยู่กับระบบปฏิบัติการพื้นฐาน ควรอยู่ใน JDK7
ปรับปรุง: ถูกบันทึกอยู่ใน Java SE 7. คริส Janicki ข้อเสนอการเชื่อมโยงไปเกี่ยวข้องกวดวิชา Java
ฉันเรียกใช้ส่วนย่อยของโค้ดนี้ทุกครั้งที่ฉันไปอ่านไฟล์คุณสมบัติโดยจะอ่านไฟล์นั้นหากมีการแก้ไขตั้งแต่ครั้งสุดท้ายที่ฉันอ่านเท่านั้น หวังว่านี่จะช่วยใครบางคนได้
private long timeStamp;
private File file;
private boolean isFileUpdated( File file ) {
this.file = file;
this.timeStamp = file.lastModified();
if( this.timeStamp != timeStamp ) {
this.timeStamp = timeStamp;
//Yes, file is updated
return true;
}
//No, file is not updated
return false;
}
วิธีการที่คล้ายกันถูกนำมาใช้ใน FileWatchdogLog4J
คุณสามารถฟังการเปลี่ยนแปลงไฟล์โดยใช้ FileReader โปรดดูตัวอย่างด้านล่าง
// File content change listener
private String fname;
private Object lck = new Object();
...
public void run()
{
try
{
BufferedReader br = new BufferedReader( new FileReader( fname ) );
String s;
StringBuilder buf = new StringBuilder();
while( true )
{
s = br.readLine();
if( s == null )
{
synchronized( lck )
{
lck.wait( 500 );
}
}
else
{
System.out.println( "s = " + s );
}
}
}
catch( Exception e )
{
e.printStackTrace();
}
}
หากคุณยินดีที่จะมีส่วนร่วมด้วยเงิน JNIWrapper เป็นไลบรารีที่มีประโยชน์พร้อม Winpack คุณจะสามารถรับเหตุการณ์ระบบไฟล์ในไฟล์บางไฟล์ได้ น่าเสียดายที่ windows เท่านั้น
ดูhttps://www.teamdev.com/jniwrapper
มิฉะนั้นการใช้รหัสเนทีฟก็ไม่ใช่เรื่องเลวร้ายเสมอไปโดยเฉพาะอย่างยิ่งเมื่อข้อเสนอที่ดีที่สุดคือกลไกการสำรวจความคิดเห็นเช่นเดียวกับเหตุการณ์ที่เกิดขึ้นเอง
ฉันสังเกตเห็นว่าการทำงานของระบบไฟล์ Java อาจช้าในคอมพิวเตอร์บางเครื่องและอาจส่งผลต่อประสิทธิภาพของแอปพลิเคชันได้ง่ายหากไม่ได้รับการจัดการที่ดี
คุณอาจพิจารณา Apache Commons JCI (Java Compiler Interface) แม้ว่า API นี้ดูเหมือนจะเน้นไปที่การรวบรวมคลาสแบบไดนามิก แต่ก็มีคลาสใน API ที่ตรวจสอบการเปลี่ยนแปลงของไฟล์ด้วย
ตัวอย่าง: http://commons.apache.org/jci/usage.html
มีไลบรารีข้ามเดสก์ท็อปเชิงพาณิชย์สำหรับไฟล์และโฟลเดอร์ที่เรียกว่า JxFileWatcher สามารถดาวน์โหลดได้จากที่นี่: http://www.teamdev.com/jxfilewatcher/
นอกจากนี้คุณสามารถดูได้ทางออนไลน์: http://www.teamdev.com/jxfilewatcher/onlinedemo/
การสำรวจคุณสมบัติไฟล์ที่แก้ไขล่าสุดเป็นวิธีง่ายๆ แต่มีประสิทธิภาพ เพียงกำหนดคลาสที่ขยายของฉันFileChangedWatcherและใช้onModified()วิธีการ:
import java.io.File;
public abstract class FileChangedWatcher
{
private File file;
public FileChangedWatcher(String filePath)
{
file = new File(filePath);
}
public void watch() throws InterruptedException
{
long currentModifiedDate = file.lastModified();
while (true)
{
long newModifiedDate = file.lastModified();
if (newModifiedDate != currentModifiedDate)
{
currentModifiedDate = newModifiedDate;
onModified();
}
Thread.sleep(100);
}
}
public String getFilePath()
{
return file.getAbsolutePath();
}
protected abstract void onModified();
}
เช่นเดียวกับคำตอบอื่น ๆ นี่คือวิธีที่ฉันใช้ File, Timer และ TimerTask เพื่อให้สิ่งนี้ทำงานเป็นการสำรวจเธรดพื้นหลังตามช่วงเวลาที่กำหนด
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
public class FileModifiedWatcher
{
private static File file;
private static int pollingInterval;
private static Timer fileWatcher;
private static long lastReadTimeStamp = 0L;
public static boolean init(String _file, int _pollingInterval)
{
file = new File(_file);
pollingInterval = _pollingInterval; // In seconds
watchFile();
return true;
}
private static void watchFile()
{
if ( null == fileWatcher )
{
System.out.println("START");
fileWatcher = new Timer();
fileWatcher.scheduleAtFixedRate(new TimerTask()
{
@Override
public void run()
{
if ( file.lastModified() > lastReadTimeStamp )
{
System.out.println("File Modified");
}
lastReadTimeStamp = System.currentTimeMillis();
}
}, 0, 1000 * pollingInterval);
}
}
}