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]});
}
}