【发布时间】:2011-05-07 19:05:41
【问题描述】:
在 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();
// 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);
// ...更多解析如下
但是当我运行它时,我读取的前 23 个字节不是输出中的前 23 个字节,而是下游的几百或几千个字节。我假设 StreamReader 做了一些缓冲,所以底层流已经提前了,比如说 4K 进入输出。底层流不支持寻回起点。
我被困在这里了。有没有人有运行外部命令并以二进制形式捕获其标准输出的有效解决方案?输出可能非常大,所以我想流式传输它。
任何帮助表示赞赏。
顺便说一句,我目前的解决方法是让 samtools 以文本格式返回记录,然后解析这些记录,但这很慢,我希望直接使用二进制格式来加快速度。
【问题讨论】:
-
我唯一能想到的就是将所需的编码设置为 Unicode,然后将 StreamReader 中的每个字符分成两个字节。这将是一个可怕的黑客攻击,如果输出的字节数为奇数,可能会惨遭失败。一种解决方法是实现您自己的编码,将字节直接映射到它们各自的 char 值,如 ASCII,但不将上限转换为“?”。但我会让别人想出一个正确的答案。 :)
-
事实发生 10 年后,但是当 Process 实例为 OutputDataReceived 事件做好准备时,您的数据是否正在被使用和处理?我自己正在寻找它,但我认为 Process 类不能用于捕获二进制数据,因此。