Учитывая, что фактическая последовательность данных, которую вы используете, потенциально разделена по линиям, вам необходимо прочитать данные в самом маленьком «укусе», который вы можете - двухсимвольные массивы, и игнорировать пробелы (пробелы или символы новой строки) ,
Как только вы сделаете это, вы сможете отслеживать, что вы читали, когда пишете его в свой файл. Когда вы получите свою «магическую последовательность», запустите новый подфайл.
Две сложности, которые не охватывают:
- ли «волшебная последовательность» вообще можно существовать в файле как часть нормальных данных? Если это так, вы собираетесь разделить один-единственный файл.
- Я предполагаю, что вы не хотите «волшебную последовательность» в конце каждого подфайла. Это добавит немного сложности для сравнения:
- Если вы начинаете матч, вам нужно приостановить запись в подфайл.
- Если вы на полпути и внезапно прекратите сопоставление, вам придется выписать частичное совпадение, прежде чем записывать новую несогласованную запись.
Одно из преимуществ делать это таким образом: если суб-файл, в то же время в главном файле, началась в конце строки, то он начнет на новой линии и перерыв после 16 двух -характеры, а не имитировать свою позицию в основном файле.Или вы хотите, чтобы субфайлы выводились в истинных байтах без разделителей пробелов?
Я собираюсь уйти и написать эту программу: это звучит весело!
ОК, я написал следующее. Надеюсь, что использование описывает, что делать. Я не особенно хочу использовать потоки - Я нахожу их ужасно неэффективен - но вы начали его ...
//
// SubFile.cpp
//
#include <string>
#include <fstream>
#include <iostream>
#include <iomanip>
using namespace std;
const unsigned MaxBytesPerLine = 16;
const unsigned char magic[] = { '\x20','\x00','\x20','\x00','\x00','\x10','\x00','\x00' };
class OutFile : private ofstream {
public: // Methods
using ofstream::is_open; // Let others see whether I'm open
OutFile(const string &fileName, bool bin);
bool Write(unsigned b);
~OutFile();
private: // Variables
unsigned num; // Number bytes in line
bool bin; // Whether to output binary
}; // OutFile
OutFile::OutFile(const string &filename, bool bin) :
ofstream(filename),
num(0),
bin(bin) {
if (!bin) {
setf(uppercase);
} // if
} // OutFile::OutFile(name, bin)
bool OutFile::Write(unsigned b) {
if (bin) {
char c = (char)b; // Endian fix!
return write(&c, 1).good();
} // if
if (num > 0) {
*this << " ";
} // if
*this << setbase(16) << setw(2) << setfill('0') << b;
if (++num == MaxBytesPerLine) {
*this << endl;
num = 0;
} // if
return good();
} // OutFile::Write(b)
OutFile::~OutFile() {
if (bin) {
return;
} // if
if (num == 0) {
return;
} // if
if (!good()) {
return;
} // if
*this << endl;
} // OutFile::~OutFile
void Usage(char *argv0) {
cout << "Usage:" << endl;
cout << " " << argv0 << " <filename.txt> [bin]" << endl;
cout << " Read <filename.txt> in hex char pairs, ignoring whitespace." << endl;
cout << " Write pairs out to multiple sub-files, called \"1.txt\", \"2.txt\" etc." << endl;
cout << " New files are started when the following sequence is detected: " << endl << " ";
for (unsigned i = 0; i < sizeof(magic); ++i) {
cout << ' ' << hex << setw(2) << setfill('0') << (int)magic[i];
} // for
cout << endl;
cout << " If bin is specified: write out in binary, and files have a '.bin' extension" << endl;
} // Usage(argv0)
int main(int argc, char *argv[]) {
if (argc < 2) {
Usage(argv[0]);
return 1;
} // if
ifstream inFile(argv[1]);
if (!inFile.is_open()) {
cerr << "Could not open '" << argv[1] << "'!" << endl;
Usage(argv[0]);
return 2;
} // if
bool bin = (argc >= 3) &&
(argv[2][0] == 'b'); // Close enough!
unsigned fileNum = 0; // Current output file number
inFile >> setbase(16); // All inFile accesses will be like this
while (inFile.good()) { // Let's get started!
string outFileName = to_string(++fileNum) + (bin ? ".bin" : ".txt");
OutFile outFile(outFileName, bin);
if (!outFile.is_open()) {
cerr << "Could not create " << outFileName << "!" << endl;
return (int)(fileNum + 2);
} // if
unsigned b; // byte read in
unsigned pos = 0; // Position in 'magic'
while (inFile >> b) {
if (b > 0xFF) {
cerr << argv[1] << " contains illegal value: "
<< hex << uppercase << showbase << b << endl;
return -1;
} // if
if (b == magic[pos]) { // Found some magic!
if (++pos == sizeof(magic)) { // ALL the magic?
break; // Leave!
} // if
continue; // Otherwise go back for more
} // if
if (pos > 0) { // Uh oh. No more magic!
for (unsigned i = 0; i < pos; ++i) {
outFile.Write(magic[i]); // So write out what we got
} // for
pos = 0;
} // if
outFile.Write(b);
} // while
} // for
if (inFile.eof()) {
return 0; // Success!
} // if
string s;
inFile.clear();
getline(inFile, s);
cerr << argv[1] << " contains invalid data: " << s << endl;
return -2;
} // main(argc,argv)
Всякий раз, когда кто-то код сообщения, там неизменно комментариев:
«Почему не сделал ты делаешь это?"
«Зачем ты это сделал?»
Пусть открываются шлюзы!
Таким образом, фактическое содержимое файла представляет собой шестнадцатеричные числа в текстовой форме? Это не двоичный файл? –
Правильно, содержимое находится в текстовом файле. Я думал, что с ней будет легче работать, поэтому я выкинул ее в текстовый файл. У меня есть доступ к двоичному файлу, если это лучше. – Michael
Кроме того, похоже, что записи не обязательно разделяются линиями, что означает, что вы не можете использовать построчное чтение. И даже если в правильном месте есть разрывы строк, вы не можете использовать сравнение '==', так как строки содержат больше, чем разделитель, и сравнение двух строк с использованием '==' ищет точное соответствие *. Объявление, если файл действительно не текстовый, а все двоичные данные, вы не можете использовать 'std :: getline' и сравнение строк вообще. –