0

次の構造のバイナリファイルを読み書きしたい:

ここに画像の説明を入力してください

ファイルは「RECORDS」で構成されています。各「RECORD」の構造は次のとおりです。最初のレコードを例として使用します

  • (赤)STARTバイト:0x5A(常に1バイト、固定値0x5A)
  • (緑)LENGTHバイト:0x00 0x16(常に2バイト、値は「0x000x02」から「0xFF0xFF」に変更できます)
  • (青)内容:LENGTHフィールドの10進値から2を引いた値で示されるバイト数。

この場合、LENGHTフィールドの値は22(0x00 0x16を10進数に変換)であるため、CONTENTには20(22-2)バイトが含まれます。私の目標は、各レコードを1つずつ読み取り、出力ファイルに書き込むことです。実際、私は読み取り関数と書き込み関数(いくつかの擬似コード)を持っています:

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++での作成方法がよくわかりません。誰かが私を正しい方向に向けてくれませんか?

4

4 に答える 4

3

std::ifstreamを使用して、ファイルをバイナリモードで開く必要があります(std::ios_base::binary)。

peek非常に似ていますが、文字を抽出できなかった場合のeof代わりに戻ります。-1またread、指定されたバイト数を値に読み込むことができます。byte( 、 )に精通しているタイプの中にはtype[]、C ++に存在しないか、動作が異なるものがあることに注意してください。std::vector後者に使用できますが、byte自分で定義する必要があります。

于 2012-08-05T12:12:36.557 に答える
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(データの読み取り、処理、書き込みを行うものの名前が悪い、ところで)、ファイルから単一のレコードを処理するファンクターを定義することから始めましょう。

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代わりにsを使用します。]

于 2012-08-05T14:37:20.303 に答える
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として変換されます。

私がそれを正しく理解した場合、私のコードは一度に1バイトずつファイルを読み取り、バイトの16進値を出力する必要があります。私が間違っている ?

于 2012-08-05T20:38:55.200 に答える
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;
}
于 2012-08-07T07:50:32.177 に答える