2012-08-05 66 views
0

二进制文件,我想读\写它具有以下结构的二进制文件:读写在结构C++

enter image description here

该文件由“记录”组成。每个 “RECORD” 具有以下结构:我将使用第一记录如实施例

  • (红色)START字节:0x5A(始终为1个字节,固定值0x5A)
  • (绿色)LENGTH字节:0×00 0x16 (始终为2个字节,值可以改变从“0×00 0×02”到 “0xFF的为0xFF”)
  • (蓝色)含量: 长度字段的十进制值减2

在指示字节数这种情况LENGHT字段值是22(0x00 0x16转换为十进制),因此CONTENT将包含20(22 - 2)个字节。 我的目标是逐一读取每条记录,并将其写入输出文件。其实我有读取功能和写入功能(有些伪代码):

private void Read(BinaryReader binaryReader, BinaryWriter binaryWriter) 
{ 
    byte START = 0x5A; 
    int decimalLenght = 0; 
    byte[] content = null; 
    byte[] length = new byte[2]; 

    while (binaryReader.PeekChar() != -1) 
    { 
     //Check the first byte which should be equals to 0x5A 
     if (binaryReader.ReadByte() != START) 
     { 
      throw new Exception("0x5A Expected"); 
     } 

     //Extract the length field value 
     length = binaryReader.ReadBytes(2); 

     //Convert the length field to decimal 
     int decimalLenght = GetLength(length); 

     //Extract the content field value 
     content = binaryReader.ReadBytes(decimalLenght - 2); 

     //DO WORK 
     //modifying the content 

     //Writing the record 
     Write(binaryWriter, content, length, START); 
    } 
} 

private void Write(BinaryWriter binaryWriter, byte[] content, byte[] length, byte START) 
{ 
    binaryWriter.Write(START); 
    binaryWriter.Write(length); 
    binaryWriter.Write(content); 
} 

正如你可以看到我已经写了C#,但我真的不知道如何将它与C++。 有人可以请指出我在正确的方向吗?

回答

0

谢谢你这一切是解决我能下发展:

// TestCPP003.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 

#include "boost\program_options.hpp" 
namespace po = boost::program_options; 

#include "Util.h" 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    po::options_description desc("Allowed options"); 

    desc.add_options() 
     ("h", "produce help message") 
     ("i", po::value<string>(), "input file") 
     ("o", po::value<string>(), "output file"); 

    po::variables_map vm; 
    po::store(po::parse_command_line(argc, argv, desc), vm); 

    if (vm.count("h")) 
    { 
     cout << desc << endl; 
     return 0; 
    } 

    po::notify(vm); 

    if (vm.count("i")) 
    { 
     cout << vm["i"].as<string>() << "\n"; 
    } 

    string sInputFile = vm["i"].as<string>(); 

    if (fileExists(sInputFile.c_str())) 
    { 
     cout << "file exists: <" << sInputFile << ">" << endl; 
    } 
    else 
    { 
     cout << "file not exists: <" << sInputFile << ">" << endl; 
     cout << "RETURN CODE: 8" << endl; 
     return 8; 
    } 

    string sOutputFile = vm["o"].as<string>(); 

    static const int START_BYTE = '\x5a'; 
    static const int AFP_RECORD_HEADER_SIZE = 1; 
    static const int AFP_RECORD_LENGTH_SIZE = 2;  
    char * afpHeaderBlock = new char[1]; 
    char * afpLengthBlock; 
    unsigned int afpRecordLength = 0; 
    char * afpContentBlock; 

    ifstream inputStream(sInputFile, ios::in|ios::binary); 
    ofstream outputStream(sOutputFile, ios::out|ios::binary); 

    if (inputStream.is_open() && outputStream.is_open()) 
    { 
     while (inputStream.read(afpHeaderBlock, AFP_RECORD_HEADER_SIZE)) 
     {   
      //cout << ToHex(string(afpHeaderBlock, AFP_RECORD_HEADER_SIZE), true) << endl; 

      if (START_BYTE == afpHeaderBlock[0]) 
      { 
       cout << "0x5A Found!" << endl; 
      } 
      else 
      { 
       cout << "0x5A not Found! - AFP Error" << endl; 
      } 

      outputStream.write(afpHeaderBlock, AFP_RECORD_HEADER_SIZE); 

      afpLengthBlock = new char[AFP_RECORD_LENGTH_SIZE]; 
      afpRecordLength = 0; 

      inputStream.read(afpLengthBlock, AFP_RECORD_LENGTH_SIZE); 

      //cout << ToHex(string(afpLengthBlock, AFP_RECORD_LENGTH_SIZE), true) << endl; 

      afpRecordLength = (afpRecordLength << 8) + static_cast<const unsigned char&>(afpLengthBlock[0]); 
      afpRecordLength = (afpRecordLength << 8) + static_cast<const unsigned char&>(afpLengthBlock[1]); 

      //cout << "AFP Record Length: " << afpRecordLength << endl; 

      outputStream.write(afpLengthBlock, AFP_RECORD_LENGTH_SIZE); 

      afpContentBlock = new char[afpRecordLength - AFP_RECORD_LENGTH_SIZE]; 

      inputStream.read (afpContentBlock, afpRecordLength - AFP_RECORD_LENGTH_SIZE); 

      outputStream.write(afpContentBlock, afpRecordLength - AFP_RECORD_LENGTH_SIZE); 
     } 

     inputStream.close(); 
     outputStream.flush(); 
     outputStream.close(); 
    } 

    cout << "RETURN CODE: 0" << endl; 
    return 0; 
} 
3

您需要使用std::ifstream并打开binary modestd::ios_base::binary)中的文件。

peek非常相似,但如果不能提取字符,则返回eof而不是-1。并且read将使您能够将给定数量的字节读入一个值。请注意,您熟悉的某些类型(bytetype[])在C++中不存在或工作不同。后者可以使用std::vector,但您需要自己定义byte

2

我想我会做一些事情该顺序:

struct record { 
    static const int start = '\x5a'; 
    std::vector<char> data; // you might prefer unsigned char. 
}; 

std::istream &operator>>(std::istream &is, record &r) { 
    char ch; 
    short len; 

    is.get(ch); 
    verify(ch == record::start); 
    is.read((char *)&len, sizeof(len)); 
    r.data.resize(len); 
    is.read(&r.data[0], len); 
    return is; 
} 

std::ostream &operator<<(std::ostream &os, record const &r) { 
    os << record::start; 
    short len = (short)r.data.size(); 
    os.write((char *)&len, sizeof(len)); 
    os.write(&r.data[0], len); 
    return os; 
} 

要处理的记录的文件,就像你在你的Read(可怜的名字显示的东西,读,处理和写入数据, BTW)让我们通过定义一个函子来处理从文件中的单个记录开始:

class process_record { 
    record operator()(record r) { 
     // code to process a single record goes here 
     // it will take one record as input, and return the processed record. 
    } 
} 

然后,处理一个文件,我们会使用的代码是这样的:

std::transform(std::istream_iterator<record>(infile), 
       std::istream_iterator<record>(), 
       std::ostream_iterator<record>(outfile, ""), 
       process_record()); 

[注:为简便起见,我用C-风格转换在这里,但在真正的代码,我可能会使用static_cast!而非]

0

好了,根据您的回答,我有做一些实验:

string sFile = "C:\Test.bin"; 
static const int START_BYTE = '\x5a'; 
char tempByte; 

ifstream inputFile (sFile, ios::in); 
inputFile.open(sFile, ios::binary); 

while (!inputFile.eof()) 
{ 
    inputFile.get(temptByte); 

    cout << "Value of Byte " << hex << static_cast<int>(tempByte) << " hexadecimal" << endl; 
} 

但是,输出始终显示为:ffffffcc,或者如果未转换为-52。

如果我得到它的权利,我的代码应该在一次读取文件一个字节,并打印出字节十六进制值。我错了吗 ?