I’m working on Advent of Code 2025 with Zig, and my first order of business was to come up with a repeatable way for me to store my input files and fetch their contents. So I zig init’d my project directory, created an input folder in the root of it, and now store my input files there where each file is just a .txt file with its name as the day, i.e. 1.txt.
The problem I’m having is related to how I create the file path. I’m using std.fmt.bufPrint to take the day number as input, convert it from u8 to a u8, and append “.txt” to it so I can feed it to openFile. bufPrint fills the input buffer with the formatted text and also returns what was formatted as a slice. What I would intuitively prefer is to just use the actual buffer as my file path:
const cwd: std.fs.Dir = std.fs.cwd();
var input_dir = cwd.openDir("input", .{}) catch |err| {...};
defer input_dir.close();
var file_path: [7:0]u8 = std.mem.zeroes([7:0]u8); // length 7 to account for max u8 digits + ".txt"
_ = std.fmt.bufPrint(&file_path, "{d}.txt", .{day}) catch |err| {...};
const file = input_dir.openFile(&file_path, .{ .mode = .read_only }) catch |err| {...};
defer file.close();
But this fails due to a BadPathName error from openFile. I can make this work by coercing file_path to a [5]u8 by changing &file_pathto file_path[0..5] where I call openFile. That’s obviously not wise because the moment I have a 2-digit day in the path it’ll break. The more straightforward version of the whole thing looks like this:
const cwd: std.fs.Dir = std.fs.cwd();
var input_dir = cwd.openDir(“input”, .{}) catch |err| {…};
defer input_dir.close();
var path_buf: []u8 = undefined;
const file_path = std.fmt.bufPrint(&path_buf, “{d}.txt”, .{day}) catch |err| {…};
const file = input_dir.openFile(file_path, .{ .mode = .read_only }) catch |err| {…};
defer file.close();
This whole exercise leaves me with two questions:
- Is that simplified example the more Zig-idiomatic version of what I’m trying to do? It just seems like a waste to use a slice when I allocated a buffer specifically, but maybe I’m overthinking it and there’s not really any waste since it’s still just a slice of that buffer at the end of the day.
- Is
openFilenot using a sentinel-value slice/array appropriately? Or am I just making a bad assumption of how it ought to work?
/edit: Forgot to mention I’m on Windows, which impacts paths quite a bit