Qt存储大整数到`JsonValue`

ops/2024/12/28 6:43:55/

原文链接:【Qt】Qt存储大整数到`JsonValue`【2023.08.01】_在qt中,当您将一个uint64数据存储为qjsonvalue,如果该数据超出了javascript-CSDN博客

 

Qt存储大整数到JsonValue

简介

  我负责的需求是这样,存储文件绝对路径和文件大小到json字符串。格式如下:

{"fileList": {"path": "dsadadadadadad","size": 222}
}

开发过程中,未意识到文件可能大于int的最大值,所以埋下了隐患。今天被测试提了个bug。主要原因是QJsonValue的toInt()返回的是4字节的int类型,拿来存一个大于有符号四字节整数的值会溢出。这种边界值界定不明确导致bug的情况还是比较常见,做个总结分享帮助大家避坑。

此外就是csdn上对于这块的教程属实是又少又粗略。
 

上代码

/*** 本程序是测试Qt 程序存储64位整数 至Json文件 并加载读出*/
#include <QtCore/QCoreApplication>
#include <QJsonObject>
#include <QJsonValue>
#include <QDebug>
#include <QDir>
#include <QJsonDocument>
#include <QByteArray>
#include <iostream>
#include <climits>
#include <cfloat>
#include <iomanip>void printTypeInfo();
/***Type    Size(bytes)           Minimum               Maximum------------------------------------------------------------------------------------------------------------bool    1char    1                     -128                  127int     4                     -2147483648           2147483647uint    4                     4294967295short   2                     -32768                32767ushort  2                     65535long    4                     -2147483648           2147483647ulong   4                     4294967295ll      8                     -9223372036854775808  9223372036854775807ull     8                     18446744073709551615float   4                     1.17549e-038          3.40282e+038double  8                     2.22507e-308          1.79769e+308ldouble 8                     2.22507e-308          1.79769e+308------------------------------------------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);//printTypeInfo();using namespace std;/************************************************************************//**	第一部分、往文件中写*//************************************************************************/// 创建JSON对象QJsonObject root;// 创建fileList数组QJsonObject obj;obj["path"] = "YangNaifeng";qint64 llData =  1;// LLONG_MAX;obj["size"] = llData;//最大15位root.insert("fileList", obj);QJsonDocument doc;doc.setObject(root);auto path = QCoreApplication::applicationDirPath();auto outJson = path + "/" + "sad.json";QDir dir(path);if (dir.mkpath(path)){QFile file(outJson);file.open(QIODevice::WriteOnly);file.write(doc.toJson());file.close();}else{qCritical() << QString::fromStdWString(L"创建文件夹失败!");}/************************************************************************//**	从文件中读 并解析*//************************************************************************/QFile readFile(outJson);readFile.open(QIODevice::ReadOnly);QByteArray data = readFile.readAll();QJsonDocument docRead = QJsonDocument::fromJson(data);if (!docRead.isNull() && docRead.isObject()) {QJsonObject obj = docRead.object();if (obj.contains("fileList") && obj["fileList"].isObject()) {QJsonObject fileListObj = obj["fileList"].toObject();QString path = fileListObj["path"].toString();auto eDoubleType = QJsonValue::Double;cout << fileListObj["size"].type();//QJsonValue::Doubleauto size = fileListObj["size"].toDouble();qint64  nSize = QString::number(size, 'f', 0).toLongLong();qDebug() << "Path:" << path;qDebug() << "Size:" << size;}else{qDebug() << "fileList not found";}}else{qDebug() << "Invalid JSON document";}return a.exec();
}void printTypeInfo()
{using namespace std;// 设置表格样式cout << left;cout << setw(8) << "Type";cout << setw(22) << "Size(bytes)";cout << setw(22) << "Minimum";cout << setw(22) << "Maximum";cout << endl;cout << "------------------------------------";cout << "------------------------------------";cout << "------------------------------------";cout << endl;// boolcout << setw(8) << "bool";cout << setw(22) << sizeof(bool);cout << setw(22);cout << setw(22);cout << endl;// charcout << setw(8) << "char";cout << setw(22) << sizeof(char);cout << setw(22) << (int)CHAR_MIN;cout << setw(22) << (int)CHAR_MAX;cout << endl;// intcout << setw(8) << "int";cout << setw(22) << sizeof(int);cout << setw(22) << INT_MIN;cout << setw(22) << INT_MAX;cout << endl;// unsigned intcout << setw(8) << "uint";cout << setw(22) << sizeof(unsigned int);cout << setw(22);cout << setw(22) << UINT_MAX;cout << endl;// shortcout << setw(8) << "short";cout << setw(22) << sizeof(short);cout << setw(22) << SHRT_MIN;cout << setw(22) << SHRT_MAX;cout << endl;// unsigned shortcout << setw(8) << "ushort";cout << setw(22) << sizeof(unsigned short);cout << setw(22);cout << setw(22) << USHRT_MAX;cout << endl;// longcout << setw(8) << "long";cout << setw(22) << sizeof(long);cout << setw(22) << LONG_MIN;cout << setw(22) << LONG_MAX;cout << endl;// unsigned longcout << setw(8) << "ulong";cout << setw(22) << sizeof(unsigned long);cout << setw(22);cout << setw(22) << ULONG_MAX;cout << endl;// long long cout << setw(8) << "ll";cout << setw(22) << sizeof(long long);cout << setw(22) << LLONG_MIN;cout << setw(22) << LLONG_MAX;cout << endl;// unsigned long longcout << setw(8) << "ull";cout << setw(22) << sizeof(unsigned long long);cout << setw(22);cout << setw(22) << ULLONG_MAX;cout << endl;// floatcout << setw(8) << "float";cout << setw(22) << sizeof(float);cout << setw(22) << FLT_MIN;cout << setw(22) << FLT_MAX;cout << endl;// doublecout << setw(8) << "double";cout << setw(22) << sizeof(double);cout << setw(22) << DBL_MIN;cout << setw(22) << DBL_MAX;cout << endl;// long doublecout << setw(8) << "ldouble";cout << setw(22) << sizeof(long double);cout << setw(22) << LDBL_MIN;cout << setw(22) << LDBL_MAX;cout << endl;cout << "------------------------------------";cout << "------------------------------------";cout << "------------------------------------";}

总结

1.QJsonValue存储整数是按照double类型存储的,即使是1这么一个很小的数。

2.QJsonValue的toInt()是提供了double到int的转换。而不是文件本身存的就是int类型的数据。

3.QJsonValue之所以没有tolonglong()的接口是因为double类型是有精度损失的。double类型的有效数字位数:15-16位数字,double类型的有效数字位数是15位还是16位,主要取决于浮点数的值:a. 对于绝对值在1.0和2^53之间的正常值,double类型一般能表示15位有效数字。b. 当浮点数接近0时,指数部位全部为0,此时有效数字位数可以达到16位。3. 当浮点数接近2^53时,指数部位为最大值,此时有效数字位数只有15位。

4.为啥Qt存整数到Json不是按整形存,而是以double类型存?

为什么JSON不支持 int64 类型?

通过上面的介绍有两个关键点:

   1.  JSON 是基于 JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集
   2.  JSON 支持number 类型

Javascript的数字存储使用了IEEE 754中规定的双精度浮点数数据类型,而这一数据类型能够安全存储 -(2^53-1) 到 2^53-1 之间的数值(包含边界值)。JSON 是 Javascript 的一个子集,所以它也遵守这个规则。

以下是rfc7159的说明:

Note that when such software is used, numbers that are integers and are in the range [-(2^53)+1, (2^53)-1] are interoperable in the sense that implementations will agree exactly on their numeric values.

这两个边界值可以通过 JavaScript 的 Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER 获取。

5.对于特别大的数,保证精度首选字符串。


http://www.ppmy.cn/ops/145592.html

相关文章

探寻 OneCode 核心优势:MVVM 进阶与前后端协同之魅

在当今的软件开发领域&#xff0c;高效、可维护且功能强大的架构是开发者们不懈追求的目标。OneCode 凭借其独特的增强版 MVVM 架构、前后端一体化特性&#xff0c;以及创新的技术如 OneCode DSM&#xff08;Domain-Specific Modeling&#xff0c;领域特定建模&#xff09;、视…

【论文阅读】AllMatch: Exploiting All Unlabeled Data for Semi-Supervised Learning

一、引言 在当今的机器学习领域&#xff0c;半监督学习&#xff08;SSL&#xff09;作为一种重要的学习范式&#xff0c;受到了广泛的关注。它旨在利用有限的标记数据和大量的未标记数据来提升模型的性能&#xff0c;从而在数据标记成本较高而未标记数据丰富的情况下发挥重要作…

小型五轴联动数控机床助力职业教育发展

小型五轴联动加工中心&#xff0c;CNC系统通过编程控制五个轴的协同运动&#xff0c;每个轴的运动都是独立的&#xff0c;但通过CNC系统的控制&#xff0c;这些轴可以实现精确的同步和协调&#xff0c;以完成复杂曲面和不规则形状的加工。 小型五轴加工中心x、y、z轴为移动轴&a…

layui动态拼接生成下拉框验证必填项失效问题

利用 jQuery 动态拼接下拉框时&#xff0c;lay-verify"required" 失效了&#xff0c;有以下几种原因。 1. <form></form>标签 加入 layui 类&#xff0c;class"layui-form" 。提交按钮上加自动提交&#xff0c;lay-submit ""; 。需…

React:前端开发领域的璀璨之星

亲爱的小伙伴们&#x1f618;&#xff0c;在求知的漫漫旅途中&#xff0c;若你对深度学习的奥秘、Java 与 Python 的奇妙世界&#xff0c;亦或是读研论文的撰写攻略有所探寻&#x1f9d0;&#xff0c;那不妨给我一个小小的关注吧&#x1f970;。我会精心筹备&#xff0c;在未来…

基于Android MTP的技术深度解析

基于Android MTP的技术深度解析 目录 引言MTP协议概述 MTP的历史与发展MTP与PTP的区别MTP的优势与劣势Android中的MTP实现 Android MTP架构MTP在Android中的工作流程Android MTP的代码结构MTP协议详解 MTP协议栈MTP操作码MTP数据包格式MTP对象格式Android MTP API MtpDevice类…

Git核心概念

版本控制 什么是版本控制 版本控制是一种记录一个或若干文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统。 除了项目源代码&#xff0c;你可以对任何类型的文件进行版本控制。 为什么要版本控制 有了它你就可以将某个文件回溯到之前的状态&#xff0c;甚至将整…

图片拼接|横向拼接|竖向拼接|正方形拼接|其他模式拼接 python

读取某文件夹下所有子文件夹的图片&#xff0c;进行拼接 文件夹 —文件夹1 |----图片1 |----图片2 —文件夹2 |----图片3 —文件夹3 |----图片4 |----图片5 import os import cv2 import numpy as np import random from math import ceil, sqrt# 支持中文路径的图片读取函数…