/// <summary> /// Asynchronously writes a raw block of data to a file, combining <paramref name="basePath"/> with block's <see cref="DirectoryEntryBlock.FilePath"/>. Directories will be created as necessary. /// </summary> /// <param name="basePath"></param> /// <param name="rawBlock"></param> /// <param name="block"></param> public static async Task WriteRawBlockAsync( string basePath, byte[] rawBlock, DirectoryEntryBlock block, CancellationToken cancellationToken = default) { string path = Path.Combine(basePath, block.FilePath); Directory.CreateDirectory(Path.GetDirectoryName(path) !); using var fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read, (int)block.TotalUncompressedSize, true); await fs.WriteAsync(rawBlock, cancellationToken); }
/// <summary> /// Asynchronously reads a raw block from the stream into the given buffer. /// </summary> /// <param name="archiveStreams"></param> /// <param name="buffer"></param> /// <param name="block"></param> /// <returns></returns> public static async Task ReadRawBlockAsync( Stream archiveStream, Memory <byte> buffer, DirectoryEntryBlock block, IProgress <EntryOperation>?progress = null, CancellationToken cancellationToken = default) { int offset = 0; foreach (var entry in block.Entries) { cancellationToken.ThrowIfCancellationRequested(); var entrySlice = buffer.Slice(offset, (int)entry.UncompressedSize); await ReadRawEntryAsync(archiveStream, entrySlice, entry.Offset, cancellationToken); offset += (int)entry.UncompressedSize; progress?.Report(EntryOperation.Read); } }