I would like to avoid making a set size buffer because of things like a file being too big, or small enough that there is empty space in the buffer. An ArenaAllocator
sounds promising since you can allocate more space as needed. Is there a "proper" way to do this, i.e. load a .json file passed as a command line argument into a buffer?
Asked
Active
Viewed 3,574 times
3

steamsy
- 104
- 1
- 8
4 Answers
2
How can you create a buffer of the same size as a file?
You can request file's size and allocate the same amount of memory:
var file = try std.fs.cwd().openFile("file.txt", .{ open = true }));
const file_size = (try file.stat()).size;
var buffer = try allocator.alloc(u8, file_size);
Then you can read the file by using readNoEof
:
try file.reader().readNoEof(buffer);
Alternatively, you can use File
's readToEndAlloc
function:
const size_limit = std.math.maxInt(u32); // or any other suitable limit
var result = try file.readToEndAlloc(allocator, size_limit);

sigod
- 3,514
- 2
- 21
- 44
-
On master 0.9.0 I had to replace `.{ open = true }` with `std.fs.O_RDONLY` but this probably works for stable – steamsy Dec 03 '21 at 04:39
-
1If the file is available at compile time, you could use the `@embedFIle` function: https://ziglang.org/documentation/master/#embedFile – Dave Mason Feb 19 '22 at 15:56
1
using GeneralPurposeAllocator
. you can learn more about allocators in https://youtu.be/vHWiDx_l4V0
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = &gpa.allocator;
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
const file = try std.fs.cwd().openFile(args[1], .{});
const file_content = try file.readToEndAlloc(allocator, 1024 * 1024); // 1MB max read size
defer allocator.free(file_content);
std.debug.print("{s}", .{file_content});
}

Ali Chraghi
- 613
- 6
- 16
1
On 0.10.0-dev.2345+9747303d1, here's what worked for me:
const std = @import("std");
pub fn main() !void {
var file = try std.fs.cwd().openFile("test.ts", .{ .mode = .read_only });
const file_size = (try file.stat()).size;
const allocator = std.heap.page_allocator;
var buffer = try allocator.alloc(u8, file_size);
try file.reader().readNoEof(buffer);
std.debug.print("{s}\n", .{buffer});
}
OpenFlags
for .openFile
is defined here:
https://github.com/ziglang/zig/blob/master/lib/std/fs/file.zig#L80

Lawrence Chen
- 11
- 1
- 1
1
None of the answers worked for me in Zig today sine a few interfaces changed (e.g. allocator -> allocator()). Here is what worked for me (Dec 2022):
const std = @import("std");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = &gpa.allocator();
var file = try std.fs.cwd().openFile("./sample.txt", .{});
const file_content = try file.readToEndAlloc(allocator.*, 10 * 1024 * 1024); // 10MB read
defer allocator.free(file_content);
std.debug.print("{s}", .{file_content});
}

Benjamin Gruenbaum
- 270,886
- 87
- 504
- 504