将二进制序列化转换为人类可读的序列化

Converting binary serialization to human-readable serialization

我正在将一个用于将结构的二进制转储文件转换为文件并使用 fread 读回该二进制结构的程序。我想将其转换为创建和读取人类可读的数据文件,这当然意味着我需要格式化数据等。

ascii 数据文件的创建很顺利。我从使用 fwrite 切换到使用 fprintf,其格式指定以 \n 结尾作为新行。

FPFPF = fopen( flightStr, "w+" );

    if (FPFPF != NULL)
    {
        for ( i = 0; i < FlightInfo[flightnum].endFrameIndex; i++)
        {
            FlightEntries[flightnum][i].local_z += DeltaAlt;

            //if (fwrite (&FlightEntries[flightnum][i], sizeof (FLIGHT_ENTRY_TYPE), 1, FPFPF) !=1)
            if (fprintf (FPFPF, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
                FlightEntries[flightnum][i].local_x,
                FlightEntries[flightnum][i].local_y,
                FlightEntries[flightnum][i].local_z,
                FlightEntries[flightnum][i].pitch,
                FlightEntries[flightnum][i].roll,
                FlightEntries[flightnum][i].heading,
                FlightEntries[flightnum][i].gearpos,
                FlightEntries[flightnum][i].flappos,
                FlightEntries[flightnum][i].speedbrakepos,
                FlightEntries[flightnum][i].canopypos,
                FlightEntries[flightnum][i].afterburnerOn,
                FlightEntries[flightnum][i].kias,
                FlightEntries[flightnum][i].time) !=1)
            {
                WE++;
            }
        }

        fclose( FPFPF );
    }

这很好用。你可以看到旧的 fwrite 现在被注释掉了。

我希望读取文件也一样容易,但它似乎不起作用,而且我无法调试它,因为我在调试版本中使用 Freetype 时出现奇怪的内存泄漏,阻止了我进入这段代码。这是从文件中读取的代码。

if (load)
        {
            for ( i = 0; i < MAX_FLIGHT_ENTRIES; i++)
            {               
                // If the file end is found before it should be, set values to defaults
                // and save the file
                if (feof(pFile))
                {
                    FlightInfo[fileIndex].endFrameIndex = i - 1;
                    break;
                }
                else
                {
                    //fread (&FlightEntries[fileIndex][i], sizeof (FLIGHT_ENTRY_TYPE), 1, pFile);

                    fscanf (pFile, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
                        &FlightEntries[fileIndex][i].local_x,
                        &FlightEntries[fileIndex][i].local_y,
                        &FlightEntries[fileIndex][i].local_z,
                        &FlightEntries[fileIndex][i].pitch,
                        &FlightEntries[fileIndex][i].roll,
                        &FlightEntries[fileIndex][i].heading,
                        &FlightEntries[fileIndex][i].gearpos,
                        &FlightEntries[fileIndex][i].flappos,
                        &FlightEntries[fileIndex][i].speedbrakepos,
                        &FlightEntries[fileIndex][i].canopypos,
                        &FlightEntries[fileIndex][i].afterburnerOn,
                        &FlightEntries[fileIndex][i].kias,
                        &FlightEntries[fileIndex][i].time);
                }
            }

            FlightInfo[fileIndex].endFrameIndex = i - 1;

        }

在打开 pFile 之前还有一些其他检查,如果我们要做的不仅仅是查看文件是否存在,load 是一个布尔值。如果重要的话,FlightInfo 结构的所有值都是浮点数,除了 local_x、local_y 和 local_z 是双精度值。这里有什么明显错误的地方吗?它编译和运行没有错误,直到调用此代码块,然后它才崩溃。

由于对可变参数执行的默认提升,无论您传递 float 还是 doublefprintf 都没有关系。

但是对于 fscanf 来说,你传递 float* 还是 double* 非常重要:

有关标志,请参阅 http://man7.org/linux/man-pages/man3/scanf.3.html

The following type modifier characters can appear in a conversion specification:

l Indicates either that the conversion will be one of d, i, o, u, x, X, or n and the next pointer is a pointer to a long int or unsigned long int (rather than int), or that the conversion will be one of e, f, or g and the next pointer is a pointer to double (rather than float). Specifying two l characters is equivalent to L. If used with %c or %s, the corresponding parameter is considered as a pointer to a wide character or wide-character string respectively.

实际上,您应该阅读整个手册页,还有其他有趣的陷阱。

顺便说一句,l-修饰符对带有浮点说明符的 fprintf 没有影响。