Как сравнить два проанализированных файла и добавить разницу к первому?

Предположим, у меня есть два файла .dat; один на моем компьютере, а другой на другой стороне Земли — данные постоянно сериализуются в них через QDataStream,

Данные анализируются таким же образом — сначала какой-то идентификатор, а затем объект, связанный с этим конкретным идентификатором.

QFile file("data.dat");
QDataStream stream(&file);

file.open("QIODevice::ReadWrite");

stream << *id*;          // ID goes in.
stream << *data_object*; // Object with interesting data is serialized into the file.

file.close();

Через некоторое время — первый может выглядеть примерно так (иллюстративно, не синтаксически правильно):

//-------------------------------------DATA.DAT------------------------------------//

ID:873482025
dataObject

ID:129845379
dataObject

ID:836482455
dataObject

ID:224964811
dataObject

ID:625444876
dataObject

ID:215548669
dataObject

//-------------------------------------DATA.DAT------------------------------------//

Но второй еще не догнал.

//-------------------------------------DATA.DAT------------------------------------//

ID:873482025
dataObject

ID:129845379
dataObject

ID:836482455
dataObject

//-------------------------------------DATA.DAT------------------------------------//

Можно ли взять оба файла — обнаружить различия между ними и затем «слить» в тех, которые отсутствуют во втором, но присутствуют в первом?

Очевидно, что этого можно достичь, написав функцию, которая извлекает внутренние файлы, классифицирует содержимое по отдельности, сравнивает их и т. Д., Но есть ли способ сделать это, просто обработав сами файлы, не анализируя содержимое по отдельности?

3

Решение

  1. Прочитайте оба файла, чтобы извлечь наборы идентификаторов.

  2. Прочитайте один из файлов, добавляя объекты с отсутствующими идентификаторами в другой файл.

Вы можете использовать QSet сделать набор арифметики. Кроме того, каждому объекту потребуются не только операторы потоковой передачи, но и skipObject статический метод. Я также игнорирую то, как вы различаете типы объектов.

typedef qint32_t Id;

bool isOk(const QDataStream & str) { return str.status() == QDataStream::Ok; }

class Object {
...
public:
static void skipObject(QDataStream & str) {
qint8 format;
str >> format;
if (format == 0)
str.skipRawData(32); // e.g. format 0 of this object is 32 bytes long
...
}
};

QPair<QSet<Id>, bool> getIds(const QString & path) {
QSet<Id> ids;
QFile file(path);
if (!file.open(QIODevice::ReadOnly)) return ids;
QDataStream stream(&file);
while (!stream.atEnd()) {
stream >> id;
Object::skipObject(stream);
if (ids.contains(id))
qWarning() << "duplicate id" << id << "in" << path;
ids.insert(id);
}
return qMakePair(ids, isOk(stream));
}

bool copyIds(const QString & src, const QString & dst, const QSet<Id> & ids) {
QFile fSrc(src), fDst(dst);
if (! fSrc.open(QIODevice::ReadOnly)) return false;
if (! fDst.open(QIODevice::WriteOnly | QIODevice::Append)) return false;
QDataStream sSrc(&fSrc), sDst(&fDst);
while (!sSrc.atEnd()) {
Id id;
sSrc >> id;
if (ids.contains(id)) {
Object object;
sSrc >> object;
sDst << id << object;
} else
Object::skipObject(sSrc);
}
return isOk(sSrc) && isOk(sDst);
}

bool copyIds(const QString & src, const QString & dst) {
auto idsSrc = getIds(src);
auto idsDst = getIds(dst);
if (!idsSrc.second || !idsDst.second) return false;
auto ids = idsSrc.first - idsDst.first;
return copyIds(src, dst, ids);
}
2

Другие решения


По вопросам рекламы [email protected]