无法在C++程序中获取Linux'dd'命令的输出

无法在C++程序中获取Linux'dd'命令的输出

问题描述:

我试图使用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://*.com/questions/5431941/why-is-while-feof-file -always-wrong) – molbdnilo

+1

如果从命令行运行该命令,那么输出结果会是你期望的吗?我非常怀疑它,因为命令只会转储原始二进制数据。原始的二进制数据不能像文本一样处理。 –

+0

另外,你为什么要把读取循环放在'try-catch'中?唯一可能导致异常的情况是,如果在附加到字符串的同时内存不足。即使如此,程序终止也会关闭管道,所以没有实际需要。 –

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,作为无符号值