This page follows the file format description in ROOT’s
TFile.cxx
and the code of TKey, TDirectoryFile, TDatime,
TBufferFile and the compression routines (RZip.cxx,
ZipLZ4.cxx, Compression.h), all read 2026-11-12. Numbers are
big-endian. Pointers are 4 bytes in small files and 8 bytes in large files (over
2 GB), as the version numbers say.
File header
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 4 | magic | root. |
4 | 4 | fVersion | File format version; 1,000,000 or more means a large file whose pointers below are 8 bytes. |
8 | 4 | fBEGIN | Offset of the first record, fixed at 100; bytes 96 to 99 are reserved and must be 0 (rules added for the registered media type). |
12 | 4 or 8 | fEND | End of the file. |
| … | 4 or 8 | fSeekFree | Record holding the free segment list. |
| … | 4 | fNbytesFree | Its size. |
| … | 4 | nfree | Number of free segments. |
| … | 4 | fNbytesName | Size of the file name and title in the top directory record. |
| … | 1 | fUnits | Size of file pointers: 4 or 8. |
| … | 4 | fCompress | Compression setting: algorithm × 100 + level. |
| … | 4 or 8 | fSeekInfo | Record holding the streamer information. |
| … | 4 | fNbytesInfo | Its size. |
| … | 18 | fUUID | Universal unique ID. |
The top directory’s record follows at fBEGIN; the file name and title
are stored there with its directory data.
Keys
Every object is stored as a record: a key, then the object’s bytes, usually compressed.
| Field | Size | Meaning |
|---|---|---|
Nbytes | 4 | Size of the key and the compressed object together. When a new record only partly fills a deleted gap, the rest of the gap starts with its size as a negative number. |
Version | 2 | Key version; 1000 is added when the record lies beyond 2 GB and the pointers are 8 bytes. |
ObjLen | 4 | Size of the object uncompressed. |
Datime | 4 | When it was written, packed. |
KeyLen | 2 | Size of the key. |
Cycle | 2 | Cycle number: several versions of an object with the same name can coexist. |
SeekKey | 4 or 8 | Position of this record. |
SeekPdir | 4 or 8 | Position of the directory it belongs to. |
ClassName | string | The object’s class name. |
Name, Title | string |
Strings are a length byte and the characters; when the length is over 254, the byte is 255 and a 4-byte length follows.
Packed date
(year − 1995) << 26 | month << 22 | day << 17 | hour << 12 |
minute << 6 | second, in the writing machine’s local time with no time
zone.
Directories and special records
- Directory: version (2; over 1000 for 8-byte pointers), creation and modification dates (4 each), size of the key list (4), size of the name and title (4), and the positions of the directory itself, its parent and its key list. The key list record holds the number of keys (4) and then a copy of each key. A writer asked for reproducible files stores date 1 in both date fields.
- Free segments (
TFree): first and last byte of each piece of unused space, so a writer can reuse deleted gaps. - Streamer information: the
TStreamerInforecord atfSeekInfo, describing the stored classes.
Compressed blocks
Object data is compressed in blocks of at most 0xFFFFFF bytes, each
with a 9-byte header: a 2-letter algorithm code, a method byte, the compressed size
(3 bytes) and the uncompressed size (3 bytes), both little-endian.
| Code | Algorithm | fCompress algorithm |
|---|---|---|
ZL | zlib (Deflate) | 1 |
XZ | LZMA (xz) | 2 |
CS | ROOT’s own old algorithm | 3 |
L4 | LZ4, with an 8-byte XXH64 checksum of the compressed data after the header (counted in the compressed size) | 4 |
ZS | Zstandard | 5 |
fCompress 0 means use the global setting.