วิธีคัดลอกไฟล์โดยไม่ใช้ Windows File Cache

เมื่อพูดถึงการจัดการไฟล์ภายใน Windows คุณอาจพบสถานการณ์ที่ caching ของระบบปฏิบัติการอาจเป็นอุปสรรคต่อประสิทธิภาพ—โดยเฉพาะอย่างยิ่งเมื่อจัดการกับไฟล์ขนาดใหญ่ เช่น การคัดลอกไฟล์ขนาดใหญ่จากไดรฟ์ USB หรือเซิร์ฟเวอร์ไปยังเครื่องคอมพิวเตอร์ท้องถิ่นของคุณอาจทำให้เกิดปัญหาเนื่องจาก Windows จะทำการ cache ไฟล์ ซึ่งอาจทำให้ข้อมูลต้องถูกสลับออกไปและเพิ่มเวลาที่ใช้ในการดำเนินการให้เสร็จสิ้น

ในบล็อกโพสต์นี้ เราจะสำรวจวิธีการแก้ไขปัญหานี้โดยการคัดลอกไฟล์โดยไม่ใช้ cache ของระบบไฟล์ Windows โดยเฉพาะการใช้ C#

เข้าใจ Windows File System Cache

ก่อนที่จะไปสู่โซลูชันการเขียนโค้ด สิ่งสำคัญคือต้องเข้าใจว่า cache ของระบบไฟล์คืออะไร Windows ใช้ cache เพื่อเพิ่มความเร็วในการดำเนินการกับไฟล์ ซึ่งโดยทั่วไปจะรวมถึง:

  • การจัดเก็บข้อมูลไฟล์ในหน่วยความจำเพื่อให้เข้าถึงได้รวดเร็วขึ้น
  • การย้ายข้อมูลจากอุปกรณ์ที่ช้ากว่า เช่น ไดรฟ์ USB ไปยังหน่วยความจำของระบบที่เร็วกว่า

อย่างไรก็ตาม เมื่อพูดถึงไฟล์ขนาดใหญ่ (ประมาณ 2 GiB หรือมากกว่า) กระบวนการ caching นี้อาจก่อให้เกิดความไม่มีประสิทธิภาพ เนื่องจากระบบพยายามจัดการหน่วยความจำที่มีอยู่

โซลูชัน: การใช้ Win32 API Calls

ในการข้ามการทำงานของ caching นี้ Windows ได้จัดเตรียมธงเฉพาะที่คุณสามารถใช้เมื่อทำงานกับการดำเนินการไฟล์ ธงเหล่านี้คือ:

  • FILE_FLAG_WRITE_THROUGH: ธงนี้รับประกันว่าการเขียนลงไฟล์จะถูกเขียนไปยังอุปกรณ์จัดเก็บโดยตรงและจะไม่ถูก cache ในหน่วยความจำ
  • FILE_FLAG_NO_BUFFERING: ธงนี้ปิดการทำงานของ cache ของระบบสำหรับไฟล์ ซึ่งหมายความว่าการอ่านและเขียนทั้งหมดจะไปยังดิสก์โดยตรงโดยไม่ผ่านการ cache

คุณสามารถใช้ธงเหล่านี้ในโค้ด C# ของคุณเพื่อให้การคัดลอกไฟล์โดยตรงโดยไม่ใช้ cache

วิธีการจัดทำใน C# แบบทีละขั้นตอน

นี่คือวิธีการดำเนินการโซลูชันใน C#:

  1. เพิ่มไลบรารีที่จำเป็น: ให้แน่ใจว่าคุณได้รวม namespace ที่จำเป็นสำหรับการดำเนินการไฟล์และ Interop services.

    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    
  2. ประกาศ Native Methods: คุณจำเป็นต้องประกาศฟังก์ชัน Win32 API ที่จำเป็น

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr CreateFile(
        string lpFileName,
        uint dwDesiredAccess,
        uint dwShareMode,
        IntPtr lpSecurityAttributes,
        uint dwCreationDisposition,
        uint dwFlagsAndAttributes,
        IntPtr hTemplateFile);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool ReadFile(
        IntPtr hFile,
        byte[] lpBuffer,
        uint nNumberOfBytesToRead,
        out uint lpNumberOfBytesRead,
        IntPtr lpOverlapped);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool WriteFile(
        IntPtr hFile,
        byte[] lpBuffer,
        uint nNumberOfBytesToWrite,
        out uint lpNumberOfBytesWritten,
        IntPtr lpOverlapped);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool CloseHandle(IntPtr hObject);
    
  3. การใช้ธง: ในฟังก์ชันการคัดลอกไฟล์ของคุณ ใช้ธงเพื่อสร้าง handle ของไฟล์

    public void CopyFileWithoutCache(string sourceFilePath, string destFilePath)
    {
        const uint GENERIC_READ = 0x80000000;
        const uint GENERIC_WRITE = 0x40000000;
        const uint OPEN_EXISTING = 3;
        const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
        const uint FILE_FLAG_NO_BUFFERING = 0x20000000;
    
        IntPtr sourceHandle = CreateFile(sourceFilePath, GENERIC_READ, 0, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, IntPtr.Zero);
        IntPtr destHandle = CreateFile(destFilePath, GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, IntPtr.Zero);
    
        // ใส่ตรรกะการอ่านและเขียนไฟล์ที่นี่...
    
        CloseHandle(sourceHandle);
        CloseHandle(destHandle);
    }
    

สรุป

ด้วยขั้นตอนที่ได้กล่าวถึงข้างต้น คุณสามารถคัดลอกไฟล์ขนาดใหญ่ได้อย่างมีประสิทธิภาพโดยไม่ให้ถูกขัดขวางจาก cache ของระบบไฟล์ Windows วิธีนี้เป็นประโยชน์โดยเฉพาะเมื่อจัดการกับไฟล์ขนาดใหญ่ที่ถูกถ่ายโอนจากอุปกรณ์ที่ช้ากว่าเช่นไดรฟ์ USB

สำหรับข้อมูลเพิ่มเติม โปรดตรวจสอบเอกสารของ Microsoft เกี่ยวกับ FILE_FLAG_WRITE_THROUGH และ FILE_FLAG_NO_BUFFERING

โดยการเข้าใจและใช้ธงเหล่านี้ คุณสามารถปรับปรุงประสิทธิภาพการทำงานกับไฟล์ของคุณได้อย่างมีนัยสำคัญ ขอให้สนุกกับการเขียนโค้ด!