如何使用 fstream (C++) 将十六进制值读入整数
How to read hex values into integer with fstream (C++)
我正在尝试从二进制文件中读取一个小端十六进制字符串,并将该值放入一个整数中以使用它。当我尝试阅读时,我得到的不是数字,而是 ascii 符号。我已经尝试过 cast 和 atoi,但似乎没有任何效果。使用 fstream 将文件中的十六进制字符串读入整数的最佳方法是什么?
这基本上是我的程序:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
fstream input;
fstream output;
char cbuffer[4];
char revbuffer[8];
input.open(argv[1], fstream::binary | fstream::in);
output.open("output.txt", ios::out | ios::app);
input.seekg(16, input.beg);
input.read(cbuffer, 4);
cout << sizeof(revbuffer) << endl;
cout << cbuffer[0] << cbuffer[1] << cbuffer[2] << cbuffer[3] << endl;
}
如果它是以二进制格式存储的整数值,我猜它要么是 int32_t
要么是 uint32_t
。由于您提到该值以小端字节顺序存储,我猜您想确保主机 运行 您的程序转换它(如果需要)。 C++20 有 std::endian。如果这对您不可用,通常可以使用宏来检测编译时的字节序,而不是我使用的 std::endian
测试。我假设该值是下面的 uint32_t
。
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <type_traits> // std::endian
// little endian unsigned 32 bit integer to host byte order
inline uint32_t Le32toh(uint32_t le) {
#if __cplusplus <= 201703L
// run-time check
static constexpr uint16_t endian = 1;
if(*reinterpret_cast<const uint8_t*>(&endian)==1) return le;
#else
// compile-time check
static_assert(std::endian::native == std::endian::little || std::endian::native == std::endian::big);
if constexpr (std::endian::native == std::endian::little) return le;
#endif
const uint8_t* c=reinterpret_cast<const uint8_t*>(&le);
return // little-to-big endian conversion
(static_cast<uint32_t>(c[0])<<24) |
(static_cast<uint32_t>(c[1])<<16) |
(static_cast<uint32_t>(c[2])<<8) |
(static_cast<uint32_t>(c[3]));
return le;
}
int main(int argc, char* argv[]) {
std::vector<std::string> args(argv+1, argv+argc);
std::fstream output("output.txt", std::ios::out | std::ios::app);
uint32_t cbuffer;
for(const auto& file : args) {
std::fstream input(file, std::fstream::binary | std::fstream::in);
input.seekg(16, input.beg);
// read directly into the varibles memory
input.read(reinterpret_cast<char*>(&cbuffer), 4);
// output the value unconverted
std::cout << std::hex << cbuffer << "\n";
// convert if needed
cbuffer = Le32toh(cbuffer);
// output the value converted
std::cout << std::hex << cbuffer << "\n";
}
}
我正在尝试从二进制文件中读取一个小端十六进制字符串,并将该值放入一个整数中以使用它。当我尝试阅读时,我得到的不是数字,而是 ascii 符号。我已经尝试过 cast 和 atoi,但似乎没有任何效果。使用 fstream 将文件中的十六进制字符串读入整数的最佳方法是什么?
这基本上是我的程序:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
fstream input;
fstream output;
char cbuffer[4];
char revbuffer[8];
input.open(argv[1], fstream::binary | fstream::in);
output.open("output.txt", ios::out | ios::app);
input.seekg(16, input.beg);
input.read(cbuffer, 4);
cout << sizeof(revbuffer) << endl;
cout << cbuffer[0] << cbuffer[1] << cbuffer[2] << cbuffer[3] << endl;
}
如果它是以二进制格式存储的整数值,我猜它要么是 int32_t
要么是 uint32_t
。由于您提到该值以小端字节顺序存储,我猜您想确保主机 运行 您的程序转换它(如果需要)。 C++20 有 std::endian。如果这对您不可用,通常可以使用宏来检测编译时的字节序,而不是我使用的 std::endian
测试。我假设该值是下面的 uint32_t
。
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <type_traits> // std::endian
// little endian unsigned 32 bit integer to host byte order
inline uint32_t Le32toh(uint32_t le) {
#if __cplusplus <= 201703L
// run-time check
static constexpr uint16_t endian = 1;
if(*reinterpret_cast<const uint8_t*>(&endian)==1) return le;
#else
// compile-time check
static_assert(std::endian::native == std::endian::little || std::endian::native == std::endian::big);
if constexpr (std::endian::native == std::endian::little) return le;
#endif
const uint8_t* c=reinterpret_cast<const uint8_t*>(&le);
return // little-to-big endian conversion
(static_cast<uint32_t>(c[0])<<24) |
(static_cast<uint32_t>(c[1])<<16) |
(static_cast<uint32_t>(c[2])<<8) |
(static_cast<uint32_t>(c[3]));
return le;
}
int main(int argc, char* argv[]) {
std::vector<std::string> args(argv+1, argv+argc);
std::fstream output("output.txt", std::ios::out | std::ios::app);
uint32_t cbuffer;
for(const auto& file : args) {
std::fstream input(file, std::fstream::binary | std::fstream::in);
input.seekg(16, input.beg);
// read directly into the varibles memory
input.read(reinterpret_cast<char*>(&cbuffer), 4);
// output the value unconverted
std::cout << std::hex << cbuffer << "\n";
// convert if needed
cbuffer = Le32toh(cbuffer);
// output the value converted
std::cout << std::hex << cbuffer << "\n";
}
}