Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C++;? 我在网上搜索了一个C++中读取二进制文件的方法,我发现了两种工作模式:_C++_Io - Fatal编程技术网

在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;
}