I was working through some bugs I found in a previous attempt of mine to read files line-by-line. The solution below seems to remedy the problems I was having, but I wanted a second set of eyes on this to see if I've overlooked anything (the buffer size of 1 was simply testing my case where the buffer was too small, I usually have it as 4096):
const std = @import("std");
pub fn main() !void {
var read_pos: u64 = 0;
try readFileLines(std.heap.smp_allocator, "foo.txt", &read_pos);
}
pub fn readFileLines(alloc: std.mem.Allocator, file_name: []const u8, read_pos: *u64) !void {
const fs_file: std.fs.File = try std.fs.cwd().openFile(file_name, .{});
const stats = try fs_file.stat();
try fs_file.seekTo(read_pos.*);
var buffer: [1]u8 = undefined;
var reader = fs_file.reader(&buffer);
var writer = std.io.Writer.Allocating.init(alloc);
defer writer.deinit();
outer: while (read_pos.* < stats.size) {
writer.clearRetainingCapacity();
while (true) {
const res = reader.interface.takeDelimiterInclusive('\n') catch |err| {
switch (err) {
error.EndOfStream => break :outer,
error.StreamTooLong => {
const buf = reader.interface.buffer;
if (buf.len == 0) return error.StreamTooLong;
try writer.writer.writeAll(buf);
_ = try reader.interface.discard(.limited(buf.len));
read_pos.* += buf.len;
continue;
},
else => return err,
}
};
try writer.writer.writeAll(res);
read_pos.* += res.len;
break;
}
const line = try writer.toOwnedSlice();
if (line.len == 0) break;
std.log.err("line: {s}", .{line});
}
}