在C++;? 我在网上搜索了一个C++中读取二进制文件的方法,我发现了两种工作模式:
第一:在C++;? 我在网上搜索了一个C++中读取二进制文件的方法,我发现了两种工作模式:,c++,io,C++,Io,第一: #include <iostream> #include <fstream> int main(int argc, const char *argv[]) { if (argc < 2) { ::std::cerr << "Usage: " << argv[0] << "<filename>\n"; return 1; } ::std::ifstream in(arg
#include <iostream>
#include <fstream>
int main(int argc, const char *argv[])
{
if (argc < 2) {
::std::cerr << "Usage: " << argv[0] << "<filename>\n";
return 1;
}
::std::ifstream in(argv[1], ::std::ios::binary);
while (in) {
char c;
in.get(c);
if (in) {
// ::std::cout << "Read a " << int(c) << "\n";
printf("%X ", c);
}
}
return 0;
}
第2条:
xxd/tmp/test.bed的结果
:
0000000: 6c1b 01dc 0fe7 0f6b 01 l......k.
ls-l/tmp/test.bed的结果
-rw-rw-r-- 1 user user 9 Nov 3 16:37 test.bed
第二种方法是在开始时给出正确的十六进制代码,但似乎文件大小有误,第一种方法是弄乱字节
这些方法看起来非常不同,也许在C++中有很多方法可以做同样的事情?有专业人士采用的习惯用法吗?在第一种情况下,您打印的是有符号的字符,而在第二种情况下,您打印的是无符号字符X将字符扩展为整数,这导致了差异。在将char
对象作为整数值处理之前,您当然希望将它们转换为无符号char
!问题是char
可能会被签名,在这种情况下,当您强制转换负值时,负值会转换为负值int
s。显示为十六进制的负int
s将有两个以上的十六进制数字,前导数字可能都是“f”
我没有立即发现第二种方法的尺寸错误的原因。但是,C++读取二进制文件的方法很简单:
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
std::vector<unsigned char> bytes;
{
std::ifstream in(name, std::ios_base::binary);
bytes.assign(std::istreambuf_iterator<char>(in >> std::noskipws),
std::istreambuf_iterator<char>());
}
std::cout << std::hex << std::setfill('0');
for (int v: bytes) {
std::cout << std::setw(2) << v << ' ';
}
#包括
#包括
#包括
#包括
std::向量字节;
{
std::ifstream-in(名称,std::ios\u base::binary);
字节分配(std::istreambuf_迭代器(在>>std::noskipws中),
std::istreambuf_迭代器();
}
STD::CUT< P>两种方法都是C和C++的奇怪混合(实际上,第二种是普通C);尽管如此,第一种方法基本上是正确的,但是您必须为c
使用无符号字符,否则超过0x7f的任何字节都将被读取为负数,这将导致错误的输出。1
要以“C++方式”正确操作,您应该执行以下操作:
std::cout<<std::hex<<std::setfill('0');
...
if (in)
std::cout << std::setw(2)<<int(c) << "\n";
std::cout在搜索@Roland Illig的答案(现在已删除)不起作用的原因时,我找到了以下解决方案,不确定是否符合专业标准,但它给出了正确的结果,并允许检查文件的开头n字节:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
int main(int argc, const char *argv[])
{
if (argc < 3) {
::std::cerr << "usage: " << argv[0] << " <filename>\n";
return 1;
}
int nbytes = std::stoi(argv[2]);
char buffer[nbytes];
std::streamsize size = nbytes;
std::ifstream readingFile(argv[1], std::ios::binary);
readingFile.read(buffer, (int)size);
std::streamsize bytesread = readingFile.gcount();
unsigned char rawchar;
if (bytesread > 0) {
for (int i = 0; i < bytesread; i++) {
rawchar = (unsigned char) buffer[i];
printf("%02x ", (int) rawchar);
}
printf("\n");
}
return 0;
}
#包括
#包括
#包括
#包括
int main(int argc,const char*argv[]
{
如果(argc<3){
::标准::cerr=0)
{
printf(“%02x”,当前字节);
currentByte=inBinaryFile.get();
}
printf(“\n”);
inBinaryFile.close();
返回0;
}
C++有点混淆,C++使用位移位操作符来指定一个选项。我发现代码非常冗长。它永久修改了<代码> STD::CUT的输出格式。如果格式化恢复了代码,代码看起来会是什么样子?它看起来像是代码> iOSXBase<代码>是一个子类,<代码> iOS/COD>,BATW有什么不同?即使是ios::binary
和ios\u base::binary
?或者,也许我弄错了,ios
是ios\u base
的一个子类,因此继承了binary
?@RolandIllig:考虑到整个二进制文件的输出非常强大,我会认为类似于std::ostream fmt(0);fmt.copyfmt(std::cout);…;std::cout.copyfmt(fmt);
可能是合理的。由于格式化标志是本地功能,我认为没有必要恢复它们(stdio甚至没有粘性格式化标志的概念)@RolandIllig:如前所述:是的,设置的格式标志将保持原样。但是,如果你关心事物的格式,你最好根据具体需要在本地设置格式标志:已经设置的格式标志是一些随机组合,无论最后设置在何处都很有用。事实上e sticky是IOStreams中如何实现格式化标志的副产品,它不希望您全局设置标志并使用它们!您可以根据本地需要设置格式化标志。尽管您当然可以使用setf()
要设置字段的各种标志,我认为使用相应的操纵器要容易得多,例如,std::cout@DietmarKühl:我倾向于避免使用流操纵器,我从来都不知道哪一个是“粘性的”,我已经被这些东西咬了好几次。现在我终于查到了,但是宽度
被随机重置了,想想看。这就是为什么,如果可能的话,我试图完全避开std流,它们的设计充满了缺陷,特别是“执行不力的雄心勃勃的想法”类别。(#1 sin:希望对这个问题有更多的解释:
#include <iostream>
#include <fstream>
#include <vector>
#include <iomanip>
std::vector<unsigned char> bytes;
{
std::ifstream in(name, std::ios_base::binary);
bytes.assign(std::istreambuf_iterator<char>(in >> std::noskipws),
std::istreambuf_iterator<char>());
}
std::cout << std::hex << std::setfill('0');
for (int v: bytes) {
std::cout << std::setw(2) << v << ' ';
}
std::cout<<std::hex<<std::setfill('0');
...
if (in)
std::cout << std::setw(2)<<int(c) << "\n";
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
int main(int argc, const char *argv[])
{
if (argc < 3) {
::std::cerr << "usage: " << argv[0] << " <filename>\n";
return 1;
}
int nbytes = std::stoi(argv[2]);
char buffer[nbytes];
std::streamsize size = nbytes;
std::ifstream readingFile(argv[1], std::ios::binary);
readingFile.read(buffer, (int)size);
std::streamsize bytesread = readingFile.gcount();
unsigned char rawchar;
if (bytesread > 0) {
for (int i = 0; i < bytesread; i++) {
rawchar = (unsigned char) buffer[i];
printf("%02x ", (int) rawchar);
}
printf("\n");
}
return 0;
}
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, const char* argv[])
{
ifstream inBinaryFile;
inBinaryFile.open(argv[1], ios_base::binary);
int currentByte = inBinaryFile.get();
while(currentByte >= 0)
{
printf("%02x ", currentByte);
currentByte = inBinaryFile.get();
}
printf("\n");
inBinaryFile.close();
return 0;
}