在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