Akka.Net文件IO - 仅处理文件的前n个字节

时间:2018-05-17 14:06:06

标签: akka-stream akka.net

我有一个非常简单的流来处理文件 - 只有一个FileIO.FromFile来源,一个直通流和一个Last接收器:

    var source = FileIO.FromFile(new FileInfo(fileName));

    var flow = Flow.FromFunction<ByteString, ByteString>(x =>
    {
       Log.Info(x.Count.ToString());
       return x;
    });

    var sink = Sink.Last<ByteString>();

    var runnable = source.Via(flow).ToMaterialized(sink, Keep.Right);
    var result = runnable.Run(Context.Materializer()).Result;

流按预期运行:记录器捕获字节串大小,直到文件源完全耗尽。

现在,我将接收器改为使用第一而不是最后

    var source = FileIO.FromFile(new FileInfo(fileName));

    var flow = Flow.FromFunction<ByteString, ByteString>(x =>
    {
       Log.Info(x.Count.ToString());
       return x;
    });

    var sink = Sink.First<ByteString>();

    var runnable = source.Via(flow).ToMaterialized(sink, Keep.Right);
    var result = runnable.Run(Context.Materializer()).Result;

“First”的文档声明“在接收到一个元素后取消”,我认为这意味着接收器发出信号取消流,这将关闭源。但是当这个流运行时,会发生两件事。

1)我收到以下调试日志消息

[DEBUG][17/05/2018 13:55:16][Thread 0004][akka://Demo/user/DATReader/StreamSupervisor-0/Flow-0-1-fileSource] Unhandled message from akka://Demo/user/DATReader/StreamSupervisor-0/Flow-0-0-unknown-operation : Akka.Streams.Actors.Cancel

2)文件被锁定,因此任何进一步的读取尝试都会因访问被拒绝异常而失败。

我也尝试在源上使用Take(1),但也可以看到相同的效果。

我的问题是:如何只读取文件中的前n个字节并优雅地关闭流,以便释放任何锁(由FileIO.FromFile获取)?

1 个答案:

答案 0 :(得分:0)

就我而言,没有这种错误。尝试使用sharedKillSwitch来控制完成。有关此处的文档Dynamic stream handling

            var sharedKillSwitch = KillSwitches.Shared("my-kill-switch");
            var source = FileIO.FromFile(new FileInfo(fileName), chunkSize: 1024)
                    .Via(sharedKillSwitch.Flow<ByteString>());

            var sink = Sink.First<ByteString>();

            var runnable = source.Select(x => {                 
                Log.Info(x.Count.ToString());
                sharedKillSwitch.Shutdown();
                return x;
            })
            .ToMaterialized(sink, Keep.Right);

            var result = runnable.Run(materializer).Result;