Java Files.writeString: เขียนไฟล์ข้อความสั้นให้ครบชุด
การอัปเดตไฟล์คอนฟิกถ้าเขียนทับทีละส่วน อาจเหลือไฟล์ครึ่งใบตอนโปรเซสค้าง Files.writeString เขียนทั้งสตริงพร้อม charset ชัดเจน และผมอชอบเขียนลงไฟล์ชั่วคราวแล้ว ATOMIC_MOVE ทับของเดิมครับ
WHY: ทั้งก้อนหรือไม่เสียเลย
เหมือนเขียนเมนูร้านลงกระดาษแผ่นใหม่ทั้งแผ่น แล้วค่อยสลับกับแผ่นเก่าบนโต๊ะ ไม่ใช่ลบทีละบรรทัดกลางชั่วโมงเร่ง
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
public class Main {
static void writeAtomically(Path target, String body) throws Exception {
Path dir = target.getParent() == null ? Path.of(".") : target.getParent();
Path tmp = Files.createTempFile(dir, "cfg-", ".tmp");
try {
Files.writeString(tmp, body, StandardCharsets.UTF_8,
StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
Files.move(tmp, target, StandardCopyOption.ATOMIC_MOVE,
StandardCopyOption.REPLACE_EXISTING);
} catch (Exception e) {
Files.deleteIfExists(tmp);
throw e;
}
}
public static void main(String[] args) throws Exception {
Path dir = Files.createTempDirectory("ws");
Path file = dir.resolve("app.cfg");
writeAtomically(file, "theme=mint");
assert Files.readString(file, StandardCharsets.UTF_8).equals("theme=mint");
writeAtomically(file, "theme=forest");
assert Files.readString(file, StandardCharsets.UTF_8).equals("theme=forest");
System.out.println("writeString atomic verified");
}
}
HOW: ระบุ Charset เสมอ
ค่าเริ่มต้นของบาง API พึ่ง charset ของเครื่อง อย่าพึ่ง — ส่ง StandardCharsets.UTF_8 ทุกครั้ง writeString รับ CharSequence จึงส่ง String ตรง ๆ ได้
บนบางไฟล์ซิสเต็ม ATOMIC_MOVE ข้ามดิสก์อาจไม่รองรับ ให้จับ例外แล้ว fallback เป็น REPLACE_EXISTING ธรรมดา พร้อมทดสอบ
GOTCHA: ไฟล์ชั่วคราวค้างเมื่อพัง
ใช้ try/finally หรือลบ temp เมื่อ move ล้มเหลว อย่าทิ้งไฟล์ .tmp เกลื่อนในโฟลเดอร์คอนฟิก
Recap
-
Files.writeString+ UTF-8 ชัดเจน - เขียน temp แล้ว move ทับเมื่อต้องการอัปเดตทั้งก้อน
- จัดการกรณี atomic move ใช้ไม่ได้