public void ThrowsArgumentNullExceptionForNullBuffers() { using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.Write)) { AssertExtensions.Throws <ArgumentNullException>("buffers", () => RandomAccess.Read(handle, buffers: null, 0)); } }
public void ThrowsOnWriteAccess() { using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Write)) { Assert.Throws <UnauthorizedAccessException>(() => RandomAccess.Read(handle, new Memory <byte>[] { new byte[1] }, 0)); } }
public void ThrowsArgumentNullExceptionForNullBuffers(FileOptions options) { using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Read, options)) { AssertExtensions.Throws <ArgumentNullException>("buffers", () => RandomAccess.Read(handle, buffers: null, 0)); } }
public void ReadsBytesFromGivenFileAtGivenOffset(FileOptions options) { const int fileSize = 4_001; string filePath = GetTestFilePath(); byte[] expected = RandomNumberGenerator.GetBytes(fileSize); File.WriteAllBytes(filePath, expected); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: options)) { byte[] actual = new byte[fileSize + 1]; int current = 0; int total = 0; do { Span <byte> buffer = actual.AsSpan(total, Math.Min(actual.Length - total, fileSize / 4)); current = RandomAccess.Read(handle, buffer, fileOffset: total); Assert.InRange(current, 0, buffer.Length); total += current; } while (current != 0); Assert.Equal(fileSize, total); Assert.Equal(expected, actual.Take(total).ToArray()); } }
public void ShouldReuseBuffer() { var ra = new RandomAccess(new byte[] { 1, 2, 3, 4 }); ra.Byte(); var read = ra.Read(3); Assert.AreEqual(3, read.Length); Assert.AreEqual(0, read.Position); Assert.AreEqual(2, read.Byte()); Assert.AreEqual(3, read.Byte()); Assert.AreEqual(4, read.Byte()); read.JumpAbsolute(0); Assert.AreEqual(2, read.Byte()); read.JumpRelative(1); Assert.AreEqual(4, read.Byte()); read.JumpAbsolute(1); var read2 = read.Read(2); Assert.AreEqual(2, read2.Length); Assert.AreEqual(0, read2.Position); Assert.AreEqual(3, read2.Byte()); Assert.AreEqual(4, read2.Byte()); }
public async Task ReadUsingSingleBuffer(bool asyncOperation, bool asyncHandle) { const int fileSize = 1_000_000; // 1 MB string filePath = GetTestFilePath(); byte[] expected = RandomNumberGenerator.GetBytes(fileSize); File.WriteAllBytes(filePath, expected); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: GetFileOptions(asyncHandle))) using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(Environment.SystemPageSize)) { int current = 0; int total = 0; do { current = asyncOperation ? await RandomAccess.ReadAsync(handle, buffer.Memory, fileOffset : total) : RandomAccess.Read(handle, buffer.GetSpan(), fileOffset: total); Assert.True(expected.AsSpan(total, current).SequenceEqual(buffer.GetSpan().Slice(0, current))); total += current; }while (current != 0); Assert.Equal(fileSize, total); } }
static async Task Validate(SafeFileHandle handle, FileOptions options, bool[] syncWrites, bool[] syncReads) { byte[] writeBuffer = new byte[1]; byte[] readBuffer = new byte[2]; long fileOffset = 0; foreach (bool syncWrite in syncWrites) { foreach (bool syncRead in syncReads) { writeBuffer[0] = (byte)fileOffset; if (syncWrite) { RandomAccess.Write(handle, writeBuffer, fileOffset); } else { await RandomAccess.WriteAsync(handle, writeBuffer, fileOffset); } Assert.Equal(writeBuffer.Length, syncRead ? RandomAccess.Read(handle, readBuffer, fileOffset) : await RandomAccess.ReadAsync(handle, readBuffer, fileOffset)); Assert.Equal(writeBuffer[0], readBuffer[0]); fileOffset += 1; } } }
public void ThrowsOnWriteAccess(FileOptions options) { using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Write, options)) { Assert.Throws <UnauthorizedAccessException>(() => RandomAccess.Read(handle, new byte[1], 0)); } }
public TpsHeader(RandomAccess rx) { Data = rx ?? throw new ArgumentNullException(nameof(rx)); Address = rx.LongLE(); if (Address != 0) { throw new NotATopSpeedFileException("File does not start with 0x00000000. It is not a TopSpeed file or it may be encrypted."); } HeaderSize = rx.ShortLE(); var header = rx.Read(HeaderSize - 6); FileLength1 = header.LongLE(); FileLength2 = header.LongLE(); MagicNumber = header.FixedLengthString(4); Zeroes = header.ShortLE(); LastIssuedRow = header.LongBE(); Changes = header.LongLE(); ManagementPageReference = header.ToFileOffset(header.LongLE()); PageStart = header.ToFileOffset(header.LongArrayLE((0x110 - 0x20) / 4)); PageEnd = header.ToFileOffset(header.LongArrayLE((0x200 - 0x110) / 4)); }
public void ShouldFailBeyondBuffer() { var ra = new RandomAccess(new byte[] { 1, 2, 3, 4 }); ra.Byte(); var read = ra.Read(3); Assert.Throws <IndexOutOfRangeException>(() => read.LongLE()); }
public void ShouldFailBeforeBuffer() { var ra = new RandomAccess(new byte[] { 1, 2, 3, 4 }); ra.Byte(); var read = ra.Read(3); read.JumpAbsolute(-1); Assert.Throws <IndexOutOfRangeException>(() => read.Byte()); }
/// <summary> /// 读取二进制文件。 /// </summary> /// <param name="path">给定的文件路径。</param> /// <param name="fileOffset">给定的读取偏移量。</param> /// <returns>返回字节数组。</returns> public static byte[] ReadBinaryFile(this string path, long fileOffset) { using (var handle = File.OpenHandle(path)) { var length = RandomAccess.GetLength(handle); var buffer = new byte[length - fileOffset]; var readLength = RandomAccess.Read(handle, buffer, fileOffset); return(buffer); } }
public void ZeroesTheFileContentsWhenExtendingTheFile(FileOptions options) { using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.Write, options: options)) { RandomAccess.SetLength(handle, FileSize); byte[] buffer = new byte[FileSize + 1]; Assert.Equal(FileSize, RandomAccess.Read(handle, buffer, 0)); Assert.All(buffer, @byte => Assert.Equal(0, @byte)); } }
private void ReadFileTable(SafeFileHandle handle) { // Read the 12 byte footer at the end of the file Span <byte> fileFooter = stackalloc byte[12]; if (RandomAccess.Read(_fileHandle, fileFooter, _fileLength - fileFooter.Length) < fileFooter.Length) { throw new InvalidDataException("Couldn't read file footer"); } var signature = BitConverter.ToUInt32(fileFooter[..4]);
public void ReadToAnEmptyBufferReturnsZero() { string filePath = GetTestFilePath(); File.WriteAllBytes(filePath, new byte[1]); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open)) { Assert.Equal(0, RandomAccess.Read(handle, new Memory <byte>[] { Array.Empty <byte>() }, fileOffset: 0)); } }
public void ReadFromBeyondEndOfFileReturnsZero(FileOptions options) { string filePath = GetTestFilePath(); File.WriteAllBytes(filePath, new byte[100]); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: options)) { long eof = RandomAccess.GetLength(handle); Assert.Equal(0, RandomAccess.Read(handle, new byte[1], fileOffset: eof + 1)); } }
public void CanUseStackAllocatedMemory(FileOptions options) { string filePath = GetTestFilePath(); File.WriteAllBytes(filePath, new byte[1] { 3 }); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: options)) { Span <byte> stackAllocated = stackalloc byte[2]; Assert.Equal(1, RandomAccess.Read(handle, stackAllocated, fileOffset: 0)); Assert.Equal(3, stackAllocated[0]); } }
public void ReadToTheSameBufferOverwritesContent() { string filePath = GetTestFilePath(); File.WriteAllBytes(filePath, new byte[3] { 1, 2, 3 }); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open)) { byte[] buffer = new byte[1]; Assert.Equal(buffer.Length + buffer.Length, RandomAccess.Read(handle, Enumerable.Repeat(buffer.AsMemory(), 2).ToList(), fileOffset: 0)); Assert.Equal(2, buffer[0]); } }
/// <summary>Read the database for the specified terminal from the specified directory.</summary> /// <param name="term">The identifier for the terminal.</param> /// <param name="directoryPath">The path to the directory containing terminfo database files.</param> /// <returns>The database, or null if it could not be found.</returns> internal static Database?ReadDatabase(string?term, string?directoryPath) { if (string.IsNullOrEmpty(term) || string.IsNullOrEmpty(directoryPath)) { return(null); } Span <char> stackBuffer = stackalloc char[256]; SafeFileHandle?fd; if (!TryOpen(string.Create(null, stackBuffer, $"{directoryPath}/{term[0]}/{term}"), out fd) && // /directory/termFirstLetter/term (Linux) !TryOpen(string.Create(null, stackBuffer, $"{directoryPath}/{(int)term[0]:X}/{term}"), out fd)) // /directory/termFirstLetterAsHex/term (Mac) { return(null); } using (fd) { // Read in all of the terminfo data long termInfoLength = RandomAccess.GetLength(fd); const int MaxTermInfoLength = 4096; // according to the term and tic man pages, 4096 is the terminfo file size max const int HeaderLength = 12; if (termInfoLength <= HeaderLength || termInfoLength > MaxTermInfoLength) { throw new InvalidOperationException(SR.IO_TermInfoInvalid); } byte[] data = new byte[(int)termInfoLength]; long fileOffset = 0; do { int bytesRead = RandomAccess.Read(fd, new Span <byte>(data, (int)fileOffset, (int)(termInfoLength - fileOffset)), fileOffset); if (bytesRead == 0) { throw new InvalidOperationException(SR.IO_TermInfoInvalid); } fileOffset += bytesRead; } while (fileOffset < termInfoLength); // Create the database from the data return(new Database(term, data)); } }
private static bool CompareTimeZoneFile(string filePath, byte[] buffer, byte[] rawData) { try { // bufferSize == 1 used to avoid unnecessary buffer in FileStream using (SafeFileHandle sfh = File.OpenHandle(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { long fileLength = RandomAccess.GetLength(sfh); if (fileLength == rawData.Length) { int index = 0; int count = rawData.Length; while (count > 0) { int n = RandomAccess.Read(sfh, buffer.AsSpan(index, count), index); if (n == 0) { ThrowHelper.ThrowEndOfFileException(); } int end = index + n; for (; index < end; index++) { if (buffer[index] != rawData[index]) { return(false); } } count -= n; } return(true); } } } catch (IOException) { } catch (SecurityException) { } catch (UnauthorizedAccessException) { } return(false); }
/// <summary> /// Creates a new <see cref="TpsRecord"/>. This is typically done on the first of a list. /// </summary> /// <param name="rx">The data to read from.</param> public TpsRecord(RandomAccess rx) { if (rx == null) { throw new ArgumentNullException(nameof(rx)); } Flags = rx.Byte(); if ((Flags & 0xC0) != 0xC0) { throw new ArgumentException($"Cannot construct a TpsRecord without record lengths (0x{rx.ToHex2(Flags)})"); } RecordLength = rx.ShortLE(); HeaderLength = rx.ShortLE(); Data = rx.Read(RecordLength); BuildHeader(); }
public TpsPage(RandomAccess rx) { if (rx == null) { throw new ArgumentNullException(nameof(rx)); } Records = new List <TpsRecord>(); Address = rx.LongLE(); Size = rx.ShortLE(); var header = rx.Read(Size - 6); SizeUncompressed = header.ShortLE(); SizeUncompressedWithoutHeader = header.ShortLE(); RecordCount = header.ShortLE(); Flags = header.Byte(); CompressedData = header.Read(Size - 13); }
public void ReadsBytesFromGivenFileAtGivenOffset() { const int fileSize = 4_001; string filePath = GetTestFilePath(); byte[] expected = RandomNumberGenerator.GetBytes(fileSize); File.WriteAllBytes(filePath, expected); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open)) { byte[] actual = new byte[fileSize + 1]; long current = 0; long total = 0; do { int firstBufferLength = (int)Math.Min(actual.Length - total, fileSize / 4); Memory <byte> buffer_1 = actual.AsMemory((int)total, firstBufferLength); Memory <byte> buffer_2 = actual.AsMemory((int)total + firstBufferLength); current = RandomAccess.Read( handle, new Memory <byte>[] { buffer_1, Array.Empty <byte>(), buffer_2 }, fileOffset: total); Assert.InRange(current, 0, buffer_1.Length + buffer_2.Length); total += current; } while (current != 0); Assert.Equal(fileSize, total); Assert.Equal(expected, actual.Take((int)total).ToArray()); } }
public async Task ReadAsyncUsingMultipleBuffers(bool asyncOperation, bool asyncHandle) { const int fileSize = 1_000_000; // 1 MB string filePath = GetTestFilePath(); byte[] expected = RandomNumberGenerator.GetBytes(fileSize); File.WriteAllBytes(filePath, expected); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: GetFileOptions(asyncHandle))) using (SectorAlignedMemory <byte> buffer_1 = SectorAlignedMemory <byte> .Allocate(Environment.SystemPageSize)) using (SectorAlignedMemory <byte> buffer_2 = SectorAlignedMemory <byte> .Allocate(Environment.SystemPageSize)) { long current = 0; long total = 0; IReadOnlyList <Memory <byte> > buffers = new Memory <byte>[] { buffer_1.Memory, buffer_2.Memory, }; do { current = asyncOperation ? await RandomAccess.ReadAsync(handle, buffers, fileOffset : total) : RandomAccess.Read(handle, buffers, fileOffset: total); int takeFromFirst = Math.Min(buffer_1.Memory.Length, (int)current); Assert.True(expected.AsSpan((int)total, takeFromFirst).SequenceEqual(buffer_1.GetSpan().Slice(0, takeFromFirst))); int takeFromSecond = (int)current - takeFromFirst; Assert.True(expected.AsSpan((int)total + takeFromFirst, takeFromSecond).SequenceEqual(buffer_2.GetSpan().Slice(0, takeFromSecond))); total += current; } while (current == buffer_1.Memory.Length + buffer_2.Memory.Length); Assert.Equal(fileSize, total); } }
public async Task ReadUsingSingleBuffer(bool async) { const int fileSize = 1_000_000; // 1 MB string filePath = GetTestFilePath(); byte[] expected = RandomNumberGenerator.GetBytes(fileSize); File.WriteAllBytes(filePath, expected); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.Open, options: FileOptions.Asynchronous | NoBuffering)) // to use Scatter&Gather APIs on Windows the handle MUST be opened for async IO using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(Environment.SystemPageSize)) { int current = 0; int total = 0; // From https://docs.microsoft.com/en-us/windows/win32/fileio/file-buffering: // "File access sizes, including the optional file offset in the OVERLAPPED structure, // if specified, must be for a number of bytes that is an integer multiple of the volume sector size." // So if buffer and physical sector size is 4096 and the file size is 4097: // the read from offset=0 reads 4096 bytes // the read from offset=4096 reads 1 byte // the read from offset=4097 THROWS (Invalid argument, offset is not a multiple of sector size!) // That is why we stop at the first incomplete read (the next one would throw). // It's possible to get 0 if we are lucky and file size is a multiple of physical sector size. do { current = async ? await RandomAccess.ReadAsync(handle, buffer.Memory, fileOffset : total) : RandomAccess.Read(handle, buffer.GetSpan(), fileOffset: total); Assert.True(expected.AsSpan(total, current).SequenceEqual(buffer.GetSpan().Slice(0, current))); total += current; }while (current == buffer.Memory.Length); Assert.Equal(fileSize, total); } }
public uint HashFileLocationsUsingRandomAccessCrc32() { SafeFileHandle handle = File.OpenHandle(FilePath, FileMode.Open); byte[] buffer = new byte[1024 * 1024 * 2]; uint hash1 = 0; uint hash2 = 0; uint hash3 = 0; for (int i = 0; i < 10; i++) { RandomAccess.Read(handle, buffer, 0); hash1 = HashUtils.CRC32(buffer); RandomAccess.Read(handle, buffer, Count / 2); hash2 = HashUtils.CRC32(buffer); RandomAccess.Read(handle, buffer, Count - 1024 * 1024 * 2); hash3 = HashUtils.CRC32(buffer); } return((uint)HashCode.Combine(hash1, hash2, hash3)); }
protected override long MethodUnderTest(SafeFileHandle handle, byte[] bytes, long fileOffset) => RandomAccess.Read(handle, new Memory <byte>[] { bytes }, fileOffset);
protected override int MethodUnderTest(SafeFileHandle handle, byte[] bytes, long fileOffset) => RandomAccess.Read(handle, bytes, fileOffset);