C++ 如何从文件创建 byte[] 数组(我不是说逐字节读取文件)?

标签 c++ file visual-c++ byte

我有一个问题,我自己无法解决,也无法在任何地方找到答案。我有一个文件包含这样一个字符串:

01000000d08c9ddf0115d1118c7a00c04

我想以这种方式手动读取文件:

char fromFile[] =
"\x01\x00\x00\x00\xd0\x8c\x9d\xdf\x011\x5d\x11\x18\xc7\xa0\x0c\x04";

如果有任何帮助,我将不胜感激。

我想用 C++ 来做(最好是 vc++)。

谢谢!

最佳答案

int t194(void)
{
   // imagine you have n pair of char, for simplicity, 
   // here n is 3 (you should recognize them)
   char pair1[] = "01"; // note:
   char pair2[] = "8c"; //   initialize with 3 char c-style strings
   char pair3[] = "c7"; //

   {
      // let us put these into a ram based stream, with spaces
      std::stringstream ss;
      ss << pair1 << " " << pair2 << " " << pair3;

      // each pair can now be extracted into
      // pre-declared int vars
      int i1 = 0;
      int i2 = 0;
      int i3 = 0;

      // use formatted extractor to convert
      ss >> i1 >> i2 >> i3;

      // show what happened (for debug only)
      std::cout << "Confirm1:"  << std::endl;
      std::cout << "i1: " << i1 << std::endl;
      std::cout << "i2: " << i2 << std::endl;
      std::cout << "i3: " << i3 << std::endl << std::endl;

      // output is:
      // Confirm1:
      // i1: 1
      // i2: 8
      // i3: 0
      // Shucks, not correct.
      // We know the default radix is base 10
      // I hope you can see that the input radix is wrong,
      // because c is not a decimal digit, 
      // the i2 and i3 conversions stops before the 'c'
   }

   // pre-delcare
   int i1 = 0;
   int i2 = 0;
   int i3 = 0;
   {
      // so we try again, with radix info added
      std::stringstream ss;
      ss << pair1 << " " << pair2 << " " << pair3; 
      // strings are already in hex, so we use them as is

      ss >> std::hex  // change radix to 16
         >> i1 >> i2 >> i3;

      // now show what happened
      std::cout << "Confirm2:"  << std::endl;
      std::cout << "i1: " << i1 << std::endl;
      std::cout << "i2: " << i2 << std::endl;
      std::cout << "i3: " << i3 << std::endl << std::endl;

      // output now:
      // i1: 1
      // i2: 140
      // i3: 199
      // not what you expected?  Though correct, 
      // now we can see we have the wrong radix for output

      // add output radix to cout stream
      std::cout << std::hex  // add radix info here!
                << "i1: " << i1 << std::endl
                // Note: only need to do once for std::cout
                << "i2: " << i2 << std::endl
                << "i3: " << i3 << std::endl << std::endl
                << std::dec;

      // output now looks correct, and easily comparable to input
      // i1: 1
      // i2: 8c
      // i3: c7

      // So: What next?
      //     read the entire string of hex input into a single string
      //     separate this into pairs of chars (perhaps using    
      //       string::substr())
      //     put space separated pairs into stringstream ss
      //     extract hex values until ss.eof()
      //     probably should add error checks
      // and, of course, figure out how to use a loop for these steps
      //
      // alternative to consider:
      //   read 1 char at a time, build a pairing, convert, repeat 
   }



   //
   // Eventually, you should get far enough to discover that the
   // extracts I have done are integers, but you want to pack them
   // into an array of binary bytes.
   //
   // You can go back, and recode to extract bytes (either 
   // unsigned char or uint8_t), which you might find interesting.
   //
   // Or ... because your input is hex, and the largest 2 char
   // value will be 0xff, and this fits into a single byte, you
   // can simply static_cast them (I use unsigned char)

   unsigned char bin[] = {static_cast<unsigned char>(i1),
                          static_cast<unsigned char>(i2),
                          static_cast<unsigned char>(i3) };

   // Now confirm by casting these back to ints to cout
   std::cout << "Confirm4:  "
             << std::hex << std::setw(2) << std::setfill('0')
             << static_cast<int>(bin[0]) << " "
             << static_cast<int>(bin[1]) << " "
             << static_cast<int>(bin[2]) << std::endl;

   // you also might consider a vector (and i prefer uint8_t)
   // because push_back operations does a lot of hidden work for you
   std::vector<uint8_t>  bytes;
   bytes.push_back(static_cast<uint8_t>(i1));
   bytes.push_back(static_cast<uint8_t>(i2));
   bytes.push_back(static_cast<uint8_t>(i3));

   // confirm
   std::cout << "\nConfirm5:  ";
   for (size_t i=0; i<bytes.size(); ++i)
      std::cout << std::hex << std::setw(2) << std::setfill(' ')
                << static_cast<int>(bytes[i]) << " ";
   std::cout << std::endl;

注意:bytes 或 char 的 cout(或 ss)可能会令人困惑,并不总是给出您可能期望的结果。我的背景是嵌入式软件,而且我在使字节流 i/o 工作方面的经验少得惊人。只是说这在处理流 i/o 时往往会使我的工作产生偏差。

   // other considerations:
   //
   // you might read 1 char at a time.  this can simplify
   //    your loop, possibly easier to debug
   //    ... would you have to detect and remove eoln?  i.e.  '\n'
   //    ... how would you handle a bad input 
   //        such as not hex char, odd char count in a line
   //
   // I would probably prefer to use getline(),
   //    it will read until eoln(), and discard the '\n'
   //    then in each string, loop char by char, creating char pairs, etc.
   //
   // Converting a vector<uint8_t> to char bytes[] can be an easier
   //    effort in some ways.  A vector<> guarantees that all the values
   //    contained are 'packed' back-to-back, and contiguous in
   //    memory, just right for binary stream output
   //
   //    vector.size() tells how many chars have been pushed
   //
   // NOTE: the formatted 'insert' operator ('<<') can not
   //       transfer binary data to a stream.  You must use
   //       stream::write() for binary output.
   //
   std::stringstream ssOut;

   // possible approach:
   // 1 step reinterpret_cast 
   // - a binary block output requires "const char*"

   const char* myBuff = reinterpret_cast<const char*>(&myBytes.front());

   ssOut.write(myBuff, myBytes.size()); 
   // block write puts binary info into stream

   // confirm
   std::cout << "\nConfirm6:  ";

   std::string s = ssOut.str();  // string with binary data

   for (size_t i=0; i<s.size(); ++i)
   {
      // because binary data is _not_ signed data, 
      // we need to 'cancel' the sign bit
      unsigned char ukar = static_cast<unsigned char>(s[i]); 

      // because formatted output would interpret some chars 
      //   (like null, or \n), we cast to int
      int  intVal = static_cast<int>(ukar);  

      // cast does not generate code

      // now the formatted 'insert' operator 
      // converts and displays what we want
      std::cout << std::hex << std::setw(2) << std::setfill('0') 
                << intVal << " ";
   }
   std::cout << std::endl;
   //
   //
   return (0);
} // int t194(void)

关于C++ 如何从文件创建 byte[] 数组(我不是说逐字节读取文件)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30647571/

相关文章:

c++ - 在 Turbo C++ 3.0 的 16 位 Dos 5 上使用 inp()

c++ - 如何从 C++ 中的可变参数模板类派生

c++ - C++使用WaitForMultipleObjects检测完成哪个线程

file - awk 将单个文件分成具有特定文件名的多个文件

visual-c++ - 如何使用stdext::hash_map?

c++ - 如何编辑 Qvector 中 Qvector 的内容

java - 寻找用于目录同步的java库

java - 可执行 JAR 文件问题?

Windows 结构的 C++

c++ - C/C++ 应用程序的新手设计注意事项