How can I read a file in zig, and run over it line by line?
I did found os.File.openRead, but it seems old cause it says that  container 'std.os' has no member called 'File'.
How can I read a file in zig, and run over it line by line?
I did found os.File.openRead, but it seems old cause it says that  container 'std.os' has no member called 'File'.
std.io.reader.readUntilDelimiterOrEof lets your read any std.io.reader line by line. You usually get the reader of something like a file by calling it’s reader() method. So for example:
var file = try std.fs.cwd().openFile("foo.txt", .{});
defer file.close();
var buf_reader = std.io.bufferedReader(file.reader());
var in_stream = buf_reader.reader();
var buf: [1024]u8 = undefined;
while (try in_stream.readUntilDelimiterOrEof(&buf, '\n')) |line| {
    // do something with line...
}
The std.io.bufferedReader isn’t mandatory but recommended for better performance.
I muddled through this by looking at the Zig library source/docs, so this might not be the most idiomatic way:
const std = @import("std");
pub fn main() anyerror!void {
    //  Get an allocator
    var gp = std.heap.GeneralPurposeAllocator(.{ .safety = true }){};
    defer _ = gp.deinit();
    const allocator = &gp.allocator;
    // Get the path
    var path_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
    const path = try std.fs.realpath("./src/main.zig", &path_buffer);
    // Open the file
    const file = try std.fs.openFileAbsolute(path, .{ .read = true });
    defer file.close();
    // Read the contents
    const buffer_size = 2000;
    const file_buffer = try file.readToEndAlloc(allocator, buffer_size);
    defer allocator.free(file_buffer);
    // Split by "\n" and iterate through the resulting slices of "const []u8"
    var iter = std.mem.split(file_buffer, "\n");
    var count: usize = 0;
    while (iter.next()) |line| : (count += 1) {
        std.log.info("{d:>2}: {s}", .{ count, line });
    }
}
The above is a little demo program that you should be able to drop into the default project created from zig init-exe, it'll just print out it's own contents, with a line number.
You can also do this without allocators, provided you supply the required buffers.
I'd also recommend checking out this great resource: https://ziglearn.org/chapter-2/#readers-and-writers
Note: I'm currently running a development version of Zig from master (reporting 0.9.0), but I think this has been working for the last few official releases.
To open a file and get a file descriptor back
std.os.open
https://ziglang.org/documentation/0.6.0/std/#std;os.open
To read from the file
std.os.read
https://ziglang.org/documentation/0.6.0/std/#std;os.read
I can't find a .readlines() style function in the zig standard library. You'll have to write your own loop to find the \n characters.
Below is a test case that shows how to create a file, write to it then open the same file and read its content.
const std = @import("std");
const testing = std.testing;
const expect = testing.expect;
test "create a file and then open and read it" {
    var tmp_dir = testing.tmpDir(.{}); // This creates a directory under ./zig-cache/tmp/{hash}/test_file
    // defer tmp_dir.cleanup(); // commented out this line so, you can see the file after execution finished.
    var file1 = try tmp_dir.dir.createFile("test_file", .{ .read = true });
    defer file1.close();
    const write_buf: []const u8 = "Hello Zig!";
    try file1.writeAll(write_buf);
    var file2 = try tmp_dir.dir.openFile("test_file", .{});
    defer file2.close();
    const read_buf = try file2.readToEndAlloc(testing.allocator, 1024);
    defer testing.allocator.free(read_buf);
    try testing.expect(std.mem.eql(u8, write_buf, read_buf));
}
Check out fs package tests on Github or on your local machine under <zig-install-dir>/lib/fs/test.zig.
Also note that test allocator only works for tests. In your actual source code you need to choose an appropriate allocator.