2017-04-04 133 views
0

我試圖使用sudo dd if=/dev/sda ibs=1 count=64 skip=446命令從主引導記錄獲取分區表信息以解析它我基本上試圖讀取輸出到一個字符串,以解析它,但我得到的是以下內容:� !。我很期待是:無法在C++程序中獲取Linux'dd'命令的輸出

80 01 01 00 83 FE 3F 01 3F 00 00 00 43 7D 00 00 00 00 01 02 83 FE 3F 0D 82 7D 00 00 0C F1 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

我當前的代碼看起來是這樣的,而且是剛剛從這裏取:How to execute a command and get output of command within C++ using POSIX?

#include <iostream> 
#include <stdexcept> 
#include <stdio.h> 
#include <string> 

using namespace std; 

string exec(const char* cmd) { 
    char buffer[128]; 
    string result = ""; 
    FILE* pipe = popen(cmd, "r"); 
    if (!pipe) throw std::runtime_error("popen() failed!"); 
    try { 
     while (!feof(pipe)) { 
      if (fgets(buffer, 128, pipe) != NULL) 
       result += buffer; 
     } 
    } catch (...) { 
     pclose(pipe); 
     throw; 
    } 
    pclose(pipe); 
    return result; 
} 

int main() { 

    string s = exec("sudo dd if=/dev/sda ibs=1 count=64 skip=446"); 
    cout << s; 

} 

很顯然,我做錯了什麼,但我可以」找出問題所在。我如何獲得正確的輸出到我的字符串?

+0

順便說一句,你應該閱讀[爲什麼是「while(!feof(file))」總是錯的?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file -always-wrong) – molbdnilo

+1

如果從命令行運行該命令,那麼輸出結果會是你期望的嗎?我非常懷疑它,因爲命令只會轉儲原始二進制數據。原始的二進制數據不能像文本一樣處理。 –

+0

另外,你爲什麼要把讀取循環放在'try-catch'中?唯一可能導致異常的情況是,如果在附加到字符串的同時內存不足。即使如此,程序終止也會關閉管道,所以沒有實際需要。 –

回答

0
while (!feof(pipe)) { 

這是your first bug

result += buffer; 

這是你的第二個bug。 buffer是一個char陣列,在這種情況下衰減到char *。如您所知,字符串上下文中的char *通常會被解釋爲由'\0'字節終止的C風格字符串。

您可能已經注意到,您希望獲得一堆讀取的00字節。那麼,在char陣列衰減到char *之後,到第一個00字節的所有內容都會附加到result而不是128字節。如果在這128個字節中沒有00字節,那麼您可能最終會得到一些隨機垃圾,作爲額外的獎勵,並且可能性很小。

if (fgets(buffer, 128, pipe) != NULL) 

這是你的第三個錯誤。如果讀取數據碰巧包含0A字節,即'\n'字符,則不會讀取128個字節。

cout << s; 

這是你的第四個錯誤。由於數據將(在所有其他錯誤都修復後)大概包含二進制內容,因此您的終端不太可能成功顯示各種字節,特別是字節001F

要解決你的代碼,你需要:

  1. 正確處理檔案結尾的條件。

  2. 正確讀取二進制數據。 fgets()等,完全不適合這項任務。如果你堅持使用C文件結構,你唯一合理的選擇是使用fread()

  3. 正確地從一個二進制數據blob組裝一個std::string。僅僅附加一個char緩衝區,穿過你的手指,並希望最好的,將無法正常工作。您很可能需要使用兩個參數std::string構造函數,它將開始和結束迭代器值作爲參數。

  4. 正確顯示二進制數據,而不是像剛剛那樣將整個blob轉儲到std::cout。最常用的方法是操縱器std::hex,並且將每個char努力上變換爲int,作爲無符號值

相關問題