#Read a file into a std.ArrayList(std.ArrayList(u8))
1 messages · Page 1 of 1 (latest)
so I did this
var wrote = false;
while (try file.reader().readUntilDelimiterOrEofAlloc(allocator, '\n', std.math.maxInt(usize))) |line| {
defer allocator.free(line);
try std.fs.cwd().writeFile("x.txt", line);
wrote = true;
var arr = std.ArrayList(u8).init(allocator);
errdefer arr.deinit();
try arr.appendSlice(line);
try tab.buf.append(arr);
}
if (!wrote) {
try tab.buf.append(std.ArrayList(u8).init(allocator));
}
}```
i don't see any reason to use a list of lists. maybe use a list of slices
const std = @import("std");
test {
const allocator = std.testing.allocator;
const file = try std.fs.cwd().openFile("/tmp/tmp.zig", .{});
var lines = std.ArrayList([]const u8).init(allocator);
defer {
for (lines.items) |line| allocator.free(line);
lines.deinit();
}
while (try file.reader().readUntilDelimiterOrEofAlloc(allocator, '\n', std.math.maxInt(u32))) |line| {
try lines.append(line);
}
for (lines.items) |line| std.debug.print("line={s}\n", .{line});
}
for an editor
where I will be constantly changing bytes on each line
oh ok let me adjust it...
it seemed a little rude for me, please ask next time instead of instantly sending a solution
it's just me, you weren't rude
seems like for an editor, you'd want to re-use the memory as much as possible?
i'll be maybe writing my own arraylist later
and optimize it later
i just want it working first
i think this does a decent job of re-using memory. i'm sure it could be improved, but maybe its interesting
const std = @import("std");
test {
const allocator = std.testing.allocator;
const file = try std.fs.cwd().openFile("/tmp/tmp.zig", .{});
var lines = std.ArrayList(std.ArrayListUnmanaged(u8)).init(allocator);
defer {
for (lines.items) |*line| line.deinit(allocator);
lines.deinit();
}
// simulate reading the file a few times
for (0..5) |_| {
try file.seekTo(0);
var linei: usize = 0;
while (true) : (linei += 1) {
// re-use existing line if available
const line = if (linei < lines.items.len) blk: {
lines.items[linei].clearRetainingCapacity();
break :blk &lines.items[linei];
} else blk: {
const newline = try lines.addOne();
newline.* = .{};
break :blk newline;
};
// std.debug.print("linei={} lines={}/{} line={*}\n", .{ linei, lines.items.len, lines.capacity, lines.items.ptr });
file.reader().streamUntilDelimiter(line.writer(allocator), '\n', null) catch |e| switch (e) {
error.EndOfStream => break,
else => return e,
};
}
lines.items.len = linei;
}
for (lines.items) |line| std.debug.print("line={s}\n", .{line.items});
}
streamUntilDelimiter() is pretty nice for this
i think this line is necessary for when the previous lines were longer than current lines: lines.items.len = linei;
and i chose to use std.ArrayList(std.ArrayListUnmanaged(u8)) so that the inner lists can be a little smaller - don't need to store the allocator field for every line.