Skip to main content
  1. Posts/

Reading from files using buffers in Zig

definitepotato
Author
definitepotato
Code slinger, golang, ziglang, grokking life, tabletop games enthusiast, obsession with keebs and numbers.
Table of Contents

Let’s explore reading lines from a file in zig. We’ll do this with and without buffers. To explore these code snippets create a file named example.txt with any content you want. In a previous post about writing to files we talked about what buffers are, why they’re useful, and the impact they have on performance and resources.

Read file in chunks using a buffer on the stack
#

const std = @import("std");

pub fn main() !void {
var buffer: [4096]u8 = undefined;

    const file = try std.fs.cwd().openFile("example.txt", .{});
    defer file.close();

    while (true) {
        const bytes_read = try file.read(&buffer);
        if (bytes_read == 0) break; // End of file.

        const chunk = buffer[0..bytes_read];
        std.debug.print("{s}", .{chunk});
    }
}

Read all lines of a file at once using a buffer on the stack
#

const std = @import("std");

pub fn main() !void {
  var buffer: [4096]u8 = undefined;

  const file = try std.fs.cwd().openFile("example.txt", .{});
  defer file.close();

  const bytes_read = try file.readAll(&buffer);
  const content = buffer[0..bytes_read];

  std.debug.print("{s}\n", .{content});
}

Read all lines of a file using an allocator
#

const std = @import("std");

pub fn main() !void {
  var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
  defer arena.deinit();
  const allocator = arena.allocator();

  const content = try std.fs.cwd().readFileAlloc(
      allocator,
      "example.txt",
      1024 * 1024
  );

  std.debug.print("{s}\n", .{content});
}

Read a file byte by byte with no allocations
#

const std = @import("std");

pub fn main() !void {
    var file = try std.fs.cwd().openFile("example.txt", .{});
    defer file.close();

    var read_buf: [512]u8 = undefined;
    var file_reader = file.reader(&read_buf);
    const reader: *std.Io.Reader = &file_reader.interface;

    // Read byte by byte
    while (true) {
        const byte_slice = reader.take(1) catch |err| switch (err) {
            error.EndOfStream => break,
            else => return err,
        };
        std.debug.print("{c}", .{byte_slice[0]});
    }
}

Related