Writes, Syscalls, and Buffering

std.debug.print will flush the output to stderr.
But with stdout write, I believe you need to call flush on your own.

I thought about it, but no, that was not the reason.

os.write(line[0..]);

works as needed.

1 Like

But it’s kinda strange… why does not compiler complain about os.write(line)?..

When I change the relevant line of your program to os.write(line); it works fine for me.

Did you try to pipe in the same file as out? Because this won’t work:

./snip-line 3 < in.txt > in.txt

It’s just going to erase your text file.

Hmm… now os.write(line) works for me too.
Probably, I did something wrong before.

No, I did not do this:

$ history | grep "/skip-line"
 2279  cd ../skip-line/
 2282  ./skip-line 
 2285  ./skip-line 
 2286  ./skip-line 3 in.txt 
 2287  ./skip-line 3 < in.txt 
 2289  ./skip-line 3 < in.txt > out.txt
 2293  ./skip-line 3 < in.txt > out.txt
 2295  ./skip-line 3 < in.txt > out.txt
 2297  ./skip-line 3 < in.txt
 2301  ./skip-line 3 < in.txt > ooo
 2303  ./skip-line 3 < in.txt > ooo
 2305  ./skip-line 3 < in.txt > ooo
 2306  ./skip-line 1 < in.txt > ooo
 2307  ./skip-line 5 < in.txt > ooo
 2308  ./skip-line 7 < in.txt > ooo
 2310  ./skip-line 7 < in.txt > ooo
 2312  ./skip-line 7 < in.txt > ooo
 2314  ./skip-line 7 < in.txt > ooo
 2317  ./skip-line 2 < in.txt > bbb
 2321  ./skip-line 3 < a.txt > b.txt
 2324  ./skip-line 5 < a.txt > c.txt
 2327  ./skip-line 4 < a.txt > d.txt
 2330  ./skip-line 4 < a.txt > d.txt
 2332  ./skip-line 3 < a.txt > out.txt

But I didn’t do < a > a, see history above.

Probably you were right.
The point is that initially I had buffered writer:

//    var o = std.io.getStdOut();
//    var os = o.writer();

    var o = std.io.getStdOut();
    var bw = std.io.bufferedWriter(o.writer());
    var os = bw.writer();

With this buffered writer output file is always empty regardless of write() arguments (buf[0..line.len], line[0..], line). I just was lazy to search where flush is sitting in the std lib, switched to unbuffered “mode” and did not realize that it was the change that made the program work correctly, but not playing with write() arguments.

But still… I thought that upon program exit output file will be closed and flushed automatically… nope, this does not happen.

1 Like

There was a good discussion awhile back about why Zig doesn’t do that.

wait… what has this to do with Zig?..
here we have redirections handled by a shell (bash in my case).
when a launched program exits, all open files are closed (fd 2 in this case)
and when a file is closed, OS should flush pending write ops, shouldn’t it?

I would even say “should”, yes, but they don’t, at least the POSIX-y ones don’t. I did think, for that reason, that you were referring to Zig adding this behavior, sorry about that.

I think there’s some sort of use-mention confusion happening here.

1 Like

Ok, where is that flush() living in all those fancy reader/writer interfaces?

1 Like

A BufferedWriter has a flush() method. It should be possible to open fds in line-buffered mode, but I’ve never done this, a userspace buffer is fine with me.

You can find details in std.fs.File. If you’re interested in opening a file handle in line buffered form, what you need will be in there.

Note

I tested it again with system call write. And it was flushed well.

TBH, I personally very seldom use fopen()/fread()/fwrite()/fclose buffered wrappers, instead I prefer open()/read()/write()/close().

I got it:

    var o = std.io.getStdOut();
    var bw = std.io.bufferedWriter(o.writer());
    var os = bw.writer();

    var buf: [1024]u8 = undefined;
    var cnt: u32 = 0;
    while (try is.readUntilDelimiterOrEof(&buf, '\n')) |line| {
        cnt += 1;
        if (cnt == ln) continue;
        std.debug.print("line #{}\n", .{cnt});
        // _ = try os.write(buf[0..line.len]);
        // _ = try os.write(line[0..]);
        _ = try os.write(line);
        _ = try os.write("\n");
    }
    try bw.flush();

works fine.

But it’s a bit brain out for me, I’d expect all ops to be available in the result of std.io.getStdOut();

1 Like

see also this comment

1 Like

I guess the Zig no hidden control flow ideal again? Flush seems like should be available on the Writer interface if it is expected. I do hope that it is at least consistent between OSes.

Be nice for the next person and flush before you exit. :stuck_out_tongue: