Read Directory Contents With Zig
Efficiently Reading Directory Contents in Zig with a Page Allocator
Hey there welcome back to my Zig series, the language that I’ve been using a lot lately for my hobby projects. It’s a language that keeps evolving and I’m excited to share more about it with you. I personally find it an absolute joy to work with and hope I can awake some interest in you the reader as well and perhaps even turn you to the zig side.
In this article, we’ll check out how to read the contents of a directory in Zig, the zig way by using allocators. For our purposes we’ll be using the std.heap.page_allocator
which is the most basic allocator that zig comes with. We could further optimize this if we wanted to also allow recursive directory reading, but for now we’ll keep it simple.
Understanding the Basics of Directory Management
Before we jump into the code, let’s clarify what we’re trying to achieve. Directories are foundational to file systems. They allow us to organize files hierarchically, making it easier to navigate and manage data. When working with file systems, you’ll often need to read the contents of a directory for tasks like file management, data processing, displaying a list of files to the user, or for your various CLI programs that you might be writing.
The Power of Zig
Zig stands out among modern programming languages due to its simplicity and low-level control. With explicit memory management and a focus on safety and performance, Zig provides developers the tools needed for efficient system programming. The language allows for direct interaction with the file system, making it an excellent choice for tasks like reading directory contents.
The Code
This is the complete code block with comments on how to read the contents of a directory in Zig using the page allocator.
const std = @import("std");
pub fn main() !void {
// Define the allocator
const allocator = std.heap.page_allocator;
// Open the current working directory as an iterable directory
var dir = try std.fs.cwd().openIterableDir(".", .{});
defer dir.close();
// Create an ArrayList to hold the file names
var file_list = std.ArrayList([]const u8).init(allocator);
defer file_list.deinit();
// Iterate through the directory contents
var dirIterator = dir.iterate();
while (try dirIterator.next()) |dirContent| {
// Append the file name to the ArrayList
try file_list.append(dirContent.name);
}
// Print the contents of the ArrayList
const stdout = std.io.getStdOut().writer();
for (file_list.items) |file_name| {
try stdout.print("File: {s}\n", .{file_name});
}
}
Now let’s break down the code:
- At the very tippy top we define the allocator we want to use, in this case the page allocator.
- We then open the current working directory as an iterable directory. the
openIterableDir
function takes in two parameters, the first is subDir which like the name suggests allows you to open a subdirectory of the current working directory, and the second is a set of flags which we are not using in this case. - We then create an
ArrayList
to hold the file names, this is a dynamic array that can grow and shrink as needed. - We use the allocator to initialize the
ArrayList
and then defer the deinit function to free the memory when the function exits. - We then iterate through the directory contents using the
dirIterator
and append the file names to theArrayList
. - Finally, we print the contents of the
ArrayList
to the standard output.
And that’s it! You’ve successfully read the contents of a directory in Zig using the page allocator.
if you wish to learn more about the page allocator or any other allocator that zig comes with, feel free to check out my article on Zig Allocators Explained.
Conclusion
Thank you for taking your time and reading the article till the end. I hope you’ve learnt something new and exciting and that you may consider using or learning Zig in the future. If you have any questions or feedback feel free to reach out to me on Twitter.