Russian Qt Forum

Qt => Вопросы новичков => Тема начата: CTime от Май 24, 2018, 11:00



Название: Частично переписать содержимое бинарного файла
Отправлено: CTime от Май 24, 2018, 11:00
Доброго времени суток! Столкнулся с такой задачей. Имеется бинарный файл, заголовок (первые 12 байт) которого имеет вид, приведенный на рисунке (во вложении). Необходимо на основе этого файла создать другой бинарный файл, в котором вместо значения inf3 поместить, например, (значение inf3) + 10. Вопрос в том, как именно дочитать файл до значения inf3, попутно копируя содержимое во второй файл, потом собственно считать значение inf3, прибавить к этому значению 10, записать его, а потом продолжить копирование файла уже до конца? Если не видно, то inf3 занимает не целое количество байт, а 15 бит. В Qt недавно, наверное еще не все инструменты знакомы, поэтому прошу помощи. Заранее огромное спасибо! Собственно достать само значение inf3 у меня вроде получилось:
Код:
    QString inFileName;
    QString inFilter;
    inFilter = "Bin files (*.rpu);; All Files (*.*)";
    inFileName = QFileDialog::getOpenFileName(0, trUtf8("Select file"), QApplication::applicationDirPath(), inFilter, 0);
    QFile inFile;
    inFile.setFileName(inFileName);
    QString outFileName = inFileName + "_output.rpu";
    QFile outFile;
    outFile.setFileName(outFileName);
    if (!inFile.open(QIODevice::ReadOnly)) qDebug() << "inFile error";
    if (!outFile.open(QIODevice::WriteOnly)) qDebug() << "outFile Error";
    QByteArray inArray;
    inArray = inFile.read(12);
    QDataStream stream (&inArray, QIODevice::ReadWrite);
    stream.setByteOrder(QDataStream::LittleEndian);
    stream.device()->seek(0);
    quint32 tmp;
    quint16 inf3;
    stream.operator >>(tmp) >> (tmp) >> (tmp);
    inf3 = (tmp&0x00007FFF);
    qDebug() << inf3;
    stream.device()->seek(0);


Название: Re: Частично переписать содержимое бинарного файла
Отправлено: qate от Май 24, 2018, 12:35
Очевидно - надо считать ВЕСЬ файл в qbytearray, замени нужные байты и запиши новый файл
Для мелких файлов это будет нормально так делать


Название: Re: Частично переписать содержимое бинарного файла
Отправлено: CTime от Май 24, 2018, 14:33
Размер файлов в среднем около 400мб, не знаю, можно ли такие файлы считать мелкими...
Цитировать
замени нужные байты
вот в этом основной вопрос состоит


Название: Re: Частично переписать содержимое бинарного файла
Отправлено: Пантер от Май 24, 2018, 14:42
Открываешь один файл на чтение, другой на запись. Читаешь из одного, пишешь в другой. Чего не ясно-то?


Название: Re: Частично переписать содержимое бинарного файла
Отправлено: qate от Май 24, 2018, 16:52
400мб для разовой работы не много

если много, делай QFile::copy
затем второй файл открывай на чтение и запись
считывай байты №2 и №3
вычисляй что нужно
пиши их обратно


Название: Re: Частично переписать содержимое бинарного файла
Отправлено: Igors от Май 25, 2018, 06:19
Код
C++ (Qt)
quint16  temp;
// читаем temp
const quint16 mask = 0x7FFF;
quint16 newVal = (temp & ~mask) | ((temp & mask) + 10);


Название: Re: Частично переписать содержимое бинарного файла
Отправлено: Old от Май 25, 2018, 06:32
Код
C++ (Qt)
quint16  temp;
// читаем temp
const quint16 mask = 0x7FFF;
quint16 newVal = (temp & ~mask) | ((temp & mask) + 10);
Не будет работать как надо. После прибавления результат может изменить старший бит.  
Код
C++ (Qt)
quint16 newVal = (temp & ~mask) | ((temp + 10) & mask);
 


Название: Re: Частично переписать содержимое бинарного файла
Отправлено: CTime от Май 25, 2018, 14:16
Спасибо всем, кто откликнулся! После всего прочитанного у меня получилось что-то вроде этого:
Код:
QFile inFile;
    inFile.setFileName(inFileName);
    QString outFileName = inFileName + "_output.rpu";
    QFile outFile;
    outFile.setFileName(outFileName);
    if (!inFile.open(QIODevice::ReadOnly) || (!outFile.open(QIODevice::ReadWrite)))
    {
            qDebug() << "some file error";
    }
    else
    {
        QByteArray array;
        array = inFile.readAll();
        inFile.close();
        QDataStream stream (&array, QIODevice::ReadWrite);
        stream.setByteOrder(QDataStream::LittleEndian);
        QDataStream outStream (&outFile);
        stream.device()->seek(0);
        quint32 tmp;
        quint16 inf3;
        stream.operator >>(tmp) >> (tmp) >> (tmp);
        inf3 = (tmp&0x00007FFF);
        qDebug() << inf3;
        const quint16 mask = 0x7FFF;
        quint16 newVal = (inf3 & ~mask) | ((inf3 + 10) & mask);
        qDebug() << newVal;
        stream.device()->seek(0);
        //ВСТАТЬ НА НУЖНУЮ ПОЗИЦИЮ
        stream << newVal;
        stream.device()->seek(0);
        outStream << stream;
        outFile.close();
    }
}
В правильном ли направлении я двигаюсь? И как все-таки встать на нужную позицию для записи?


Название: Re: Частично переписать содержимое бинарного файла
Отправлено: qate от Май 25, 2018, 17:24
QDataStream тут не нужен, достаточно QFile
А уж если ты считал весь файл в QByteArray, то и seek не нужен

Ты прочитал все рекомендации и все применил их все, получилась каша.


Название: Re: Частично переписать содержимое бинарного файла
Отправлено: Igors от Май 26, 2018, 08:48
Код
C++ (Qt)
// позиция заменяемого числа в файле
const qlonglong editOffset = 0;
 
bool Copy2Out( const QString & inFileName )
{
// копируем файл 1:1
QString outFileName  = inFileName + "_output.rpu";
if (!QFile::copy(inFileName, outFileName))
 return Error("File copy error");
 
// открываем выходной файл
 QFile file(outFileName);
 if (!file.open(QIODevice::ReadWrite))
  return Error("File write error");
 
// читаем число для замены
quint16 src, dst;
file.seek(editOffset);
file.read((char *) &src, 2);
 
// меняем
const quint16 mask = 0x7FFF;
dst = src & mask;
dst += 10;
if (dst & ~mask)
 return Error("Overflow Error");
 
dst |= (src & ~mask);
 
// пишем взад
file.seek(editOffset);
file.write((char *) &dst, 2);
 
if (file.error() != QFile::NoError)
 return Error("File Write Error");
 
return true;
}