Table of Contents

CompoundFile Class

Definition

Namespace
Bodu.IO.Compound
Assembly
Bodu.IO.Compound.dll
Package
Bodu.IO.Compound 1.0.0
Source
CompoundFile.cs

Represents an OLE2 / Compound File Binary (CFB) container opened over a path or stream, exposing its storage hierarchy, the metadata of every entry, and the byte payload of each named stream for reading or editing.

public sealed class CompoundFile : IDisposable
Inheritance
CompoundFile
Implements
Inherited Members
Extension Methods

Examples

The following example opens a compound file, walks its top-level entries, and reads one named stream. The instance is disposed by the using declaration, which also closes the source stream unless leaveOpen is set.

using Bodu.IO.Compound;

using CompoundFile file = CompoundFile.Open(File.OpenRead("book.xls"));
foreach (CompoundEntryInfo info in file.RootStorage.EnumerateEntries())
    Console.WriteLine($"{info.EntryType}: {info.Name} ({info.Length} bytes)");

if (file.RootStorage.TryOpenStream("Workbook", out CompoundStream? workbook))
{
    using (workbook)
        // ... read the BIFF records from the workbook stream ...
}

Remarks

A compound file is a structured-storage envelope: one physical file that begins with the OLE2 signature D0 CF 11 E0 and holds a header, allocation tables (FAT and mini-FAT), a directory, and sectors. CompoundFile.Open parses that container and exposes a logical hierarchy. Navigation starts at RootStorage and descends through nested CompoundStorage containers to CompoundStream leaves; a CompoundStorage is the managed counterpart of the COM IStorage interface and a CompoundStream is the counterpart of IStream.

A compound file is a structured-storage envelope - effectively a small file system embedded in a single file - used by legacy Microsoft Office formats (.xls, .doc, .ppt, .msg) and other technologies. This type is the managed counterpart of the COM StgOpenStorage entry point: navigation begins at RootStorage and descends through nested CompoundStorage objects to the CompoundStream leaves.

By default a read-only file buffers the entire source into memory when opened, so access after opening never touches the original source and the read-only instance is safe to share across threads. Opening read-only with buffered: false instead reads sectors on demand from a seekable stream - bounding memory for large files - in which case the stream must stay open for the instance's lifetime and reads are serialized rather than parallel.

Opening with Read yields a read-only file. Create(Stream, bool, CompoundBuildOptions) (or a creating FileMode) starts a new writable file, and Open with ReadWrite loads an existing file for editing. Edits are staged in memory and written to the destination only by Commit() (which rewrites the whole container); Revert() discards them. Mutating an existing file requires read access - write-only access is supported only for creating modes.

Properties

Access

Gets the access level the compound file was opened with.

public FileAccess Access { get; }

Property Value

FileAccess

The FileAccess supplied at open time.

CanRead

Gets a value indicating whether the compound file can be read.

public bool CanRead { get; }

Property Value

bool

true when the file was opened with read access; otherwise false.

CanWrite

Gets a value indicating whether the compound file can be written.

public bool CanWrite { get; }

Property Value

bool

true when the file was opened with write access; otherwise false.

IsDirty

Gets a value indicating whether the file has staged edits that have not been committed.

public bool IsDirty { get; }

Property Value

bool

true when a writable file has uncommitted changes; otherwise false.

RootStorage

Gets the root storage that anchors the compound file's directory hierarchy.

public CompoundStorage RootStorage { get; }

Property Value

CompoundStorage

The root CompoundStorage.

Methods

Commit()

Writes the staged contents of a writable file to its destination, clearing the dirty state.

public void Commit()

Remarks

The destination is truncated and the whole container is rewritten from the staging tree. When the destination is not seekable, the committed bytes are appended at the current position.

Exceptions

InvalidOperationException

Thrown when the file is read-only.

ObjectDisposedException

Thrown when the file has been disposed.

CompoundFileSerializationException

Thrown when the staging tree cannot be represented.

CommitAsync(CancellationToken)

Asynchronously writes the staged contents of a writable file to its destination, clearing the dirty state.

public Task CommitAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

A token that cancels the commit before or during the write.

Returns

Task

A task that completes when the container has been written and flushed.

Remarks

The asynchronous counterpart of Commit(), sharing the same layout computation. Cancellation is observed before any destination mutation and again during the write; a cancellation or failure mid-write leaves the destination partially written and the file dirty - the same surface a synchronous Commit() fault presents - so call CommitAsync(CancellationToken) (or Commit()) again, or Revert().

Exceptions

InvalidOperationException

Thrown when the file is read-only.

ObjectDisposedException

Thrown when the file has been disposed.

CompoundFileSerializationException

Thrown when the staging tree cannot be represented.

OperationCanceledException

Thrown when cancellationToken is canceled.

Create(Stream, bool, CompoundBuildOptions)

Creates a new, empty writable compound file whose staged contents are written to the supplied destination by Commit().

public static CompoundFile Create(Stream destination, bool leaveOpen = false, CompoundBuildOptions options = default)

Parameters

destination Stream

The stream the committed compound file is written to.

leaveOpen bool

true to leave destination open when the returned instance is disposed; otherwise false.

options CompoundBuildOptions

The build options applied when the staging tree is serialized.

Returns

CompoundFile

A new writable CompoundFile.

Examples

using FileStream output = File.Create("book.xls");
using CompoundFile file = CompoundFile.Create(output);
using (CompoundStream stream = file.RootStorage.CreateStream("Workbook"))
    stream.Write(workbookBytes);
file.Commit();

Remarks

Edits made through RootStorage are staged in memory; nothing is written to destination until Commit() is called. Disposing the file without committing discards the staged edits.

Exceptions

ArgumentNullException

Thrown when destination is null.

Create(string, CompoundBuildOptions)

Creates a new, empty writable compound file whose staged contents are written to the file at the specified path by Commit().

public static CompoundFile Create(string path, CompoundBuildOptions options = default)

Parameters

path string

The path of the file the committed compound file is written to.

options CompoundBuildOptions

The build options applied when the staging tree is serialized.

Returns

CompoundFile

A new writable CompoundFile.

Remarks

The returned instance owns the created file and closes it when disposed. Edits are staged in memory until Commit() is called; disposing without committing leaves the file empty.

Exceptions

ArgumentNullException

Thrown when path is null.

Dispose()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

public void Dispose()

Flush()

Writes the staged contents of a writable file to its destination, clearing the dirty state.

public void Flush()

Remarks

This is an alias for Commit(), named for parity with stream-style consumers.

Exceptions

InvalidOperationException

Thrown when the file is read-only.

ObjectDisposedException

Thrown when the file has been disposed.

CompoundFileSerializationException

Thrown when the staging tree cannot be represented.

FlushAsync(CancellationToken)

Asynchronously writes the staged contents of a writable file to its destination, clearing the dirty state.

public Task FlushAsync(CancellationToken cancellationToken = default)

Parameters

cancellationToken CancellationToken

A token that cancels the write.

Returns

Task

A task that completes when the container has been written and flushed.

Remarks

This is an alias for CommitAsync(CancellationToken), named for parity with stream-style consumers.

Exceptions

InvalidOperationException

Thrown when the file is read-only.

ObjectDisposedException

Thrown when the file has been disposed.

CompoundFileSerializationException

Thrown when the staging tree cannot be represented.

IsCompoundFile(Stream)

Determines whether the supplied stream begins with the compound-file (OLE2) signature without parsing the file.

public static bool IsCompoundFile(Stream stream)

Parameters

stream Stream

A seekable stream to inspect; its position is restored before the method returns.

Returns

bool

true when the stream's leading bytes are the compound-file signature; otherwise false.

Examples

Probe a file cheaply before committing to a full open:

using FileStream source = File.OpenRead(path);
if (CompoundFile.IsCompoundFile(source))
{
    using CompoundFile file = CompoundFile.Open(source, leaveOpen: true);
    // ...
}

Exceptions

ArgumentNullException

Thrown when stream is null.

ArgumentException

Thrown when stream is not seekable.

IsCompoundFile(ReadOnlySpan<byte>)

Determines whether the supplied bytes begin with the compound-file (OLE2) signature.

public static bool IsCompoundFile(ReadOnlySpan<byte> data)

Parameters

data ReadOnlySpan<byte>

The bytes to inspect.

Returns

bool

true when data begins with the compound-file signature; otherwise false.

Open(Stream, CompoundFileOptions, bool)

Opens an existing compound file over the supplied stream for read-only access using the supplied options.

public static CompoundFile Open(Stream stream, CompoundFileOptions options, bool leaveOpen = false)

Parameters

stream Stream

The stream containing the compound file; read from its current position to the end.

options CompoundFileOptions

The options controlling the read strategy and validation level.

leaveOpen bool

true to leave stream open when the returned instance is disposed; otherwise false.

Returns

CompoundFile

An open, read-only CompoundFile.

Exceptions

ArgumentNullException

Thrown when stream or options is null.

CompoundFileFormatException

Thrown when the stream content is not a well-formed compound file.

Open(Stream, bool, bool)

Opens an existing compound file over the supplied stream for read-only access, buffering its content into memory by default.

public static CompoundFile Open(Stream stream, bool leaveOpen = false, bool buffered = true)

Parameters

stream Stream

The stream containing the compound file; read from its current position to the end.

leaveOpen bool

true to leave stream open when the returned instance is disposed; otherwise false.

buffered bool

true (the default) to read the whole file into memory at open time; false to read sectors on demand from the seekable stream, bounding memory for large files. When false, the stream must remain open and unmodified for the lifetime of the returned instance.

Returns

CompoundFile

An open, read-only CompoundFile.

Examples

using CompoundFile file = CompoundFile.Open(File.OpenRead("book.xls"));
using FileStream source = File.OpenRead("large.msg");
using CompoundFile streamed = CompoundFile.Open(source, buffered: false);

Exceptions

ArgumentNullException

Thrown when stream is null.

ArgumentException

Thrown when buffered is false and stream is not seekable.

CompoundFileFormatException

Thrown when the stream content is not a well-formed compound file.

Open(Stream, FileMode, FileAccess, bool, bool)

Opens a compound file over the supplied stream with BCL-style FileMode and FileAccess semantics, mirroring System.IO.Packaging.Package.Open.

public static CompoundFile Open(Stream stream, FileMode mode, FileAccess access, bool leaveOpen = false, bool buffered = true)

Parameters

stream Stream

The stream containing the compound file, or the destination for a writable file.

mode FileMode

The file mode. Open with Read opens for reading; a creating mode (Create/CreateNew, or OpenOrCreate over empty content) with write access starts a new file; Open with ReadWrite loads an existing file for editing.

access FileAccess

The access level. Mutating an existing file requires ReadWrite; write-only access is supported only for creating modes.

leaveOpen bool

true to leave stream open when the returned instance is disposed; otherwise false.

buffered bool

true (the default) to read the whole file into memory at open time; false to read sectors on demand from the seekable stream. Ignored for writable files.

Returns

CompoundFile

An open CompoundFile.

Remarks

Write access loads the existing content (for Open and a non-empty OpenOrCreate) or starts empty (for Create, CreateNew, and an empty OpenOrCreate) into a staging tree. Edits are written back to stream - which must be writable and seekable - only by Commit(), which rewrites the whole container.

Exceptions

ArgumentNullException

Thrown when stream is null.

NotSupportedException

Thrown when the combination of mode and access is not supported.

CompoundFileFormatException

Thrown when the stream content is not a well-formed compound file.

Open(string, FileMode, FileAccess, FileShare)

Opens the compound file at the specified path with BCL-style FileMode, FileAccess, and FileShare semantics, mirroring System.IO.Packaging.Package.Open.

public static CompoundFile Open(string path, FileMode mode, FileAccess access, FileShare share = FileShare.Read)

Parameters

path string

The path of the compound file to open or create.

mode FileMode

The file mode. Open with Read opens for reading; a creating mode with write access starts a new file; Open with write access loads the existing file for update.

access FileAccess

The access level. Write access requires a creating or updating mode.

share FileShare

The sharing mode granted to other openers of the file.

Returns

CompoundFile

An open CompoundFile that owns and closes the underlying file when disposed.

Remarks

For writable modes the staged edits are written back to the file only by Commit(); disposing without committing leaves the file unchanged.

Exceptions

ArgumentNullException

Thrown when path is null.

FileNotFoundException

Thrown when mode requires an existing file but none exists at path.

NotSupportedException

Thrown when the combination of mode and access is not supported.

CompoundFileFormatException

Thrown when the existing file content is not a well-formed compound file.

OpenRead(string)

Opens an existing compound file at the specified path for read-only access, buffering its content into memory.

public static CompoundFile OpenRead(string path)

Parameters

path string

The path of the compound file to open.

Returns

CompoundFile

An open, read-only CompoundFile.

Examples

using CompoundFile file = CompoundFile.OpenRead("book.xls");
foreach (CompoundEntryInfo info in file.RootStorage.EnumerateEntries())
    Console.WriteLine($"{info.EntryType}: {info.Name}");

Remarks

The returned instance owns the opened file and closes it when disposed. The file is opened with Read, so it does not lock out other readers.

Exceptions

ArgumentNullException

Thrown when path is null.

FileNotFoundException

Thrown when no file exists at path.

CompoundFileFormatException

Thrown when the file content is not a well-formed compound file.

OpenRead(string, CompoundFileOptions)

Opens an existing compound file at the specified path for read-only access using the supplied options.

public static CompoundFile OpenRead(string path, CompoundFileOptions options)

Parameters

path string

The path of the compound file to open.

options CompoundFileOptions

The options controlling the read strategy and validation level.

Returns

CompoundFile

An open, read-only CompoundFile.

Remarks

The returned instance owns the opened file and closes it when disposed. The file is opened with Read, so it does not lock out other readers.

Exceptions

ArgumentNullException

Thrown when path or options is null.

FileNotFoundException

Thrown when no file exists at path.

CompoundFileFormatException

Thrown when the file content is not a well-formed compound file.

Revert()

Discards all staged edits since the file was opened.

public void Revert()

Remarks

For a file opened in update mode this restores the contents loaded at open time; for a newly created file it restores the empty root storage.

Exceptions

InvalidOperationException

Thrown when the file is read-only.

ObjectDisposedException

Thrown when the file has been disposed.

SetDocumentSummaryInformation(DocumentSummaryInformation)

Writes the standard document-summary-information property set into the root storage, creating or replacing the stream.

public void SetDocumentSummaryInformation(DocumentSummaryInformation summary)

Parameters

summary DocumentSummaryInformation

The document summary information to write.

Remarks

The write counterpart of TryGetDocumentSummaryInformation(out DocumentSummaryInformation): the record's underlying PropertySet is staged as the \x05DocumentSummaryInformation stream and persisted when Commit() is called.

Exceptions

ArgumentNullException

Thrown when summary is null.

ObjectDisposedException

Thrown when the file has been disposed.

InvalidOperationException

Thrown when the file is read-only.

SetSummaryInformation(SummaryInformation)

Writes the standard summary-information property set into the root storage, creating or replacing the stream.

public void SetSummaryInformation(SummaryInformation summary)

Parameters

summary SummaryInformation

The summary information to write.

Remarks

The write counterpart of TryGetSummaryInformation(out SummaryInformation): the record's underlying PropertySet is staged as the \x05SummaryInformation stream and persisted when Commit() is called.

Exceptions

ArgumentNullException

Thrown when summary is null.

ObjectDisposedException

Thrown when the file has been disposed.

InvalidOperationException

Thrown when the file is read-only.

TryGetDocumentSummaryInformation(out DocumentSummaryInformation)

Attempts to read the document-summary-information property set from the root storage.

public bool TryGetDocumentSummaryInformation(out DocumentSummaryInformation summary)

Parameters

summary DocumentSummaryInformation

When this method returns true, the parsed DocumentSummaryInformation; otherwise null.

Returns

bool

true when the root storage contains a document-summary-information stream; otherwise false.

Exceptions

ObjectDisposedException

Thrown when the file has been disposed.

CompoundFileFormatException

Thrown when the property-set stream is malformed.

TryGetSummaryInformation(out SummaryInformation)

Attempts to read the standard summary-information property set from the root storage.

public bool TryGetSummaryInformation(out SummaryInformation summary)

Parameters

summary SummaryInformation

When this method returns true, the parsed SummaryInformation; otherwise null.

Returns

bool

true when the root storage contains a summary-information stream; otherwise false.

Exceptions

ObjectDisposedException

Thrown when the file has been disposed.

CompoundFileFormatException

Thrown when the property-set stream is malformed.

Applies to

ProductVersions
.NET8, 10