public static void WriteAllBytes(string path, byte[] bytes) { ArgumentException.ThrowIfNullOrEmpty(path); ArgumentNullException.ThrowIfNull(bytes); using SafeFileHandle sfh = OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read); RandomAccess.WriteAtOffset(sfh, bytes, 0); }
private static void WriteToFile(string path, FileMode mode, string?contents, Encoding encoding) { ReadOnlySpan <byte> preamble = encoding.GetPreamble(); int preambleSize = preamble.Length; using SafeFileHandle fileHandle = OpenHandle(path, mode, FileAccess.Write, FileShare.Read, FileOptions.None, GetPreallocationSize(mode, contents, encoding, preambleSize)); long fileOffset = mode == FileMode.Append && fileHandle.CanSeek ? RandomAccess.GetLength(fileHandle) : 0; if (string.IsNullOrEmpty(contents)) { if (preambleSize > 0 && // even if the content is empty, we want to store the preamble fileOffset == 0) // if we're appending to a file that already has data, don't write the preamble. { RandomAccess.WriteAtOffset(fileHandle, preamble, fileOffset); } return; } int bytesNeeded = preambleSize + encoding.GetMaxByteCount(Math.Min(contents.Length, ChunkSize)); byte[]? rentedBytes = null; Span <byte> bytes = bytesNeeded <= 1024 ? stackalloc byte[1024] : (rentedBytes = ArrayPool <byte> .Shared.Rent(bytesNeeded)); try { if (fileOffset == 0) { preamble.CopyTo(bytes); } else { preambleSize = 0; // don't append preamble to a non-empty file } Encoder encoder = encoding.GetEncoder(); ReadOnlySpan <char> remaining = contents; while (!remaining.IsEmpty) { ReadOnlySpan <char> toEncode = remaining.Slice(0, Math.Min(remaining.Length, ChunkSize)); remaining = remaining.Slice(toEncode.Length); int encoded = encoder.GetBytes(toEncode, bytes.Slice(preambleSize), flush: remaining.IsEmpty); Span <byte> toStore = bytes.Slice(0, preambleSize + encoded); RandomAccess.WriteAtOffset(fileHandle, toStore, fileOffset); fileOffset += toStore.Length; preambleSize = 0; } } finally { if (rentedBytes is not null) { ArrayPool <byte> .Shared.Return(rentedBytes); } } }
private static async Task WriteToFileAsync(string path, FileMode mode, string?contents, Encoding encoding, CancellationToken cancellationToken) { ReadOnlyMemory <byte> preamble = encoding.GetPreamble(); int preambleSize = preamble.Length; using SafeFileHandle fileHandle = OpenHandle(path, mode, FileAccess.Write, FileShare.Read, FileOptions.Asynchronous, GetPreallocationSize(mode, contents, encoding, preambleSize)); long fileOffset = mode == FileMode.Append && fileHandle.CanSeek ? RandomAccess.GetLength(fileHandle) : 0; if (string.IsNullOrEmpty(contents)) { if (preambleSize > 0 && // even if the content is empty, we want to store the preamble fileOffset == 0) // if we're appending to a file that already has data, don't write the preamble. { await RandomAccess.WriteAtOffsetAsync(fileHandle, preamble, fileOffset, cancellationToken).ConfigureAwait(false); } return; } byte[] bytes = ArrayPool <byte> .Shared.Rent(preambleSize + encoding.GetMaxByteCount(Math.Min(contents.Length, ChunkSize))); try { if (fileOffset == 0) { preamble.CopyTo(bytes); } else { preambleSize = 0; // don't append preamble to a non-empty file } Encoder encoder = encoding.GetEncoder(); ReadOnlyMemory <char> remaining = contents.AsMemory(); while (!remaining.IsEmpty) { ReadOnlyMemory <char> toEncode = remaining.Slice(0, Math.Min(remaining.Length, ChunkSize)); remaining = remaining.Slice(toEncode.Length); int encoded = encoder.GetBytes(toEncode.Span, bytes.AsSpan(preambleSize), flush: remaining.IsEmpty); ReadOnlyMemory <byte> toStore = new ReadOnlyMemory <byte>(bytes, 0, preambleSize + encoded); await RandomAccess.WriteAtOffsetAsync(fileHandle, toStore, fileOffset, cancellationToken).ConfigureAwait(false); fileOffset += toStore.Length; preambleSize = 0; } } finally { ArrayPool <byte> .Shared.Return(bytes); } }
private static async Task <byte[]> InternalReadAllBytesUnknownLengthAsync(SafeFileHandle sfh, CancellationToken cancellationToken) { byte[] rentedArray = ArrayPool <byte> .Shared.Rent(512); try { int bytesRead = 0; while (true) { if (bytesRead == rentedArray.Length) { uint newLength = (uint)rentedArray.Length * 2; if (newLength > Array.MaxLength) { newLength = (uint)Math.Max(Array.MaxLength, rentedArray.Length + 1); } byte[] tmp = ArrayPool <byte> .Shared.Rent((int)newLength); Buffer.BlockCopy(rentedArray, 0, tmp, 0, bytesRead); byte[] toReturn = rentedArray; rentedArray = tmp; ArrayPool <byte> .Shared.Return(toReturn); } Debug.Assert(bytesRead < rentedArray.Length); int n = await RandomAccess.ReadAtOffsetAsync(sfh, rentedArray.AsMemory(bytesRead), bytesRead, cancellationToken).ConfigureAwait(false); if (n == 0) { return(rentedArray.AsSpan(0, bytesRead).ToArray()); } bytesRead += n; } } finally { sfh.Dispose(); ArrayPool <byte> .Shared.Return(rentedArray); } }
public static byte[] ReadAllBytes(string path) { // SequentialScan is a perf hint that requires extra sys-call on non-Windows OSes. FileOptions options = OperatingSystem.IsWindows() ? FileOptions.SequentialScan : FileOptions.None; using (SafeFileHandle sfh = OpenHandle(path, FileMode.Open, FileAccess.Read, FileShare.Read, options)) { long fileLength = 0; if (sfh.CanSeek && (fileLength = sfh.GetFileLength()) > Array.MaxLength) { throw new IOException(SR.IO_FileTooLong2GB); } #if DEBUG fileLength = 0; // improve the test coverage for ReadAllBytesUnknownLength #endif if (fileLength == 0) { // Some file systems (e.g. procfs on Linux) return 0 for length even when there's content; also there are non-seekable files. // Thus we need to assume 0 doesn't mean empty. return(ReadAllBytesUnknownLength(sfh)); } int index = 0; int count = (int)fileLength; byte[] bytes = new byte[count]; while (count > 0) { int n = RandomAccess.ReadAtOffset(sfh, bytes.AsSpan(index, count), index); if (n == 0) { ThrowHelper.ThrowEndOfFileException(); } index += n; count -= n; } return(bytes); } }
private static async Task <byte[]> InternalReadAllBytesAsync(SafeFileHandle sfh, int count, CancellationToken cancellationToken) { using (sfh) { int index = 0; byte[] bytes = new byte[count]; do { int n = await RandomAccess.ReadAtOffsetAsync(sfh, bytes.AsMemory(index), index, cancellationToken).ConfigureAwait(false); if (n == 0) { ThrowHelper.ThrowEndOfFileException(); } index += n; } while (index < count); return(bytes); } }
static async Task Core(string path, byte[] bytes, CancellationToken cancellationToken) { using SafeFileHandle sfh = OpenHandle(path, FileMode.Create, FileAccess.Write, FileShare.Read, FileOptions.Asynchronous); await RandomAccess.WriteAtOffsetAsync(sfh, bytes, 0, cancellationToken).ConfigureAwait(false); }