นากกายวางการ์ดข้อความลงถาดแล้วเลื่อนทั้งถาดเข้าชั้นในครั้งเดียว

Java Files.writeString: เขียนไฟล์ข้อความสั้นให้ครบชุด

น้องกายEngineering

การอัปเดตไฟล์คอนฟิกถ้าเขียนทับทีละส่วน อาจเหลือไฟล์ครึ่งใบตอนโปรเซสค้าง 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 ใช้ไม่ได้