How to read n bytes of a file in QT C++? - c++

Hi im new to Qt and im trying to read for example the first 4 bytes of my .txt file and show it. I've been searching and figure that QbyteArray may help me best in this situation. so I really like to know how can i read the first 4 bytes of my file with QbyteArray? (appreciate if u write any example code)

Assuming your code contains something like this:
QFile file{ "path/to/file.txt" };
You can read a number of bytes from a file with file.read(n), assuming n to be a number of bytes. you can also use file.readAll() to get the entire thing
for more advanced input/output operations, you can use the QTextStream class as such:
QFile file { "path/to/file.txt" };
QTextStream stream { &file };
(This is a stream that can read and write data to the provided device, here, a file.)
For more info, see here:
https://doc.qt.io/qt-6/qfile.html for QFile
https://doc.qt.io/qt-6/qtextstream.html for QTextStream

Related

How to conveniently read chunks of a file to QByteArray?

I want to send chunks of a file over network. I want to send them as individual QByteArrays, say by 200 bytes. I thought I can use QFile, but I don't understand what is wrong with it. I try to open the file at given path and then start sending it asynchronously:
QByteArray readFileChunk(QFileInfo filePath, quint64 offset, quint64 minLength)
{
if(filePath.isFile() && filePath.isReadable()) {
// Prepare the file instance and reset the byte count to 0
QFile currentFile(filePath.absoluteFilePath());
}
}
I do not know how to read range from X to Y from a file as QByteArray. I found no concise example on the internet so I'm posting this question.

QFile to QByteArray save file name

I have a QFile that needs to be sent through a LAN network. In order to do so, I convert the QFile into QByteArray by doing:
//! [Inside a QTcpSocket class]
// Get the file name using a QFileDialog
QFile file(QFileDialog::getOpenFileName(NULL, tr("Upload a file")));
// If the selected file is valid, continue with the upload
if (!file.fileName().isEmpty) {
// Read the file and transform the output to a QByteArray
QByteArray ba = file.readAll();
// Send the QByteArray
write(ba);
}
When I receive it, I can transform it easily by using:
void saveFile(QByteArray ba) {
// Ask the user where he/she wants to save the file
QFile file(QFileDialog::getSaveFileName(NULL, tr("Save file")));
// Check that the path is valid
if (!file.fileName().isEmpty()) {
// Write contents of ba in file
file.write(ba);
// Close the file
file.close();
}
}
However, I would like to know the file name (such as Document.docx) or at least know its extension to avoid forcing the user to know exactly which file type he has received.
Ideally, when the file is uploaded, the receiver user will be prompted to save the file. For example:
Sender sends Document1.docx
Receiver gets prompted if he/she wants to save Document1.docx
Based on receiver's decision, Document1.docx is saved in receiver's workstation.
So, my question is: Is there any way to know the name and extension of a QFile when its transformed into a QByteArray and then transformed again (in another computer) into a QFile?
You just read the raw bytes of a file using QFile::readAll().
Q: Is there any way to know the name and extension of a QFile when its
transformed into a QByteArray?
No. The file name and extension is not necessarily inserted in bytes of a file. It depends on the file format. For example you can make your custom file with a specific extension and put its name and extension at the begging of the bytes.
You can send the name and extension of the file manually before sending the raw bytes of the file. Before that you can send the length of name and extension and the number of bytes in file. This way you know how many bytes are related to name, extension and raw bytes.
The answer on you particular question is NO. Although particular files contain the so called magic numbers (or signatures) in the beginning of the data, this signature should be unique for particular file format.
But the problem you have described seems not be serious, because you can simply send filename string and extension string separately of the file content.

QFile does not open file

QLabel* codeLabel = new Qlabel;
QFile file("C:\index.txt");
file.open(stderr, QIODevice::WriteOnly);
QByteArray data;
data = file.readAll();
codeLabel->setText("test"+QString(data));
file.close();
Then there is only "test" in QLabel.
Help, Please
Aside from the fact you should escape backslashes within C-style strings (c:\\index.txt), you have a problem with the following sequence:
// vvvvvvvvv
file.open(stderr, QIODevice::WriteOnly);
:
data = file.readAll();
// ^^^^
What exactly did you think was going to happen when you opened the file write-only, then tried to read it? You need to open it for reading such as with QIODevice::ReadOnly or QIODevice::ReadWrite.
On top of that, you should check the return code of all functions that fail by giving you a return code. You currently have no idea whether the file.open() worked or not.
I'm also not convinced that you should be opening stderr (which is really an ouput "device") for input. You'll almost certainly never get any actual data coming in on that file descriptor, which is probably why your input is empty.
You need to step back and ask what you're trying to acheive. For example, are you trying to capture everything your process sends to standard error? If so, it's not going to work that way.
If you're just trying to read the index.txt file, you're using the wrong overload. Remove the stderr parameter altogether:
file.open (QIODevice::ReadOnly);
If it's something else you're trying to do, add that to the question.
file.open(stderr, QIODevice::WriteOnly);
this closes the file again and reopens with the stderr stream in write only mode
you'll want to change that to
file.open(QIODevice::ReadOnly);
QFile file("C:\index.txt");
Here you try to open a file called: C:index.txt because '\i' is converted to i. You want to double you backslash:
QFile file("C:\\index.txt");
Because you read from a file you opened write-only.

How to get boost::iostream to operate in a mode comparable to std::ios::binary?

I have the following question on boost::iostreams. If someone is familiar with writing filters, I would actually appreciate your advices / help.
I am writing a pair of multichar filters, that work with boost::iostream::filtering_stream as data compressor and decompressor.
I started from writing a compressor, picked up some algorithm from lz-family and now am working on a decompressor.
In a couple of words, my compressor splits data into packets, which are encoded separately and then flushed to my file.
When I have to restore data from my file (in programming terms, receive a read(byte_count) request), I have to read a full packed block, bufferize it, unpack it and only then give the requested number of bytes. I've implemented this logic, but right now I'm struggling with the following problem:
When my data is packed, any symbols can appear in the output file. And I have troubles when reading file, which contains symbol (hex 1A, char 26) using boost::iostreams::read(...., size).
If I was using std::ifstream, for example, I would have set a std::ios::binary mode and then this symbol could be read simply.
Any way to achieve the same when implementing a boost::iostream filter which uses boost::iostream::read routine to read char sequence?
Some code here:
// Compression
// -----------
filtering_ostream out;
out.push(my_compressor());
out.push(file_sink("file.out"));
// Compress the 'file.in' to 'file.out'
std::ifstream stream("file.in");
out << stream.rdbuf();
// Decompression
// -------------
filtering_istream in;
in.push(my_decompressor());
in.push(file_source("file.out"));
std::string res;
while (in) {
std::string t;
// My decompressor wants to retrieve the full block from input (say, 4096 bytes)
// but instead retrieves 150 bytes because meets '1A' char in the char sequence
// That obviously happens because file should be read as a binary one, but
// how do I state that?
std::getline(in, t); // <--------- The error happens here
res += t;
}
Short answer for reading file as binary :
specify ios_base::binary when opening file stream.
MSDN Link

Reading bmp file for steganography

I am trying to read a bmp file in C++(Turbo). But i m not able to print binary stream.
I want to encode txt file into it and decrypt it.
How can i do this. I read that bmp file header is of 54 byte. But how and where should i append txt file in bmp file. ?
I know only Turbo C++, so it would be helpfull for me if u provide solution or suggestion related to topic for the same.
int main()
{
ifstream fr; //reads
ofstream fw; // wrrites to file
char c;
int random;
clrscr();
char file[2][100]={"s.bmp","s.txt"};
fr.open(file[0],ios::binary);//file name, mode of open, here input mode i.e. read only
if(!fr)
cout<<"File can not be opened.";
fw.open(file[1],ios::app);//file will be appended
if(!fw)
cout<<"File can not be opened";
while(!fr)
cout<<fr.get(); // error should be here. but not able to find out what error is it
fr.close();
fw.close();
getch();
}
This code is running fine when i pass txt file in binary mode
EDIT :
while(!fr)
cout<<fr.get();
I am not able to see binary data in console
this was working fine for text when i was passing character parameter in fr.get(c)
I think you question is allready answered:
Print an int in binary representation using C
convert your char to an int and you are done (at least for the output part)
With steganography, what little I know about it, you're not "appending" text. You're making subtle changes to the pixels (shading, etc..) to hide something that's not visually obvious, but should be able to be reverse-decrypted by examining the pixels. Should not have anything to do with the header.
So anyway, the point of my otherwise non-helpful answer is to encourage you go to and learn about the topic which you seek answers, so that you can design your solution, and THEN come and ask for specifics about implementation.
You need to modify the bit pattern, not append any text to the file.
One simple example :
Read the Bitmap Content (after header), and sacrifice a bit from each of the byte to hold your content
If on Windows, recode to use CreateFile and see what the real error is. If on Linux, ditto for open(2). Once you have debugged the problem you can probably shift back to iostreams.