Qt Learning Path: binary file reading and writing

Source: Internet
Author: User

 

In the previous chapter, we covered the QFile QFileInfo use of and two classes. We mentioned that it QIODevice provides read() , and readLine() so on, basic operations. At the same time, QT provides a higher level of operation: for binary streams QDataStream and for text streams QTextStream . In this section, we will explain QDataStream the use and some techniques. The next chapter is QTextStream the relevant content.

QDataStreamProvides serialization of binary data based on QIODevice . A data stream is a binary stream that is completely independent of the underlying operating system, CPU, or byte order (big or small). For example, a data stream written on a PC with a Windows platform installed can be read directly to a SPARC machine running Solaris without any processing. Since the data stream is a binary stream, we can also read and write directly to the binary data without encoding, such as image, video, audio, etc.

QDataStreamYou can access both C + + basic types, such as int, char, short, and more, as well as access complex data types, such as custom classes. In fact, QDataStream for class storage, complex classes are partitioned into a number of base units.

Combined QIODevice , QDataStream it is easy to read and write files, network sockets, and so on. Let's start with the code:

12345 QFile file("file.dat"); file. Open(qiodevice::WriteOnly); Qdatastream out (&file); out << QString("The answer is"); out << (qint32);

In this code, we first open a file named File.dat (note that we did not check the success of the file opening for the sake of simplicity, which is not allowed in the formal program). We then file pass a pointer to an instance of the object we just QDataStream created out . Similar to the std::cout standard output stream, QDataStream It also overloads the output redirection << operator. The following code is simple: Output "The answer is" and the number 42 to the data stream (if you do not understand the meaning of this sentence, this is the answer to the ultimate question of the universe;-P please search the Galaxy Roaming Guide yourself). Since our out object is built on file , it is equivalent to writing the answer to the ultimate question of the universe file .

One point to note: It is best to use a Qt integer for reading and writing, such as in a program qint32 . This ensures that the same behavior can be found on any platform and any compiler.

Let's look at an example of how Qt stores data. For example char * , a string that, when stored, stores the string first, including the length of the (32-bit integer), and then the contents of the string, and the Terminator,. When reading, the entire length is read out with a 32-bit integer, and the entire string is fetched at that length.

However, if you run this code directly, you will get a blank file.dat, and no data is written. This is because we are file not properly closed. For performance reasons, data is only actually written when the file is closed. Therefore, we must add a line of code at the end:

1 File. Close(); //If you do not want to close the file, you can use File.flush ();

Run the program again and you'll get the answer to the ultimate cosmic question.

We've got the answer to the ultimate question of the universe, and here we're going to read the answer:

123456 QFile file("file.dat"); file. Open(qiodevice::ReadOnly); Qdatastream in(&file); QString str; qint32 a; in >> str >> a;

There's nothing to say about this piece of code. The only thing to note is that you have to read the data in the order in which it was written. In other words, the order in which program data is written must be pre-defined. In this example, we first write the string and then write the number, so the first thing we read is the string, and then the number. If the order is reversed, the program behavior is indeterminate, and when it is serious it can cause the program to crash directly.

Since the binary stream is purely byte data, the problem is that if the program is read differently between versions (as mentioned earlier, QT guarantees the consistency of read and write content, but does not guarantee consistency between different QT versions), the data will be wrong. Therefore, we must provide a mechanism to ensure consistency between different versions. In general, we will write with the following code:

123456789101112 QFile file("file.dat"); file. Open(qiodevice::WriteOnly); Qdatastream out (&file); //write Magic numbers and versions out << (quint32)0xa0b0c0d0; out << (qint32)123; out. Setversion(qdatastream::qt_4_0); //Write Dataout << lots_of_interesting_data;

Here, we have added two lines of code:

1 out << (quint32)0xa0b0c0d0;

Used to write magic numbers. The so-called magic number is a technique that is often used in binary output. Binary formats are unreadable by people and often have the same suffix names (such as DAT), so we have no way of distinguishing between two binary files which is legal. Therefore, the binary format that we define usually has a magic number that identifies the legitimacy of the file. In this example, we write the 0xa0b0c0d0 at the beginning of the file, and first check whether the number is 0xa0b0c0d0 when reading it. If not, it means that the file is not in a recognizable format, so there is no need to continue reading. General binary files will have such a magic number, such as the Java class file magic number is 0xCAFEBABE, using the binary Viewer can be viewed. The magic number is a 32-bit unsigned integer, so we use it quint32 to get a platform-independent 32-bit unsigned integer.

Next line,

1 out << (qint32)123;

Is the version that identifies the file. We use magic numbers to identify the type of file, thus judging whether the file is legitimate. However, there may be differences between different versions of a file: We may save the integer in the first edition, and the second version may save the string. In order to identify different versions, we can only write the version to the file. For example, now our version is 123.

The following line is also about the version:

1 Out. Setversion(qdatastream::qt_4_0);

The above sentence is the version number of the file, but the reading between different versions of Qt may not be the same. In this way, we have to specify which version of Qt to read. Here, we specify to read the content in Qt 4.0 format.

When we write to a file like this, we need to add a series of judgments when we read it:

1234567891011121314151617181920212223242526272829303132 QFile file("file.dat"); file. Open(qiodevice::ReadOnly); Qdatastream in(&file); //Check Magic numbersQuint32 Magic; in >> magic; if (magic! = 0xa0b0c0d0) { return bad_file_format; }//Check versionqint32 version; in >> version; if (version < ) { return bad_file_too_old; }if (version > 123) { return bad_file_too_new; } if (version <= ) { In . Setversion(qdatastream::qt_3_2); } else { In . Setversion(qdatastream::qt_4_0); }//Read Datain >> lots_of_interesting_data; if (version >= ) { In >> data_new_in_version_1_2; }in >> other_interesting_data;

This code is based on the previous explanation. First read the magic number, check whether the file is legitimate. If it is legal, read the file version: less than 100 or greater than 123 is not supported. If within the supported version range (<= version <= 123), when is less than or equal to 110, Qt_3_2 read in the format, otherwise Qt_4_0 read in the format. When these parameters are set, the data is started to be read.

So far, we've covered the QDataStream relevant content. So, why do we QIODevice have a function that is provided, or read() readLine() something like that QDataStream ? QDataStream QIODevice What's the difference? The difference is that QDataStream providing the form of a stream is generally better performance than calling the original API directly. Let's look at what the flow is in the form of the following code:

12345678910 QFile file("file.dat"); file. Open(qiodevice::ReadWrite); Qdatastream Stream(&file); QString str = "The answer is a"; QString strout; stream << str; file. Flush(); stream >> strout;

In this code, we first write the data to the file, and then we read the data. What's the problem? After running you will find that the strout actual is empty. Why didn't you read it? Haven't we already added the file.flush(); statement? The reason is not that the file is written, but that we are using a "stream". The so-called flow, like a current, its cursor moves backwards with the output. When you use the << operator output, the flow cursor is at the end, and you read it again, and of course you can't read anything. So you need to re-set the cursor to 0 after the output to continue reading. The specific code snippet is as follows:

123 stream << str; stream. Device(),seek(0); stream >> strout;

Qt Learning Path: binary file reading and writing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.