private unsafe ValueTask <int> ReadAsyncInternal(Memory <byte> destination, CancellationToken cancellationToken) { if (!CanRead) { ThrowHelper.ThrowNotSupportedException_UnreadableStream(); } long positionBefore = _filePosition; if (CanSeek) { long len = Length; if (positionBefore + destination.Length > len) { destination = positionBefore <= len? destination.Slice(0, (int)(len - positionBefore)) : default; } // When using overlapped IO, the OS is not supposed to // touch the file pointer location at all. We will adjust it // ourselves, but only in memory. This isn't threadsafe. _filePosition += destination.Length; } (SafeFileHandle.OverlappedValueTaskSource? vts, int errorCode) = RandomAccess.QueueAsyncReadFile(_fileHandle, destination, positionBefore, cancellationToken); return(vts != null ? new ValueTask <int>(vts, vts.Version) : (errorCode == 0) ? ValueTask.FromResult(0) : ValueTask.FromException <int>(HandleIOError(positionBefore, errorCode))); }
public void ThrowsArgumentNullExceptionForNullBuffers(FileOptions options) { using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.Write, options: options)) { AssertExtensions.Throws <ArgumentNullException>("buffers", () => RandomAccess.ReadAsync(handle, buffers: null, 0)); } }
/// <summary> /// 写入二进制文件。 /// </summary> /// <param name="path">给定的文件路径。</param> /// <param name="buffer">给定的字节数组。</param> /// <param name="fileOffset">给定的读取偏移量。</param> public static void WriteBinaryFile(this string path, byte[] buffer, long fileOffset) { using (var handle = File.OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read)) { RandomAccess.Write(handle, buffer, fileOffset); } }
/// <summary> /// Instantiates a new TIME from the given binary reader. /// </summary> /// <remarks> /// The byte stream is read in the following order: /// <list type="bullet"> /// <item>Centiseconds</item> /// <item>Seconds</item> /// <item>Minutes</item> /// <item>Hours</item> /// </list> /// </remarks> /// <param name="rx"></param> public TpsTime(RandomAccess rx) { if (rx == null) { throw new ArgumentNullException(nameof(rx)); } // Time, mask encoded int time = rx.LongLE(); // Hours 0 - 23 int hours = (time & 0x7F000000) >> 24; // Minutes 0 - 59 int mins = (time & 0x00FF0000) >> 16; // Seconds 0 - 59 int secs = (time & 0x0000FF00) >> 8; // Centiseconds (seconds/100) 0 - 99 int centi = time & 0x000000FF; Value = new TimeSpan(0, hours, mins, secs, centi * 10); }
public void ReturnsZeroForEmptyFile() { using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.CreateNew, FileAccess.Write)) { Assert.Equal(0, RandomAccess.GetLength(handle)); } }
public void ThrowsOnReadAccess(FileOptions options) { using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Read, options)) { Assert.Throws <UnauthorizedAccessException>(() => RandomAccess.Write(handle, new byte[1], 0)); } }
public void ShouldParseBCD(string value, int bcdLength, int bcdDigitsAfterDecimal, byte[] data) { var rx = new RandomAccess(data); var bcd = rx.BinaryCodedDecimal(bcdLength, bcdDigitsAfterDecimal); Assert.AreEqual(value, bcd); }
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)); }
/// <summary>Create a tiler.</summary> /// <param name="f">The random access device from which image data may be read. /// This may be null if the tile information is available from memory.</param> /// <param name="fileOffset">The file offset within the RandomAccess device at which /// the data begins.</param> /// <param name="dims">The actual dimensions of the image.</param> /// <param name="base_Renamed">base class (should be a primitive type) of the image.</param> public ImageTiler(RandomAccess f, long fileOffset, int[] dims, Type base_Renamed) { this.f = f; this.fileOffset = fileOffset; this.dims = dims; this.base_Renamed = base_Renamed; }
public async Task ReadAsyncUsingSingleBuffer() { 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)) 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 = await RandomAccess.ReadAsync(handle, buffer.Memory, 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 async Task WritesBytesFromGivenBufferToGivenFileAtGivenOffsetAsync() { const int fileSize = 4_001; string filePath = GetTestFilePath(); byte[] content = RandomNumberGenerator.GetBytes(fileSize); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.Asynchronous)) { int total = 0; int current = 0; while (total != fileSize) { Memory <byte> buffer = content.AsMemory(total, Math.Min(content.Length - total, fileSize / 4)); current = await RandomAccess.WriteAsync(handle, buffer, fileOffset : total); Assert.InRange(current, 0, buffer.Length); total += current; } } Assert.Equal(content, File.ReadAllBytes(filePath)); }
public async Task WriteUsingEmptyBufferReturnsZeroAsync() { using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.Create, FileAccess.Write, options: FileOptions.Asynchronous)) { Assert.Equal(0, await RandomAccess.WriteAsync(handle, Array.Empty <byte>(), fileOffset: 0)); } }
public void ShouldReadFromRandomAccess(string value, int bcdLength, int bcdDigitsAfterDecimal, byte[] data) { var rx = new RandomAccess(data); var dec = new TpsDecimal(rx, bcdLength, bcdDigitsAfterDecimal); Assert.AreEqual(value, dec.Value); }
public IndexDefinitionRecord(RandomAccess rx) { if (rx == null) { throw new ArgumentNullException(nameof(rx)); } ExternalFile = rx.ZeroTerminatedString(); if (ExternalFile.Length == 0) { int read = rx.Byte(); if (read != 0x01) { throw new ArgumentException($"Bad index definition: missing 0x01 after zero string ({read:X2})"); } } Name = rx.ZeroTerminatedString(); Flags = rx.Byte(); FieldsInKey = rx.ShortLE(); KeyField = new int[FieldsInKey]; KeyFieldFlag = new int[FieldsInKey]; for (int i = 0; i < FieldsInKey; i++) { KeyField[i] = rx.ShortLE(); KeyFieldFlag[i] = rx.ShortLE(); } }
public void ShouldParseByte(byte value, byte[] data) { var rx = new RandomAccess(data); byte parsed = rx.Byte(); Assert.AreEqual(value, parsed); }
public DataHeader(RandomAccess rx) : base(rx) { AssertIsType(0xF3); RecordNumber = rx.LongBE(); }
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 FieldDefinitionRecord(RandomAccess rx) { if (rx == null) { throw new ArgumentNullException(nameof(rx)); } Type = (TpsTypeCode)rx.Byte(); Offset = rx.ShortLE(); FullName = rx.ZeroTerminatedString(); ElementCount = rx.ShortLE(); Length = rx.ShortLE(); Flags = rx.ShortLE(); Index = rx.ShortLE(); switch (Type) { case TpsTypeCode.Decimal: BcdDigitsAfterDecimalPoint = rx.Byte(); BcdElementLength = rx.Byte(); break; case TpsTypeCode.String: case TpsTypeCode.CString: case TpsTypeCode.PString: StringLength = rx.ShortLE(); StringMask = rx.ZeroTerminatedString(); if (StringMask.Length == 0) { rx.Byte(); } break; } }
public void ShouldParseShortLittleEndian(short value, byte[] data) { var rx = new RandomAccess(data); short parsed = rx.ShortLE(); Assert.AreEqual(value, parsed); }
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 ShouldParseLongLittleEndian(int value, byte[] data) { var rx = new RandomAccess(data); var parsed = rx.LongLE(); Assert.AreEqual(value, parsed); }
public async Task ReadWriteAsyncUsingMultipleBuffers(bool memoryPageSized) { string filePath = GetTestFilePath(); // We test with buffers both one and two memory pages long. In the former case, // the I/O operations will issue one scatter/gather API call, and in the latter // case they will issue multiple calls; one per buffer. The buffers must still // be aligned to comply with FILE_FLAG_NO_BUFFERING's requirements. int bufferSize = Environment.SystemPageSize * (memoryPageSized ? 1 : 2); int fileSize = bufferSize * 2; byte[] content = RandomNumberGenerator.GetBytes(fileSize); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, FileOptions.Asynchronous | NoBuffering)) using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(fileSize)) { Memory <byte> firstHalf = buffer.Memory.Slice(0, bufferSize); Memory <byte> secondHalf = buffer.Memory.Slice(bufferSize); content.AsSpan().CopyTo(buffer.GetSpan()); await RandomAccess.WriteAsync(handle, new ReadOnlyMemory <byte>[] { firstHalf, secondHalf }, 0); buffer.GetSpan().Clear(); long nRead = await RandomAccess.ReadAsync(handle, new Memory <byte>[] { firstHalf, secondHalf }, 0); Assert.Equal(buffer.GetSpan().Length, nRead); AssertExtensions.SequenceEqual(buffer.GetSpan(), content.AsSpan()); } }
public TableNameHeader(RandomAccess rx) : base(rx, readTable: false) { AssertIsType(0xFE); Name = rx.FixedLengthString(rx.Length - rx.Position); }
public void ThrowsArgumentNullExceptionForNullBuffers(FileOptions options) { using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Read, options)) { AssertExtensions.Throws <ArgumentNullException>("buffers", () => RandomAccess.Read(handle, buffers: null, 0)); } }
public async Task WriteUsingEmptyBufferReturnsAsync(FileOptions options) { using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.Create, FileAccess.Write, options: options)) { await RandomAccess.WriteAsync(handle, Array.Empty <byte>(), fileOffset : 0); } }
public async Task HappyPath(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 { Memory <byte> buffer = actual.AsMemory(total, Math.Min(actual.Length - total, fileSize / 4)); current = await RandomAccess.ReadAsync(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 ThrowsOnWriteAccess() { using (SafeFileHandle handle = GetHandleToExistingFile(FileAccess.Write)) { Assert.Throws <UnauthorizedAccessException>(() => RandomAccess.Read(handle, new Memory <byte>[] { new byte[1] }, 0)); } }
public async Task WriteAsyncUsingMultipleBuffers(bool async) { string filePath = GetTestFilePath(); int bufferSize = Environment.SystemPageSize; int fileSize = bufferSize * 10; byte[] content = RandomNumberGenerator.GetBytes(fileSize); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.Asynchronous | NoBuffering)) using (SectorAlignedMemory <byte> buffer_1 = SectorAlignedMemory <byte> .Allocate(bufferSize)) using (SectorAlignedMemory <byte> buffer_2 = SectorAlignedMemory <byte> .Allocate(bufferSize)) { long total = 0; IReadOnlyList <ReadOnlyMemory <byte> > buffers = new ReadOnlyMemory <byte>[] { buffer_1.Memory, buffer_2.Memory, }; while (total != fileSize) { content.AsSpan((int)total, bufferSize).CopyTo(buffer_1.GetSpan()); content.AsSpan((int)total + bufferSize, bufferSize).CopyTo(buffer_2.GetSpan()); total += async ? await RandomAccess.WriteAsync(handle, buffers, fileOffset : total) : RandomAccess.Write(handle, buffers, fileOffset: total); } } Assert.Equal(content, File.ReadAllBytes(filePath)); }
public void WriteUsingEmptyBufferReturnsZero() { using (SafeFileHandle handle = File.OpenHandle(GetTestFilePath(), FileMode.Create, FileAccess.Write)) { Assert.Equal(0, RandomAccess.Write(handle, Array.Empty <byte>(), fileOffset: 0)); } }
public async Task WriteUsingSingleBuffer(bool async) { string filePath = GetTestFilePath(); int bufferSize = Environment.SystemPageSize; int fileSize = bufferSize * 10; byte[] content = RandomNumberGenerator.GetBytes(fileSize); using (SafeFileHandle handle = File.OpenHandle(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileOptions.Asynchronous | NoBuffering)) using (SectorAlignedMemory <byte> buffer = SectorAlignedMemory <byte> .Allocate(bufferSize)) { int total = 0; while (total != fileSize) { int take = Math.Min(content.Length - total, bufferSize); content.AsSpan(total, take).CopyTo(buffer.GetSpan()); if (async) { await RandomAccess.WriteAsync(handle, buffer.Memory, fileOffset : total); } else { RandomAccess.Write(handle, buffer.GetSpan(), fileOffset: total); } total += buffer.Memory.Length; } } Assert.Equal(content, File.ReadAllBytes(filePath)); }
internal ImageDataTiler(ImageData enclosingInstance, RandomAccess o, long offset, ArrayDesc d) : base(o, offset, d.dims, d.type) { InitBlock(enclosingInstance); }
protected void SetFileOffset(Object o) { if(o is RandomAccess) { fileOffset = FitsUtil.FindOffset(o); dataSize = TrueSize; input = (RandomAccess)o; } }