Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

การย่อไฟล์ใน C# - FileStream.SetLength

ใช้ FileStream.SetLength() เพื่อย่อ (Truncate) หรือขยายไฟล์เป็นขนาดที่กำหนด

Syntax


public override void SetLength(long value);

พฤติกรรม

เงื่อนไขพฤติกรรม
Value < Current Lengthไฟล์ถูกย่อ (Truncate) - ข้อมูลเกินหายไป ถ้า Position > New Length → Position = New Length
Value > Current Lengthไฟล์ขยาย - พื้นที่ใหม่เป็น Undefined (Garbage) Position คงเดิม
Value = Current Lengthไม่เกิดอะไร

ตัวอย่าง: ย่อไฟล์ให้เหลือ 100 Bytes


using System;
using System.IO;

public class FileTruncateExample
{
    public static void TruncateFile(string path, long newSize)
    {
        // ต้องเปิดด้วย FileAccess.Write
        using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Write))
        {
            Console.WriteLine($"Current Length: {fs.Length}");
            Console.WriteLine($"Current Position: {fs.Position}");

            fs.SetLength(newSize);

            Console.WriteLine($"New Length: {fs.Length}");
            Console.WriteLine($"New Position: {fs.Position}");
        }
    }

    public static void Main()
    {
        string path = "test.txt";

        // สร้างไฟล์ทดสอบ 200 bytes
        File.WriteAllBytes(path, new byte[200]);

        TruncateFile(path, 100); // ย่อเหลือ 100 bytes
    }
}

ตัวอย่าง: ตัดบรรทัดสุดท้ายออก (Truncate Last Line)


public static void TruncateLastLine(string path)
{
    using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.ReadWrite))
    {
        // หา Newline ท้ายสุด
        long pos = fs.Length - 1;
        byte[] buffer = new byte[1];

        while (pos >= 0)
        {
            fs.Position = pos;
            fs.Read(buffer, 0, 1);
            if (buffer[0] == '\n' || buffer[0] == '\r')
            {
                // ตัดที่นี่ (รวม Newline)
                fs.SetLength(pos + 1);
                return;
            }
            pos--;
        }
    }
}

⚠️ ข้อควรระวัง

  • Data Loss: Truncate ทำให้ข้อมูลหายถาวร - ไม่มี Undo
  • Position: หลัง Truncate Position อาจเปลี่ยน (ถ้ามากกว่า New Length)
  • Concurrency: Process อื่นอ่านไฟล์อยู่อาจ Error
  • SSD Wear: เขียน/ย่อบ่อยส่งผลอายุ SSD (แต่ NTFS จัดการได้ค่อนข้างดี)

Alternative: Write New File แล้ว Replace (ปลอดภัยกว่า)


public static void SafeTruncate(string path, long newSize)
{
    string tempPath = path + ".tmp";

    using (var src = new FileStream(path, FileMode.Open, FileAccess.Read))
    using (var dst = new FileStream(tempPath, FileMode.Create, FileAccess.Write))
    {
        // Copy เฉพาะส่วนที่ต้องการ
        byte[] buffer = new byte[8192];
        long remaining = newSize;
        while (remaining > 0)
        {
            int toRead = (int)Math.Min(buffer.Length, remaining);
            int read = src.Read(buffer, 0, toRead);
            if (read == 0) break;
            dst.Write(buffer, 0, read);
            remaining -= read;
        }
    }

    // Atomic Replace
    File.Replace(tempPath, path, null); // Backup = null (No Backup)
}

กรณีใช้งานจริง

  • Log Rotation: ย่อ Log File เมื่อใหญ่เกินไป
  • Circular Buffer File: เขียนทับข้อมูลเก่า
  • Temp File Cleanup: ตัดข้อมูลที่ Process เสร็จแล้ว
  • Database-like: Truncate Table (Vacuum)