我该如何在C++中创建一个十六进制转储实用程序?

7
基本上,我需要使用C++编写一个十六进制转储实用程序。它将看起来像这样: 使用Visual Studio的Word文档十六进制转储的一部分 (使用Visual Studio的Word文档十六进制转储的一部分)
我想提示用户输入文件名,然后显示十六进制值以及转换后的ASCII字符。我还不太熟悉处理二进制文件,所以如果您能简单明了地解释一下,那将不胜感激。

1
你想知道如何读取文件或将字节值显示为十六进制字符字符串吗?还是你想让别人为你编写那个程序? - Stefan Falk
第二件事。我知道如何读取文件,但是一旦我有了二进制文件,我不知道如何使用它。 - user2430692
2个回答

25
因为每一行显示了相同数据块的两个不同“视图”,实现这一目标的实用方法是将整行数据读入缓冲区。有了缓冲区中的字节,您可以按照自己的需求格式化输出行。
对于每一行输出,您需要在缓冲区上循环两次:一次以十六进制代码输出数据,一次以字符形式输出数据。
这是一个简单的演示,它只从标准输入中读取数据,并以与您展示的大致相同的格式输出。请在此处尝试一下。
#include <cctype>
#include <iostream>
#include <iomanip>

int main()
{
    const int ROW_SIZE = 16;        // Number of bytes per row
    const int GROUP_SIZE = 8;       // Number of bytes for each hex group
    unsigned long address = 0;

    std::cout << std::hex << std::setfill('0');
    while (std::cin.good())
    {
        // Read up to ROW_SIZE bytes
        int nread;
        char buf[ROW_SIZE];
        for (nread = 0; nread < ROW_SIZE && std::cin.get(buf[nread]); nread++);
        if (nread == 0) break;

        // Show the address
        std::cout << std::setw(8) << address;

        // Show the hex codes
        for (int i = 0; i < ROW_SIZE; i++)
        {
            if (i % GROUP_SIZE == 0) std::cout << ' ';
            if (i < nread)
                std::cout << ' ' << std::setw(2) << (unsigned int)(unsigned char)buf[i];
            else
                std::cout << "   ";
        }

        // Show printable characters
        std::cout << "  ";
        for (int i = 0; i < nread; i++)
        {
            std::cout << (std::isprint(buf[i]) ? buf[i] : '.');
        }

        std::cout << "\n";
        address += ROW_SIZE;
    }
}

输入

Hello there, this is a test binary file.
What do you think?

.

输出

00000000  48 65 6c 6c 6f 20 74 68  65 72 65 2c 20 74 68 69  Hello there, thi
00000010  73 20 69 73 20 61 20 74  65 73 74 20 62 69 6e 61  s is a test bina
00000020  72 79 20 66 69 6c 65 2e  0a 57 68 61 74 20 64 6f  ry file..What do
00000030  20 79 6f 75 20 74 68 69  6e 6b 3f 0a 0a 2e         you think?...

啊,好的,所以你需要使用缓冲区。谢谢你的帮助。 - user2430692
c 是什么?-- 只是一个吉祥物吗?;-) - Wolf
这段代码取决于默认的char类型是有符号还是无符号的。 - Wolf

0
#include <iostream>
#include <vector>
#include <iomanip>
#include <numeric>

template<typename byte_type = std::uint8_t, typename container_type = std::vector<std::vector<byte_type>>>
container_type arrange_bytes(const byte_type* buffer, const std::size_t size, const std::size_t w = 16) {
  return std::accumulate(buffer, buffer + size, container_type{{}}, [w](auto& acc, const byte_type byte) {
    if(acc.back().size() >= w) {
      acc.push_back({});
    }
    acc.back().push_back(byte);
    return acc;
  });
}

std::string init_text_row(const int offset) {
  std::ostringstream ost{};
  ost << std::hex << std::setfill('0') << std::setw(8) << offset;
  return ost.str();
}

template<typename byte_type = std::uint8_t>
std::string format_row(const std::vector<byte_type>& bytes, const int offset) {
  auto init = init_text_row(offset);
  return std::accumulate(bytes.begin(), bytes.end(), init, [](auto& acc, const auto& byte) {
      std::ostringstream ost{};
      ost  << ' ' << std::hex << std::setfill('0') << static_cast<unsigned>(byte);
      return acc + ost.str();
  });
}

template<typename byte_type = std::uint8_t, typename container_type = std::vector<std::vector<byte_type>>>
std::string format_bytes(const container_type& bytes) {
  struct memory {
    std::string data = {};
    int offset = 0;
  };
  return std::accumulate(bytes.begin(), bytes.end(), memory{}, [](auto& acc, const auto& row) {
    acc.data += format_row(row, acc.offset) + '\n';
    acc.offset += row.size();
    return acc;
  }).data;
}

template<typename byte_type = std::uint8_t>
std::string hexdump(const byte_type* buffer, std::size_t size) {
  return format_bytes(arrange_bytes(buffer, size));
}

#include <cstring>

int main() {
  const auto* message = "Hello, world! I am Simon the Sourcerer and I am a mighty pirate!";
  const auto len = std::strlen(message);
  std::cout << hexdump(message, len) << std::endl;
  return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接