Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Hex view

The hex view shows a file as its bytes: the offset, the bytes in hex in groups of four, and the same bytes as ASCII. Use it to look inside a file datui has no reader for, and to work out the layout of a format spec.

Opens it
A local file no reader and no spec takesOpens here instead of failing
Enter on a binary row of the home screenRows shown with Ctrl+A
Ctrl+X on the home screenAny local file under the cursor
x in the Info panelThe dataset’s file, when it is one local file
datui --hex FILEAny local file

The file is memory-mapped, never read whole: drawing reads only the rows on screen, and a find reads the file on a worker. A file of many gigabytes opens at once.

Find a record’s length

This makes feed.bin, 500 records of 25 bytes that each start with SYNC, and opens it:

make_feed.py

import ctypes


class Record(ctypes.LittleEndianStructure):
    _layout_ = "ms"
    _pack_ = 1  # no padding: 25 bytes a record
    _fields_ = [
        ("sync", ctypes.c_char * 4),
        ("seq", ctypes.c_uint64),
        ("price", ctypes.c_uint32),
        ("change", ctypes.c_int16),
        ("size", ctypes.c_int16),
        ("flags", ctypes.c_int32),
        ("check", ctypes.c_uint8),
    ]


with open("feed.bin", "wb") as f:
    for i in range(500):
        f.write(bytes(Record(b"SYNC", i, 3 * i, -i, i, 0, i % 256)))
python3 make_feed.py
datui --hex feed.bin

Press f, type SYNC, Enter. The status line says the matches are 25 bytes apart; R makes that the bytes per row, and the records line up:

Hex · feed.bin · 12,500 bytes · 25 bytes/row (fixed)
offset    00 01 02 03  04 05 06 07   08 09 0a 0b  0c 0d 0e 0f   10 11 12 13  14 15 16 17   18
00000000  53 59 4e 43  00 00 00 00   00 00 00 00  00 00 00 00   00 00 00 00  00 00 00 00   00  SYNC·····················
00000019  53 59 4e 43  01 00 00 00   00 00 00 00  03 00 00 00   ff ff 01 00  00 00 00 00   01  SYNC·····················
00000032  53 59 4e 43  02 00 00 00   00 00 00 00  06 00 00 00   fe ff 02 00  00 00 00 00   02  SYNC·····················
0x19 of 0x30d4 · 0.2% · found SYNC · every 25 bytes · format unknown

Bytes 4 to 11 count up in each record: a little-endian u8 field, in a format spec’s types. The byte inspector reads the bytes at the cursor every way at once, which is how the rest of the layout is found.

Layout

WidthBytes per row
60 columns8
80 columns16
About 150 columns32
About 300 columns64
Under 50 columnsAs many as fit, without the ASCII column

The byte inspector sits beside the bytes when there is room for it and 16 bytes per row; elsewhere i opens it under them, in at most half the rows, counting the readings that do not fit. r or --hex-width N fixes the bytes per row (1 to 4096) so that records line up; a row wider than the screen shows the part the cursor is in.

Bytes are colored by class: 0x00, printable ASCII, whitespace, other control bytes, 0x80 to 0xFE, and 0xFF. The colors are the hex_* slots in the color settings. In the ASCII column a byte that is not printable is · (. on a terminal without Unicode).

Keys

KeyAction
f, n NFind; the next and previous match, round the end of the file
:Go to an offset
RMake the distance between matches the bytes per row
rBytes per row; empty for as many as fit
i EnterShow or hide the byte inspector
vMark a range from the cursor; the status line counts it
BRead the file with a format spec
EscStop a find; close the byte inspector or the mark; then back to where it came from

Moving takes vim’s keys (h j k l, w b, 0 $, g G); the keyboard reference has every key.

Go to an offset

TypedGoes to
4096Byte 4096
0x1000Byte 4096
+16, -1616 bytes after or before the cursor
e-8The eighth byte from the end; e-1 is the last

Find

TypedFinds
PAR1The text, as UTF-8 bytes
0x1acffc1dThose bytes
de ad be efThose bytes: two or more hex pairs
de ?? be ef?? matches any byte
"de ad"The text in quotes, even when it looks like hex

Ctrl+U in the prompt finds text as UTF-16 little-endian. A match may span rows. Every match on screen is marked, and Esc stops a find still reading a large file.

The byte inspector

At the cursor, little-endian and big-endian side by side:

Reading
u8 to u64, i8 to i64With the 3-, 5- and 6-byte widths (u24, u40, u48)
f16, f32, f64Floats
bitsThe byte in binary
varint, zigzagA LEB128 varint, its length, and its zigzag value
unix s, ms, us, nsA Unix time, when it lands between 1980 and 2100
yyyymmddA date written as an integer
days 1970, days 2000A count of days since either date
textThe text up to the first NUL
null?The null sentinels the bytes hold: an int’s min, a uint’s max, NaN

A marked range (v) shows its length under the readings.