如何在Zig中从函数返回Writer和Reader?

huangapple go评论48阅读模式
英文:

How to Return a Writer and a Reader from a function in zig?

问题

我正在创建一个简单的程序,它从文件中读取数据然后处理该文件。

我看到了一个读取文件的模式,使用了 std.io.bufferedReaderstd.io.fixedBufferStream().writer()

所以我正在尝试创建一个函数来返回Writer和Reader两者。

为了做到这一点,我试图创建一个结构体,其中字段的类型是 std.io.Writerstd.io.Reader,但它们是返回类型而不是实际类型。

那么,我该如何创建它?

我的当前代码如下:

const std = @import("std");

const BufferedWriterAndReader = struct {
    writer: std.io.Writer,
    reader: std.io.Reader,
};

fn getBufferedWriterAndReader(path: []u8) BufferedWriterAndReader {
    var file = try std.fs.cwd().openFile(path, .{});
    defer file.close();
    var buf_reader = std.io.bufferedReader(file.reader());
    var file_reader = buf_reader.reader();

    var lines: [256]u8 = undefined;
    var lines_buf = std.io.fixedBufferStream(&lines);
    var lines_writer = lines_buf.writer();
    return BufferedWriterAndReader{
        .writer = lines_writer,
        .reader = file_reader,
    };
}

pub fn main() !void {
    getBufferedWriterAndReader("strategy.txt");
}

(Note: I've removed HTML escape codes for special characters to provide a cleaner translation.)

英文:

I'm creating a simple program that reads from a file and then process that file.

I saw a pattern for reading using a std.io.bufferedReader and std.io.fixedBufferStream().writer()

So I'm trying to create a function to return both Writer and Reader.

For doing such thing I'm trying to create a struct which the fields are from type std.io.Writer and std.io.Reader but they are functions that return the type and not an actual type.

So, how can I create it?

My current looks like:

const std = @import("std");

const BufferedWriterAndReader = struct {
    writer: std.io.Writer,
    reader: std.io.Reader,
};

fn getBufferedWriterAndReader(path: []u8) BufferedWriterAndReader {
    var file = try std.fs.cwd().openFile(path, .{});
    defer file.close();
    var buf_reader = std.io.bufferedReader(file.reader());
    var file_reader = buf_reader.reader();

    var lines: [256]u8 = undefined;
    var lines_buf = std.io.fixedBufferStream(&lines);
    var lines_writer = lines_buf.writer();
    return BufferedWriterAndReader{
        .writer = lines_writer,
        .reader = file_reader,
    };
}

pub fn main() !void {
    getBufferedWriterAndReader("strategy.txt");
}

答案1

得分: 1

你在这里尝试的做法由于不同的原因而行不通:

var file = try std.fs.cwd().openFile(path, .{});
defer file.close();

你在函数结束时关闭了文件,因此读取/写入文件的读者/写者将无法继续操作文件。

buf_readerlines_buf 也位于栈上或使用栈内存,因此它们在函数调用结束时会无效。

所以我建议你退一步,重新思考你实际想要在这里做什么。例如,如果你只想要一个简单的解决方案,不关心性能,可以将整个文件读取到堆上(file.readToEndAlloc())。

现在来实际回答你的问题:

你可以在编译时检查值的类型。因此,你可以这样查询确切的类型:

@compileLog(@TypeOf(lines_writer));
@compileLog(@TypeOf(file_reader));

(现在这些的结果看起来很复杂。鉴于 Zig 没有内置继承,没有简化这些类型的简单方法。)

英文:

What you are trying to do here won't work for different reasons:

    var file = try std.fs.cwd().openFile(path, .{});
    defer file.close();

You are closing the file at the end of the function. Therefor the reader/writer won't be able to read/write to the file anymore.

The buf_reader, lines_buf also sit on the stack/use stack memory, so they get invalidated at the end of the function call.

So I would suggest that you take a step back and rethink what you actually want to do here. For example if you just want a simple solution and don't care about performance, just read the entire file onto the heap (file.readToEndAlloc())

Now to actually answer your question:

You can check out the type of a value at compile-time. So you could just do this to query the exact type:

    @compileLog(@TypeOf(lines_writer));
    @compileLog(@TypeOf(file_reader));

(Now the results of that will look complicated. And there is no easy way to simplify the types given that zig has no builtin inheritance)

huangapple
  • 本文由 发表于 2023年6月21日 23:31:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76524944.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定