Inserting an integer into QByteArray - c++

I am trying to read a binary data file using QDataStream and QByteArray, make some changes, and save off as a new file.
I have the following:
QDataStream in_datastream(&file);
QByteArray fileByteArray = file.readAll();
//find my insertion point
int pos = fileByteArray.indexOf(magic_num, 0);
//move to insertion point, minus 4 bytes (size of an integer)
file.seek(pos-4);
int current_val;
//check what the value is here
in_datastream >> current_val;
//now, I want to replace that value..but how?
I have tried several things at this point, but can't seem to figure out how to make it work. I want to insert the integer 5000 at (pos-4) in the QByteArray.
//remove 4 bytes..this seems to work
fileByteArray.remove(pos-4, 4);
//actually inserts garbage.
fileByteArray.insert(pos-4, newInteger);
If I try to insert a 4 character string "TEST", they all get inserted properly. I think I am having some type conversion problems trying to put an integer in there.

First of all, integer may have size not only 4, but 8 bytes, so you should use sizeof(integer) instead of 4. Then you can convert integer to string with Qstring::number(newInteger). QString can be converted to bytearray with QString::toLatin1()

Related

How to convert QVector<double> to QByteArray and compress it

I would like to convert QVector to QByteArray. I am using something like this:
QByteArray bytesArray
QDataStream out(&bytesArray ,QIODevice::WriteOnly);
out << someVector;
bytesArray = qCompress(bytesArray, 5);
And to read it:
bytesArray = qUncompress(bytesArray)
QDataStream in(bytesArray);
QVector<qreal> otherVector;
in >> otherVector;
But i have a problem. I saved number like 1.23124121242135, and after reading i got 1.23124. How can i store and read full number?
If for any reason it wont allow storing the value( e.g.. 0.0 +10 or more decimals u could do a workaround
1 convert double t string and get t_size to int
2 create a long or another int according to the length of said value and multiply it with the size of original and save size with the new int value.
If original is 1.876649018 size is 10 so
the multiplier is 10^10
3 getting it back is just a matter of division of new long int value with the size
That is the only thing that comes to mind right now...

read / write on byte array by QDataStream

i have byte image array i want to write this byte array to another byte array with add some another value on second byte array , i'm using this code but i think something is wrong
QByteArray byteArray;
QDataStream ds(&byteArray,QIODevice::ReadWrite);
ds<<(qint32)20;
ds<<bArray;
qint32 code;
ds>>code;
when i trace ds>>code it is always have 0 value but in fact it must have 20 value and i used ds.resetStatus(); but it return 0 value again
I suspect that QDataStream::operator<< functions sets some sort of pointer/iterator/index to point to the next location where they can start inserting data when the next call is made. QDataStream::operator>> probably starts to read from the same location.
QDataStream::resetStatus() does not change the position from where the object reads/writes. It merely resets the status to QDataStream::Ok to allow you to read from the stream after an error has occurred.
You can use two QDataStream objects -- one for writing to the QByteArray and the other for reading from the same QByteArray.
QByteArray byteArray;
QDataStream ds_w(&byteArray,QIODevice::WriteOnly);
QDataStream ds_r(&byteArray,QIODevice::ReadOnly);
ds_w << (qint32)20;
ds_w << bArray;
qint32 code;
ds_r >> code;

Fill QByteArray from QAudioBuffer

My goal is to save a QAudioRecorder recording into memory. From my research it seems the best way to store the recording is to use a QByteArray. My audio recorder is probed using a QAudioProbe.
From the audioBufferProbed signal I try to append the data to the byte array using this slot method.
QByteArray *byteArr;
void AudioRecorder::processBuffer(const QAudioBuffer &buffer)
{
byteArr->append(buffer.constData<char>());
qDebug() << buffer.byteCount();
qDebug() << byteArr->size();
}
However that doesn't seem to work considering buffer.byteCount(); returns 4092 constantly which seems normal but byteArr->size(); returns weird and irregular increments starting off usually with 2, 4, 6, 7, 189.
The data also usually only ends up being around 18kb in size which also leads me to believe that the data is not being appended into the byte array correctly.
According to the QByteArray::size() docs size() should give how many bytes are in the array. Along with QAudioBuffer::byteCount() which also should give the amount of bytes in the current buffer, shouldn't the full 4092 from the buffer be copied to the array?
I am also open to another solution that doesn't use QByteArray if there is a better way to store the data.
You have a QByteArray pointer, but have not set it to anything.
You need to set it to a QByteArray, in your case you can use QByteArray(const char * data, int size):
byteArr = new QByteArray(buffer.constData<char>(), buffer.byteCount());
But to be honest, I am not sure why you are using a pointer.
You could just do:
QByteArray byteArr; // Your global declaration
:
:
byteArr.append(buffer.constData<char>(), buffer.byteCount());
You might want to try printing like this if you are using binary data...:
qDebug() << byteArr.toHex();
You are using method QByteArray::append which does something else than you expect. This overload of append you are using appends bytes until zero is encountered. This API should be used for c-strings!
So fix code like this:
QByteArray byteArr; // there is no point of create this on heap
byteArr.reserve(8*1024*1024); // reserve 8 MB - it will improve performance
void AudioRecorder::processBuffer(const QAudioBuffer &buffer)
{
byteArr.append(buffer.constData<char>(), buffer.size());
qDebug() << buffer.byteCount();
qDebug() << byteArr.size();
}

What is the best solution for writing numbers into file and than read them?

I have 640*480 numbers. I need to write them into a file. I will need to read them later. What is the best solution? Numbers are between 0 - 255.
For me the best solution is to write them binary(8 bits). I wrote the numbers into txt file and now it looks like 1011111010111110 ..... So there are no questions where the number starts and ends.
How am I supposed to read them from the file?
Using c++
It's not good idea to write bit values like 1 and 0 to text file. The file size will bigger in 8 times. 1 byte = 8 bits. You have to store bytes, 0-255 - is byte. So your file will have size 640*480 bytes instead of 640*480*8. Every symbol in text file has size of 1 byte minimum. If you want to get bits, use binary operators of programming language that you use. To read bytes much easier. Use binary file for saving your data.
Presumably you have some sort of data structure representing your image, which somewhere inside holds the actual data:
class pixmap
{
public:
// stuff...
private:
std::unique_ptr<std::uint8_t[]> data;
};
So you can add a new constructor which takes a filename and reads bytes from that file:
pixmap(const std::string& filename)
{
constexpr int SIZE = 640 * 480;
// Open an input file stream and set it to throw exceptions:
std::ifstream file;
file.exceptions(std::ios_base::badbit | std::ios_base::failbit);
file.open(filename.c_str());
// Create a unique ptr to hold the data: this will be cleaned up
// automatically if file reading throws
std::unique_ptr<std::uint8_t[]> temp(new std::uint8_t[SIZE]);
// Read SIZE bytes from the file
file.read(reinterpret_cast<char*>(temp.get()), SIZE);
// If we get to here, the read worked, so we move the temp data we've just read
// into where we'd like it
data = std::move(temp); // or std::swap(data, temp) if you prefer
}
I realise I've assumed some implementation details here (you might not be using a std::unique_ptr to store the underlying image data, though you probably should be) but hopefully this is enough to get you started.
You can print the number between 0-255 as the char value in the file.
See the below code. in this example I am printing integer 70 as char.
So this result in print as 'F' on the console.
Similarly you can read it as char and then convert this char to integer.
#include <stdio.h>
int main()
{
int i = 70;
char dig = (char)i;
printf("%c", dig);
return 0;
}
This way you can restrict the file size.

Quickly convert raw data to hex string in c++

I'm reading data from a file and trying to display the raw data as 2 digit hex strings.
I'm using the Qt framework, specifically the QTextEdit.
I've tried a bunch of different approaches and have almost accomplished what I want it to do, however it has some unexpected errors I don't know anything about.
Currently this is my implementation:
1) Read in the data:
ifstream file (filePath, ios::in|ios::binary|ios::ate);
if (file.is_open())
{
size = file.tellg();
memblock = new char [size+1];
file.seekg(0, ios::beg);
file.read(memblock, size);
file.close();
}
2) Create a single QString that will be used (because QTextEdit requires a QString):
QString s;
3) Loop through the array appending each successive character to the QString s.
int count = 0;
for(i=0;i<size;i++)
{
count++;;
s.append(QString::number(memblock[i], 16).toUpper());
s.append("\t");
if (count == 16)
{
s.append("\n");
count -= 16;
}
}
Now this works fine, except when it reaches a character FF, it appears as FFFFFFFFFFFFFFFF
So my main questions are:
Why do only the 'FF' characters appear as 'FFFFFFFFFFFFFFFF' instead?
Is there a way to convert the char data to base 16 strings without using QString::number?
I want this implementation to be as fast as possible, so if something like sprintf could work, please let me know, as I would guess that might be faster that QString::number.
QString can't be used for binary data. You should use QByteArray instead. It can be easily created from char* buffer and can be easily converted to hex string using toHex.
QByteArray array(memblock, size);
textEdit->setText(QString(array.toHex()));
QString::number doesn't have an overload that takes a char, so your input is being promoted to an int; consequently you're seeing the effects of sign extension. You should be seeing similar behavior for any input greater than 0x7F.
Try casting the data prior to calling the function.
s.append(QString::number(static_cast<unsigned char>(memblock[i]), 16).toUpper());