在C#中(在SuSE上运行在Mono 2.8下的.NET 4.0),我想运行一个外部批处理命令并以二进制形式捕获它的输出。我使用的外部工具称为“samtools”(samtools.sourceforge.net),除此之外它还可以从名为BAM的索引二进制文件格式返回记录。从Process.StandardOutput捕获二进制输出
我使用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();
// Prepare to read each alignment (binary)
var br = new BinaryReader(cmdProcess.StandardOutput.BaseStream);
while (!cmdProcess.StandardOutput.EndOfStream)
{
// Consume the initial, undocumented BAM data
br.ReadBytes(23);
// ...详细解析如下
但是当我运行这一点,我读的第一23bytes不在输出中的第一个23个字节,但而是下游数百或千字节的某处。我假设StreamReader做了一些缓冲,所以底层流已经提前说4K输出。底层的流不支持回到起点。
而我卡在这里。有没有人有工作的解决方案来运行外部命令并以二进制形式捕获它的stdout?输出可能非常大,所以我想流式传输。
任何帮助表示赞赏。顺便说一句,我目前的解决方法是让samtools以文本格式返回记录,然后解析这些记录,但这很慢,我希望通过直接使用二进制格式来加快速度。
我能想到的唯一一件事情就是将所需的编码设置为Unicode,然后将StreamReader中的每个字符分隔为两个字节。这将是一个可怕的黑客攻击,如果输出的奇数字节可能会惨败。解决方法是实现自己的编码,将字节直接映射到它们各自的char值,如ASCII,但不将上面的集合转换为'?'。但我会让其他人拿出正确的答案。 :) – cdhowie 2010-11-10 18:17:30