从Process.StandardOutput中捕获二进制输出

15 浏览
0 Comments

从Process.StandardOutput中捕获二进制输出

在C#(在SuSE上运行的Mono 2.8下的.NET 4.0)中,我想要运行一个外部批处理命令,并以二进制形式捕获其输出。我使用的外部工具叫做'samtools'(samtools.sourceforge.net),除其他功能外,它可以从一个索引的二进制文件格式(称为BAM)中返回记录。

我使用Process.Start来运行外部命令,并且我知道可以通过重定向Process.StandardOutput来捕获其输出。问题是,这是一个带有编码的文本流,所以它不能给我访问输出的原始字节的权限。我找到的几乎可行的解决方案是访问底层流。

以下是我的代码:

        Process cmdProcess = new Process();
        ProcessStartInfo cmdStartInfo = new ProcessStartInfo();
        cmdStartInfo.FileName = "samtools";
        cmdStartInfo.RedirectStandardError = true;
        cmdStartInfo.RedirectStandardOutput = true;
        cmdStartInfo.RedirectStandardInput = false;
        cmdStartInfo.UseShellExecute = false;
        cmdStartInfo.CreateNoWindow = true;
        cmdStartInfo.Arguments = "view -u " + BamFileName + " " + chromosome + ":" + start + "-" + end;
        cmdProcess.EnableRaisingEvents = true;
        cmdProcess.StartInfo = cmdStartInfo;
        cmdProcess.Start();
        // 准备读取每个比对(二进制)
        var br = new BinaryReader(cmdProcess.StandardOutput.BaseStream);
        while (!cmdProcess.StandardOutput.EndOfStream)
        {
            // 消耗初始的、未记录的BAM数据
            br.ReadBytes(23);

// ... 更多的解析接下来

但是当我运行这段代码时,我读取的前23个字节并不是输出中的前23个字节,而是几百或几千个字节下游的某个位置。我猜想StreamReader做了一些缓冲,所以底层流已经提前说4K进入了输出。底层流不支持返回到开头。

我被困在这里。有人有一个可以运行外部命令并以二进制形式捕获其stdout的工作解决方案吗?输出可能非常大,所以我希望能够流式传输它。

任何帮助将不胜感激。

顺便说一下,我目前的解决方法是让samtools以文本格式返回记录,然后解析它们,但这相当慢,我希望通过直接使用二进制格式来加快速度。

0