บทนำ
เมื่อทีมกฎหมายหรือผู้วิเคราะห์ด้านนิติวิทยาศาสตร์ต้องพิสูจน์ว่าเอกสารไม่ได้ถูกดัดแปลง การมองเห็นเนื้อหาที่ปรากฏไม่เพียงพอ คุณสมบัติที่ซ่อนอยู่—เช่น ผู้เขียน, วันที่สร้าง, หรือหมายเลขรุ่น—สามารถเปิดเผยว่าใครได้สัมผัสไฟล์และเมื่อใด การตรวจจับการเปลี่ยนแปลงเล็ก ๆ เหล่านี้ในหลายเวอร์ชันของเอกสารเป็นจุดเจ็บปวดที่มักต้องตรวจสอบคุณสมบัติแต่ละอย่างด้วยตนเอง ซึ่งใช้เวลานานและเสี่ยงต่อข้อผิดพลาด
GroupDocs.Metadata for Java ให้วิธีการเชิงโปรแกรมเพื่อสกัดทุกฟิลด์เมตาดาต้าและคำนวณ diff แบบมีโครงสร้างระหว่างสองเวอร์ชัน ในบทเรียนนี้เราจะเปรียบเทียบสามวิธีการที่ใช้งานได้จริง: diff เมตาดาต้าครบถ้วน, การตรวจจับการเปลี่ยนแปลงความเป็นเจ้าของที่เน้น, และการวิเคราะห์ประวัติการแก้ไข แต่ละวิธีจะแสดงด้วยโค้ดสั้น ๆ ที่คัดลอก‑วางได้และเราจะสาธิตวิธีส่งออกผลลัพธ์เป็น CSV หรือ JSON เพื่อใช้ในการรายงานการตรวจสอบ
ฉันเจอปัญหานี้ขณะตรวจสอบสัญญาที่ถูกแก้ไขโดยหลายฝ่ายตลอดหลายเดือน; ข้อความที่มองเห็นดูเหมือนเหมือนเดิม แต่ฟิลด์ความเป็นเจ้าของเปลี่ยนแปลงอย่างเงียบ ๆ
ฉันจะบอกได้อย่างไรว่าฟิลด์เมตาดาต้าใดบ้างที่เปลี่ยนแปลงระหว่างสองเวอร์ชันของเอกสาร?
GroupDocs.Metadata โหลดไฟล์แต่ละไฟล์, สกัดคุณสมบัติที่เข้าถึงได้ทั้งหมดลงในแผนที่, แล้ววนลูปผ่านคีย์เพื่อจัดประเภทเป็นการเพิ่ม, การลบ, และการแก้ไข ไลบรารีจัดการแท็กที่มาพร้อมและแท็กที่กำหนดเอง, ดังนั้นคุณจะได้ภาพรวมที่ครบถ้วนโดยไม่ต้องเขียนพาร์เซอร์เฉพาะรูปแบบ ผลลัพธ์คืออ็อบเจกต์ MetadataDiff ที่คุณสามารถสอบถามหรือทำซีเรียลไลซ์เพื่อใช้ในรายงานการปฏิบัติตาม
ข้อกำหนดเบื้องต้น
- Java 8 หรือใหม่กว่า
- GroupDocs.Metadata for Java 24.7 ([temporary license][TEMP_LICENSE_URL])
- ไฟล์เอกสารสองไฟล์ที่คุณต้องการเปรียบเทียบ (เช่น
contract_v1.pdfและcontract_v2.pdf)
การติดตั้ง
เพิ่ม dependency ผ่าน Maven:
<dependency>
<groupId>com.groupdocs</groupId>
<artifactId>groupdocs-metadata</artifactId>
<version>24.7</version>
</dependency>
วิธีที่ 1 – การเปรียบเทียบเมตาดาต้าครบถ้วน
วิธีนี้สกัด ทุก คุณสมบัติเมตาดาต้าจากทั้งสองเวอร์ชันและรายงานรายการที่เพิ่ม, ลบ, และเปลี่ยนแปลง
// CompareMetadataSets.run – returns a MetadataDiff object
Map<String, String> v1 = ExtractAllMetadata.run(pathV1);
Map<String, String> v2 = ExtractAllMetadata.run(pathV2);
MetadataDiff diff = new MetadataDiff();
// Detect added and changed properties
for (Map.Entry<String, String> e : v2.entrySet()) {
String key = e.getKey();
String val = e.getValue();
if (!v1.containsKey(key)) {
diff.added.put(key, val); // New property in v2
} else if (!v1.get(key).equals(val)) {
diff.changed.put(key, new String[]{v1.get(key), val}); // Value changed
}
}
// Detect removed properties
for (Map.Entry<String, String> e : v1.entrySet()) {
if (!v2.containsKey(e.getKey())) {
diff.removed.put(e.getKey(), e.getValue());
}
}
return diff;
ประเด็นสำคัญ:
- ครอบคลุม: จับทุกแท็กรวมถึงแท็กที่กำหนดเอง
- ตรรกะแผนที่ง่าย: ไม่ต้องใช้ไลบรารี diff ภายนอก
- อ็อบเจกต์ผลลัพธ์: แผนที่
added,removed, และchangedพร้อมใช้งานต่อ
💡 เคล็ดลับ: ใช้วิธีนี้เมื่อคุณต้องการเส้นทางการตรวจสอบเต็มรูปแบบสำหรับการปฏิบัติตามกฎระเบียบ
วิธีที่ 2 – ตรวจจับการเปลี่ยนแปลงความเป็นเจ้าของ
ข้อพิพาททางกฎหมายมักพึ่งพาว่าใครเป็นผู้สร้างหรือแก้ไขเอกสาร วิธีนี้มุ่งเน้นที่แท็กที่เกี่ยวกับบุคคล เช่น Creator, Editor, Manager, และ Company
// DetectOwnershipChanges.run – returns a map of changed ownership fields
Map<String, String> v1 = readOwnership(pathV1);
Map<String, String> v2 = readOwnership(pathV2);
Set<String> allKeys = new HashSet<>(v1.keySet());
allKeys.addAll(v2.keySet());
Map<String, String[]> changes = new LinkedHashMap<>();
for (String key : allKeys) {
String oldVal = v1.getOrDefault(key, "<missing>");
String newVal = v2.getOrDefault(key, "<missing>");
if (!oldVal.equals(newVal)) {
changes.put(key, new String[]{oldVal, newVal});
}
}
return changes;
readOwnership ดึงเฉพาะแท็กที่เกี่ยวข้องเท่านั้น:
Map<String, String> result = new LinkedHashMap<>();
try (Metadata metadata = new Metadata(path)) {
if (metadata.getFileFormat() == FileFormat.Unknown) return result;
for (MetadataProperty p : metadata.findProperties(
new ContainsTagSpecification(Tags.getPerson().getCreator())
.or(new ContainsTagSpecification(Tags.getPerson().getEditor()))
.or(new ContainsTagSpecification(Tags.getPerson().getManager()))
.or(new ContainsTagSpecification(Tags.getCorporate().getCompany()))))