【问题标题】:C++ Convert the binary data read from a file to a char pointerC++ 将从文件读取的二进制数据转换为 char 指针
【发布时间】:2020-11-24 15:29:03
【问题描述】:

我正在尝试实现将从文件中读取的二进制内容连续转换为字节。 我的文件samplefile.bin 包含 16bytes ,这是二进制的形式。在Hexed.it 中会这样显示。

在这种情况下,我需要以十六进制格式提取这些二进制值并将其存储到char *

我将在这里发布我的示例代码。

#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>

using namespace std;

int main()
{
   uint8_t *ptr;
   long size;
   ifstream file ("samplefile.bin", ios::in|ios::binary|ios::ate);
   size = file.tellg();
   std::vector<uint8_t> memblock(size);
   file.seekg (0, ios::beg);
   file.read(reinterpret_cast<char*>(&memblock[0]), size);
   file.close();
   ptr = new uint8_t[size];
   int z=0;
   for(int i=0; i < memblock.size(); i++)
   {
     std::cout << memblock.at(i) << ' ';
     z=memblock.at(i)&0xff;
     ptr[i] = z;
   }

   cout<<"Output"<<endl;
   for (int i=0;i<memblock.size();i++)
   {
       cout<<ptr[i];
   }
   delete []ptr;

return 0;

}

我希望将ptr 传递给其他函数。但是这个 print cout&lt;&lt;ptr[i]&lt;&lt;endl; 的输出如下所示,这意味着转换没有发生。

╠ ↕ ‼ ¶ ╙ O N ╥ í * : J Z [ \ J

我想要类似下面的东西

ptr[0] = 0xCC
ptr[1] = 0x12
...
ptr[15] = 0x4A

当我给出这样的 cout&lt;&lt;(int)ptr[i]&lt;&lt;endl; 时,我得到 0xCC 的十进制值作为 204 和其他打印相同的东西。

我已经提到了C++ read binary file and convert to hexConvert binary file to hex notation。我没有找到确切的解决方案,因为在这两个链接中他们将其转换为字符串。我的意图不是这个。

我提到了这个How properly to read data from binary file to char array,它看起来和我的很相似。但这并没有解决我的问题。
我希望这个 0xCC 作为单个字节,这应该存储到 ptr[0] 和其他值类似

如何解决这个问题?我在这里错过了什么吗?我是 C++ 新手,请帮我解决这个问题

感谢您的努力。

【问题讨论】:

  • cout &lt;&lt; "ptr[" &lt;&lt; std::dec &lt;&lt; i &lt;&lt; "]: " &lt;&lt; std::hex &lt;&lt; (int)ptr[i] &lt;&lt; '\n';

标签: c++ file hex binary-data char-pointer


【解决方案1】:

读取文件并将其数据复制到字符向量。 您可以使用 iomanip 之类的 std::hex 或 std::uppercase 将整数值打印为十六进制。

不建议分配原始指针并将其传递给另一个函数。只需传递一个 char 向量或使用 unique_ptr,它们将防止您出现内存问题。

#include <iostream>
#include <iomanip>

std::ifstream file("samplefile.bin", ios::binary);
auto mem = std::vector<char>(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
for (char c : mem)
{
    std::cout << std::uppercase << std::hex << static_cast<int>(c) << endl;
}

【讨论】:

  • 将向量的引用(如果可能,为常量)传递给函数。避免按值传递大对象。
  • 你的第二行应该被修改以避免分配。您可以使用范围构造函数。您还可以使用 CTAD 和默认初始化程序。修改为 --> std::vector mem(std::istreambuf_iterator&lt;char&gt;(file),{});
  • 感谢您的回答。函数原型已经定义,我们无法更改它。这就是为什么我要求将内容复制到char *
  • Armin,感谢你,我学习了更好的代码。 Vishun,你可以考虑从 istreambuf 迭代器到你的原始指针的 std::copy()。
  • @Amin 第二行在 C++14 中不执行赋值(甚至在启用优化的 C++11 中也不执行)。使用auto 完全没问题。
【解决方案2】:

您的代码中存在多个问题,最根本的是您似乎希望std::byte8_t 在输入到输出流时默认表示为十六进制转储。不是这种情况。您需要明确告诉流为您执行必要的格式化。如果您想存储该表示,您还需要存储流式传输的结果。

条条大路通罗马,不幸的是,C++ 标准 IO 流库并没有使处理字节流非常符合人体工程学。但这里有一种方法:

#include <cstdint>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <vector>

using byte = std::uint8_t;

auto read_bytes(std::istream& is, std::vector<byte>& bytes) -> std::istream& {
    return is.read(& reinterpret_cast<char&>(bytes[0]), bytes.size());
}

auto hexdump(std::vector<byte> const& bytes) -> std::string {
    auto ostr = std::ostringstream();
    ostr << std::uppercase << std::hex << std::setw(2) << std::setfill('0');
    for (auto const c : bytes) {
        ostr << int{c};
    }
    return ostr.str();
}

int main(int argc, char** argv) {
    if (argc != 2) return 1;

    auto fs = std::ifstream(argv[1], std::ios_base::binary | std::ios_base::ate);
    auto const size = fs.tellg();
    fs.seekg(0);
    auto buffer = std::vector<byte>(size);
    if (not read_bytes(fs, buffer)) return 1;

    std::cout << hexdump(buffer) << "\n";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    • 2019-12-03
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    相关资源
    最近更新 更多