Recursive AI

Read and write compound files

All onearchive recipes

Write a Microsoft compound file with OneArchive and read it back the same way as a .doc, .xls, .ppt or .msg file: storages are directories and streams are files.

The writer is new in 0.7.0-preview.1:

C#
using RecursiveAI.OneArchive;
using System.Text;
 
// Write a Microsoft compound file: storages are directories, streams are files.
byte[] summary = Encoding.UTF8.GetBytes("Quarterly notes");
byte[] chart = new byte[10_000];
Archive.Create("notes.cfb")
    .Add(new ArchiveEntry { Name = "Summary", Kind = ArchiveEntryKind.File, Size = summary.Length }, summary)
    .Add(new ArchiveEntry { Name = "Attachments", Kind = ArchiveEntryKind.Directory }, [])
    .Add(new ArchiveEntry { Name = "Attachments/chart", Kind = ArchiveEntryKind.File, Size = chart.Length }, chart)
    .Save();
 
byte[] head = File.ReadAllBytes("notes.cfb")[..8];
Console.WriteLine($"notes.cfb: {new FileInfo("notes.cfb").Length:N0} bytes, signature {Convert.ToHexString(head)}");
 
// Read it back, the same way as a .doc, .xls, .ppt or .msg file.
using var cfb = Archive.Open("notes.cfb");
foreach (var e in cfb.Entries) Console.WriteLine($"  {e.Kind,-9} {e.Size,6:N0}  {e.Name}");
using var s = cfb.OpenEntry(cfb.Find("Summary")!);
Console.WriteLine($"Summary: {new StreamReader(s).ReadToEnd()}");
Text
notes.cfb: 12,800 bytes, signature D0CF11E0A1B11AE1
  File          15  Summary
  Directory      0  Attachments
  File      10,000  Attachments/chart
Summary: Quarterly notes

Good to know

  • Archive.Open detects a compound file by its signature, D0 CF 11 E0 A1 B1 1A E1, so legacy Office files and Outlook messages open without naming the format. Entries then lists their storages and streams, such as WordDocument or Workbook.
  • ArchiveBuilder.Add(entry, bytes) needs the entry’s Size to match the content; a mismatch is an ArgumentException.
  • The writer writes version 3 (512-byte sectors, the default) or version 4 (4096-byte sectors), set with CompoundFileWriterOptions.
  • The reader validates strictly and has its own limits, including MaxDirectoryEntries.

The format details are in compound files.