Binary I/O

Let’s take a look at binary I/O.

Reading from a file

Our example for reading binary files is the classic hexdump tool. For simplicity, the filename is hard-coded instead of using a command-line argument.

const std = @import("std");
const print = std.debug.print;

pub fn main(init: std.process.Init) !void {
    const io = init.io;

    const cwd = std.Io.Dir.cwd();
    var file = try cwd.openFile(io, "hello", .{});
    var buf: [4096]u8 = undefined;
    var reader = file.readerStreaming(io, &buf);
    var r = &reader.interface;

    var bytes: [8]u8 = undefined;
    while (true) {
        // readSliceShort reads bytes into a buffer and
        // returns the number of bytes read.
        const n = try r.readSliceShort(&bytes);
        if (n == 0)
            break;

        // Print each byte as a hex number.
        for (bytes[0..n]) |byte|
            print("{x:02} ", .{byte});

        // Add some padding.
        for (n..8) |_|
            print("   ", .{});
        print("    ", .{});

        // Print the bytes as ASCII.
        for (bytes[0..n]) |byte|
            print("{c}", .{
                if (printable(byte)) byte else '.',
            });
        print("\n", .{});
    }
}

fn printable(byte: u8) bool {
    return '!' <= byte and byte <= '~';
}
$ echo "Hello, world!" > hello
$ zig run binary.zig 
48 65 6c 6c 6f 2c 20 77     Hello,.w
6f 72 6c 64 21 0a           orld!.

Writing to a file

The second example just writes 64 bytes, with values from 0 to 63.

const std = @import("std");

pub fn main(init: std.process.Init) !void {
    const io = init.io;

    const cwd = std.Io.Dir.cwd();
    var file = try cwd.createFile(io, "hello", .{});
    var buf: [4096]u8 = undefined;
    var writer = file.writerStreaming(io, &buf);
    var w = &writer.interface;

    // Prepare a buffer with the data.
    var data: [64]u8 = undefined;
    for (&data, 0..) |*b, n|
        b.* = @intCast(n);

    try w.writeAll(&data);

    // Don’t forget to flush!
    try writer.flush();
}

We’ll run it and print the file using the first example:

$ zig run binary-2.zig 
$ zig run binary.zig 
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 19 1a 1b 1c 1d 1e 1f     ........
20 21 22 23 24 25 26 27     .!"#$%&'
28 29 2a 2b 2c 2d 2e 2f     ()*+,-./
30 31 32 33 34 35 36 37     01234567
38 39 3a 3b 3c 3d 3e 3f     89:;<=>?

Next example: Comptime.