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

标签 c printf fopen fread scanf

我正在转换一个程序,该程序用于将结构的二进制转储到文件中,并使用 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 是一个 bool 值。如果重要的话,FlightInfo 结构的所有值都是 float ,除了 local_x、local_y 和 local_z 是 double 值。这里有什么明显错误的地方吗?它编译和运行没有错误,直到调用此代码块,然后它才崩溃。

最佳答案

没关系fprintf你是否通过 floatdouble由于对可变参数执行的默认提升。

但这对 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 无效带有浮点说明符。

关于将二进制序列化转换为人类可读的序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28835757/

相关文章:

c++ - 为 C++ 库创建自动 C 包装器?

c - 参数化包括

统计用户输入的整数与C程序中文本文件的匹配情况

c - 无法在 C 中将字符串存储为数组变量

c - 解析字符串并将 token 的索引放入表中

c - 使用 sprintf 制作格式字符串

c - TicTacToe 打印获胜者

bash - 我如何让 $(/bin/printf -6) 返回 -6 而不是认为 -6 是一个选项

c++ - 检查 fopen 不支持的文件名

c++ - 如何读取包含 '\0' 个字符的文件?