Readers and Writers
std.io.Writer
and
std.io.Reader
provide standard ways of making use of IO. std.ArrayList(u8) has a writer
method which gives us a writer. Let's use it.
const std = @import("std");
const expect = std.testing.expect;
const eql = std.mem.eql;
const ArrayList = std.ArrayList;
const allocator = std.testing.allocator;
test "io writer usage" {
var list: ArrayList(u8) = .empty;
defer list.deinit(allocator);
try list.print(allocator, "Hello {s}!", .{"World"});
try expect(eql(u8, list.items, "Hello World!"));
}
Here we will use a reader to copy the file's contents into an allocated buffer.
The second argument of
readAllAlloc
is the maximum size that it may allocate; if the file is larger than this, it
will return error.StreamTooLong.
const std = @import("std");
const expect = std.testing.expect;
const eql = std.mem.eql;
const test_allocator = std.testing.allocator;
test "io reader usage" {
const message = "Hello File!";
const file = try std.fs.cwd().createFile(
"junk_file2.txt",
.{ .read = true },
);
defer file.close();
try file.writeAll(message);
try file.seekTo(0);
var file_buffer: [1024]u8 = undefined;
var file_reader = file.reader(&file_buffer);
const contents = try file_reader.interface.readAlloc(
test_allocator,
message.len,
);
defer test_allocator.free(contents);
try expect(eql(u8, contents, message));
}
A common usecase for readers is to read until the next line (e.g. for user
input). Here we will do this with the
std.fs.File.stdin()
file.
const std = @import("std");
const expect = std.testing.expect;
const eql = std.mem.eql;
test "read until next line" {
var stdout_buf: [1024]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buf);
const stdout: *std.io.Writer = &stdout_writer.interface;
var stdin_buf: [1024]u8 = undefined;
var stdin_reader = std.fs.File.stdin().reader(&stdin_buf);
const stdin: *std.io.Reader = &stdin_reader.interface;
try stdout.writeAll("Enter your name\n");
try stdout.flush();
const bare_line = try stdin.takeDelimiter('\n') orelse unreachable;
const line = std.mem.trim(u8, bare_line, "\r");
try stdout.print("Your name is: \"{s}\"\n", .{line});
try stdout.flush();
}