วิธีคัดลอกไฟล์โดยไม่ใช้ 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#:
-
เพิ่มไลบรารีที่จำเป็น: ให้แน่ใจว่าคุณได้รวม namespace ที่จำเป็นสำหรับการดำเนินการไฟล์และ Interop services.
using System; using System.IO; using System.Runtime.InteropServices;
-
ประกาศ 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);
-
การใช้ธง: ในฟังก์ชันการคัดลอกไฟล์ของคุณ ใช้ธงเพื่อสร้าง 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
โดยการเข้าใจและใช้ธงเหล่านี้ คุณสามารถปรับปรุงประสิทธิภาพการทำงานกับไฟล์ของคุณได้อย่างมีนัยสำคัญ ขอให้สนุกกับการเขียนโค้ด!