当前位置: 首页 > article >正文

Qt存储大整数到`JsonValue`

原文链接:【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    1
 char    1                     -128                  127
 int     4                     -2147483648           2147483647
 uint    4                     4294967295
 short   2                     -32768                32767
 ushort  2                     65535
 long    4                     -2147483648           2147483647
 ulong   4                     4294967295
 ll      8                     -9223372036854775808  9223372036854775807
 ull     8                     18446744073709551615
 float   4                     1.17549e-038          3.40282e+038
 double  8                     2.22507e-308          1.79769e+308
 ldouble 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::Double
			auto 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;

		// bool
		cout << setw(8) << "bool";
		cout << setw(22) << sizeof(bool);
		cout << setw(22);
		cout << setw(22);
		cout << endl;

		// char
		cout << setw(8) << "char";
		cout << setw(22) << sizeof(char);
		cout << setw(22) << (int)CHAR_MIN;
		cout << setw(22) << (int)CHAR_MAX;
		cout << endl;

		// int
		cout << setw(8) << "int";
		cout << setw(22) << sizeof(int);
		cout << setw(22) << INT_MIN;
		cout << setw(22) << INT_MAX;
		cout << endl;

		// unsigned int
		cout << setw(8) << "uint";
		cout << setw(22) << sizeof(unsigned int);
		cout << setw(22);
		cout << setw(22) << UINT_MAX;
		cout << endl;

		// short
		cout << setw(8) << "short";
		cout << setw(22) << sizeof(short);
		cout << setw(22) << SHRT_MIN;
		cout << setw(22) << SHRT_MAX;
		cout << endl;

		// unsigned short
		cout << setw(8) << "ushort";
		cout << setw(22) << sizeof(unsigned short);
		cout << setw(22);
		cout << setw(22) << USHRT_MAX;
		cout << endl;

		// long
		cout << setw(8) << "long";
		cout << setw(22) << sizeof(long);
		cout << setw(22) << LONG_MIN;
		cout << setw(22) << LONG_MAX;
		cout << endl;

		// unsigned long
		cout << 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 long
		cout << setw(8) << "ull";
		cout << setw(22) << sizeof(unsigned long long);
		cout << setw(22);
		cout << setw(22) << ULLONG_MAX;
		cout << endl;

		// float
		cout << setw(8) << "float";
		cout << setw(22) << sizeof(float);
		cout << setw(22) << FLT_MIN;
		cout << setw(22) << FLT_MAX;
		cout << endl;

		// double
		cout << setw(8) << "double";
		cout << setw(22) << sizeof(double);
		cout << setw(22) << DBL_MIN;
		cout << setw(22) << DBL_MAX;
		cout << endl;

		// long double
		cout << 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.kler.cn/a/454642.html

相关文章:

  • 阿里云新用户服务器配置
  • C++--------继承
  • IntelliJ IDEA 中 Editor > General > Appearance 设置:编辑器的视觉外观和行为
  • feign验签不通过,但是postman没问题
  • elasticsearch中使用fuzzy查询
  • 【Rust自学】7.1. Package、Crate和定义Module
  • 赋能开发者 | 麒麟信安受邀参加2024开放原子开发者大会,以技术为引领,以人才创发展
  • 解读DeepseekV3
  • Go+chromedp实现Web UI自动化测试
  • uniapp 文本转语音
  • 挑战一个月基本掌握C++(第十二天)了解命名空间,模板,预处理器
  • 前端Python应用指南(五)用FastAPI快速构建高性能API
  • 同步异步日志系统:设计模式
  • ubuntu 账号从文本中的1000,改成0,后五笔输入法等中文输入法不可用,如何改回来
  • 【Ubuntu 20.4安装截图软件 flameshot 】
  • 全面Kafka监控方案:从配置到指标
  • 【自由能系列(初级),论文解读】神经网络中,熵代表系统的不确定性,自由能则引导系统向更低能量的状态演化,而动力学则描述了系统状态随时间的变化。
  • flask后端开发(11):User模型创建+注册页面模板渲染
  • 使用Python实现自动化文档生成工具:提升文档编写效率的利器
  • STM32F103RCT6学习之一:基本开发流程
  • FileLink为企业打造了一站式的跨网安全文件共享解决方案
  • Docker使用——国内Docker的安装办法
  • 前端面试题合集(一)——HTML/CSS/Javascript/ES6
  • Kubernetes Gateway API-2-跨命名空间路由
  • 鸿蒙Next自定义相机开发时,如何解决相机在全屏预览的时候,画面会有变形和拉伸?
  • 【Agent】Chatbot、Copilot与Agent如何帮助我们的提升效率?