using System; using System.Collections.Generic; using System.Text; using System.IO; namespace Quazistax { public static class QSFile { [ThreadStatic] private static byte[] fileBuf = new byte[128 * 1024]; private static void SimpleCopyFilePart(FileStream f, long from, long to, int length) { f.Position = from; f.Read(fileBuf, 0, length); f.Position = to; f.Write(fileBuf, 0, length); } public static void CopyFilePart(string file, long fromPos, long toPos, long length) { using (FileStream f = new FileStream(file, FileMode.Open, FileAccess.ReadWrite)) CopyFilePart(f, fromPos, toPos, length); } public static void CopyFilePart(FileStream f, long fromPos, long toPos, long length) { lock (fileBuf) { int bufSize = fileBuf.Length; if (toPos > fromPos) { if (toPos + length > f.Length) throw new ArgumentOutOfRangeException("toPos + length", "Destination range is out of file."); long i_to = toPos + length - bufSize; long i_from = fromPos + length - bufSize; for (long i = length / (long)bufSize; i > 0; --i, i_from -= bufSize, i_to -= bufSize) SimpleCopyFilePart(f, i_from, i_to, bufSize); int leftover = (int)(length % (long)bufSize); if (leftover > 0) SimpleCopyFilePart(f, fromPos, toPos, leftover); } else { if (fromPos + length > f.Length) throw new ArgumentOutOfRangeException("fromPos + length", "Source range is out of file."); long i_to = toPos; long i_from = fromPos; for (long i = length / (long)bufSize; i > 0; --i, i_from += bufSize, i_to += bufSize) SimpleCopyFilePart(f, i_from, i_to, bufSize); int leftover = (int)(length % (long)bufSize); if (leftover > 0) SimpleCopyFilePart(f, i_from, i_to, leftover); } } } public static void DeleteFilePart(string file, long startPos, long length) { using (FileStream f = new FileStream(file, FileMode.Open, FileAccess.ReadWrite)) DeleteFilePart(f, startPos, length); } public static void DeleteFilePart(FileStream f, long startPos, long length) { if (startPos + length > f.Length) throw new ArgumentOutOfRangeException("startPos + length", "Remove range is out of file."); long endPos = startPos + length; CopyFilePart(f, endPos, startPos, f.Length - endPos); f.SetLength(f.Length - length); } public static void InsertFilePart(string file, long startPos, long length) { using (FileStream f = new FileStream(file, FileMode.Open, FileAccess.ReadWrite)) InsertFilePart(f, startPos, length); } public static void InsertFilePart(FileStream f, long startPos, long length) { if (startPos > f.Length) throw new ArgumentOutOfRangeException("startPos", "Insertion position is out of file."); long endPos = startPos + length; f.SetLength(f.Length + length); CopyFilePart(f, startPos, endPos, f.Length - endPos); } public static void FillFilePart(string file, long startPos, long length, byte fillByte) { using (FileStream f = new FileStream(file, FileMode.Open, FileAccess.Write)) FillFilePart(f, startPos, length, fillByte); } public static void FillFilePart(FileStream f, long startPos, long length, byte fillByte) { if (startPos + length > f.Length) throw new ArgumentOutOfRangeException("startPos + length", "Fill range is out of file."); f.Position = startPos; for (long i = 0; i < length; ++i) f.WriteByte(fillByte); } } }