Microsoft has not published the Jet and ACE file formats. This page follows the
HACKING.md notes of the MDB Tools project, which come from reverse
engineering; parts are marked unknown there and here. Offsets are hexadecimal and
numbers little-endian. “Jet 3” is Access 97; “Jet 4” is Access 2000 to 2003, and the
ACE files of Access 2007 and later use the Jet 4 layouts with additions.
Database definition page
Pages are 2,048 bytes in Jet 3 and 4,096 in Jet 4 and ACE. Page 0 describes the database.
| Offset | Size | Field |
|---|---|---|
00 | 1 | Page type 00. |
04 | 15 | Standard Jet DB (.mdb), Standard ACE DB (.accdb), or MSISAM Database (Microsoft Money). |
14 | 1 | Format: 00 Jet 3, 01 Jet 4, 02 Access 2007, 03 Access 2010, 04 Access 2013 (none seen), 05 Access 2016, 06 Access 2019 and 2021. |
15 | 1 | Sub-version, 0 or 1 (seen with formats 3 and 4). |
16 | 2 | Unused, zero. |
18 | 126 or 128 | Region masked with RC4 using a fixed key (126 bytes in Jet 3, 128 in Jet 4). The fields below are inside it. |
38 | 1 | Jet 3: a flag byte, 0 or 1. |
3A | 2 | Jet 3: default sort order. |
3C | 2 | Default code page (1252 in every Jet 3 file examined). |
3E | 4 | Database key: when not zero, every page is RC4-encrypted with this key XORed with the page number. |
42 | 20 or 40 | Database password (Jet 3: 20 bytes, Jet 4: 40), masked. |
6A | 4 | Jet 4: build number of the engine that made the file. |
6E | 4 | Jet 4: default sort order. |
72 | 8 | Jet 4: creation date, also used to mask the password. |
299 | 2 | Access 2007 and later: length of an Office encryption structure, for files encrypted with a password (not decoded by MDB Tools). |
Page 1 holds the global page usage map. The system table MSysObjects,
whose table definition is always at page 2, lists every table, query, form and
report.
Page types
| First byte | Page |
|---|---|
00 | Database definition (page 0 only) |
01 | Data |
02 | Table definition (TDEF); see table definitions |
03 | Intermediate index |
04 | Leaf index |
05 | Page usage bitmap |
08 | Unknown; listed with a question mark |
Data pages
| Jet 3 | Jet 4 | Size | Field |
|---|---|---|---|
00 | 00 | 1 | Page type 01. |
01 | 01 | 1 | Always 1. |
02 | 02 | 2 | Free space on the page. |
04 | 04 | 4 | Page of the table definition the rows belong to. |
| – | 08 | 4 | Jet 4: write time stamp. |
08 | 0C | 2 | Number of rows. |
0A | 0E | 2 each | Row offset table. |
Rows are stored from the end of the page backwards; each row runs from its offset to
the byte before the previous row’s. In a row offset the low 13 bits
(1FFF) are the offset; 4000 means the slot holds a 4-byte
pointer to the row on another page (an overflow row); 8000 means
deleted; 2000 has not been seen.
Row layout
| Field | Jet 3 | Jet 4 |
|---|---|---|
| Number of columns | 1 byte | 2 bytes |
| Fixed-length columns | At the offsets in the column definitions | |
| Variable-length columns | One after another | |
| End-of-data offset | 1 byte | 2 bytes |
| Variable column offsets | 1 byte each | 2 bytes each |
| Jump table | For rows of 256 bytes and more: the first variable column in each 256-byte stretch | None |
| Number of variable columns | 1 byte | 2 bytes |
| Null mask | (columns + 7) / 8 bytes; bit clear means null. Boolean columns are stored only here. | |
The row is read from both ends: the counts and offset table at the end, written backwards, say where each variable column starts.
Memo and OLE values
Long text (memo) and long binary (OLE) columns hold a 12-byte header in the row:
| Offset | Size | Field |
|---|---|---|
00 | 4 | Length in the low 30 bits; the top two bits are the type: 80 the value follows inline in the row; 40 it is a single row on an LVAL page; 00 it is spread over a chain of LVAL pages. |
04 | 4 | Where the value is: row number in the low byte, page number in the upper three. |
08 | 4 | Write stamp; zero for inline values. |
LVAL pages have a data page header with the text LVAL where the
table definition page would be. In a chain, each part starts with a 4-byte pointer
to the next. A page holds 2,032 (Jet 3) or 4,076 (Jet 4) bytes of value. The
largest value is 1 GB.
Page usage maps
- Type 0: byte 0 is
00, bytes 1 to 4 the first page covered, then a bitmap, one bit per page from the least significant bit; a set bit means the page belongs to the table. - Type 1: byte 0 is
01, then 4-byte pointers to usage map pages (type05), each holding the same kind of bitmap after a 4-byte header (05 01 00 00).
Text
Jet 3 text is in the database’s code page. Jet 4 and ACE text is UCS-2 (UTF-16LE),
but may be compressed: a value starting with FF FE begins in compressed
mode, where each character whose high byte is 0 is stored as one byte; a
00 byte switches between compressed and normal mode. Writers compress
only when it makes the value shorter.