挖一挖:PostgreSQL Java里的double类型存储到varchar精度丢失问题
前言
大概故事是这样的,PostgreSQL数据库,表结构:
create table t1(a varchar);
然后使用标准的Java jdbc去插入数据,其基本代码如下:
import java.sql.*;
public class PgDoubleTest {public static void main(String[] args) {Connection connection = null;ResultSet resultSet = null;PreparedStatement ps= null;try {// 连接到数据库connection = DriverManager.getConnection("jdbc:postgresql://192.168.0.6:5432/mydb", "mydb", "test123");String sql="insert into t1 values(?)";ps = connection.prepareStatement(sql);ps.setObject(1,new Double(48));ps.execute();ps.setObject(1,new Double(48.1));ps.execute();ps.setObject(1,new Double(48.9));ps.execute();} catch (SQLException e) {e.printStackTrace();} finally {try {if (ps != null) {ps.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}
}
发现 PostgreSQL11和12及以后的版本,插入到表t1中的记录值不一样。
PG11中的结果:
mydb=# select * from t1;a
---------------------4848.100000000000001448.8999999999999986
(3 rows)
PG12及后续版本的结果:
mydb=# select * from t1;a
------4848.148.9
(3 rows)
这个问题如何分析?
分析
上边的Java代码片段,采用的都是完全相同的jdbc driver:
<dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><version>42.7.3</version></dependency>
有几种可能性,驱动层根据服务器端不同的版本,发送的数据就完全不同。或者服务器端根据客户端来的数据,处理有所不同。
检查下SQL日志
我们分别打开:postgresql.conf,开启记录所有的SQL
log_statement = 'all' # none, ddl, mod, all
于是看到,PG11的日志是这样的:
2024-03-30 11:20:46.235 CST [13553] LOG: execute <unnamed>: SET extra_float_digits = 3
2024-03-30 11:20:46.236 CST [13553] LOG: execute <unnamed>: SET application_name = 'PostgreSQL JDBC Driver'
2024-03-30 11:20:46.262 CST [13553] LOG: execute <unnamed>: insert into t1 values($1)
2024-03-30 11:20:46.262 CST [13553] DETAIL: parameters: $1 = '48'
2024-03-30 11:20:46.265 CST [13553] LOG: execute <unnamed>: insert into t1 values($1)
2024-03-30 11:20:46.265 CST [13553] DETAIL: parameters: $1 = '48.1000000000000014'
2024-03-30 11:20:46.266 CST [13553] LOG: execute <unnamed>: insert into t1 values($1)
2024-03-30 11:20:46.266 CST [13553] DETAIL: parameters: $1 = '48.8999999999999986'
2024-03-30 11:21:11.696 CST [13555] LOG: statement: select * from t1;
而PG12的日志是这样的:
2024-03-30 10:45:30.172 CST [2700] LOG: execute <unnamed>: SET extra_float_digits = 3
2024-03-30 10:45:30.173 CST [2700] LOG: execute <unnamed>: SET application_name = 'PostgreSQL JDBC Driver'
2024-03-30 10:45:30.197 CST [2700] LOG: execute <unnamed>: insert into t1 values($1)
2024-03-30 10:45:30.197 CST [2700] DETAIL: parameters: $1 = '48'
2024-03-30 10:45:30.199 CST [2700] LOG: execute <unnamed>: insert into t1 values($1)
2024-03-30 10:45:30.199 CST [2700] DETAIL: parameters: $1 = '48.1'
2024-03-30 10:45:30.200 CST [2700] LOG: execute <unnamed>: insert into t1 values($1)
2024-03-30 10:45:30.200 CST [2700] DETAIL: parameters: $1 = '48.9'
也就是说到了服务器端,绑定参数值的时候,就已经不同了。PG11里头,传的字符串值已经有了变化了。很有意思的东西。我们不忙着下结论。
既然Server端的log不能判定,我们可以看看driver层的详细的log信息。这个需要设置logging.properties. 详情可以参考文档:https://jdbc.postgresql.org/documentation/logging/
查看JDBC客户端driver层日志
PG12的相关日志有如下关键内容:
三月 31, 2024 3:49:55 下午 org.postgresql.Driver connect
详细: Connecting with URL: jdbc:postgresql://192.168.0.6:5555/mydb?loggerLevel=TRACE&loggerFile=jdbc.log
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection <init>
详细: PostgreSQL JDBC Driver 42.7.3
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection setDefaultFetchSize
详细: setDefaultFetchSize = 0非常详细: <=BE ParameterStatus(server_version = 12.11)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveParameterStatus
非常详细: <=BE ParameterStatus(session_authorization = mydb)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveParameterStatus
非常详细: <=BE ParameterStatus(standard_conforming_strings = on)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveParameterStatus
非常详细: <=BE ParameterStatus(TimeZone = Asia/Shanghai)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl readStartupMessages
非常详细: <=BE BackendKeyData(pid=8,855,ckey=-1,722,642,031)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细: <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细: simple execute, handler=org.postgresql.core.SetupQueryRunner$SimpleResultHandler@614ddd49, maxRows=0, fetchSize=0, flags=1,047
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细: FE=> Parse(stmt=null,query="SET extra_float_digits = 3",oids={})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细: FE=> Bind(stmt=null,portal=null)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细: FE=> Execute(portal=null,limit=1)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细: FE=> Sync
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE ParseComplete [null]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE BindComplete [unnamed]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细: <=BE CommandStatus(SET)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细: <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细: simple execute, handler=org.postgresql.core.SetupQueryRunner$SimpleResultHandler@711f39f9, maxRows=0, fetchSize=0, flags=1,047
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细: FE=> Parse(stmt=null,query="SET application_name = 'PostgreSQL JDBC Driver'",oids={})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
....
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细: <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection <init>
非常详细: types using binary send = OID_ARRAY,UUID,BYTEA,INT8,INT2,INT4,POINT,TIMESTAMP,BOX,TIMESTAMPTZ,NUMERIC,BYTEA_ARRAY,INT2_ARRAY,INT4_ARRAY,TEXT_ARRAY,TIMETZ,VARCHAR_ARRAY,INT8_ARRAY,TIME,FLOAT4,FLOAT8,FLOAT4_ARRAY,FLOAT8_ARRAY
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection <init>
非常详细: types using binary receive = OID_ARRAY,UUID,BYTEA,INT8,INT2,INT4,POINT,TIMESTAMP,BOX,TIMESTAMPTZ,NUMERIC,BYTEA_ARRAY,INT2_ARRAY,INT4_ARRAY,TEXT_ARRAY,TIMETZ,VARCHAR_ARRAY,INT8_ARRAY,DATE,TIME,FLOAT4,FLOAT8,FLOAT4_ARRAY,FLOAT8_ARRAY
三月 31, 2024 3:49:55 下午 org.postgresql.jdbc.PgConnection <init>
非常详细: integer date/time = true
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@2353b3e6, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细: FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.0'::double precision)>,type=FLOAT8)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
非常详细: FE=> Describe(portal=null)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细: FE=> Execute(portal=null,limit=0)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细: FE=> Sync
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE ParseComplete [null]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE BindComplete [unnamed]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE NoData
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细: <=BE CommandStatus(INSERT 0 1)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细: <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@42f93a98, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细: FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.1'::double precision)>,type=FLOAT8)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
非常详细: FE=> Describe(portal=null)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细: FE=> Execute(portal=null,limit=0)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细: FE=> Sync
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE ParseComplete [null]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE BindComplete [unnamed]
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE NoData
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细: <=BE CommandStatus(INSERT 0 1)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细: <=BE ReadyForQuery(I)
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@c46bcd4, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细: FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:49:55 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.9'::double precision)>,type=FLOAT8)
我们看到上边有明显的:
非常详细: <=BE ParameterStatus(server_version = 12.11)
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.0'::double precision)>,type=FLOAT8)
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.1'::double precision)>,type=FLOAT8)
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.9'::double precision)>,type=FLOAT8)
FE=> Parse(stmt=null,query="SET extra_float_digits = 3",oids={})
再看看PG11下边的详细日志:
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveParameterStatus
非常详细: <=BE ParameterStatus(server_version = 11.22 [by Sean])
。。
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.0'::double precision)>,type=FLOAT8)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
非常详细: FE=> Describe(portal=null)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细: FE=> Execute(portal=null,limit=0)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细: FE=> Sync
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE ParseComplete [null]
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE BindComplete [unnamed]
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE NoData
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细: <=BE CommandStatus(INSERT 0 1)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细: <=BE ReadyForQuery(I)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@42f93a98, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细: FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.1'::double precision)>,type=FLOAT8)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendDescribePortal
非常详细: FE=> Describe(portal=null)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendExecute
非常详细: FE=> Execute(portal=null,limit=0)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendSync
非常详细: FE=> Sync
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE ParseComplete [null]
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE BindComplete [unnamed]
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl processResults
非常详细: <=BE NoData
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveCommandStatus
非常详细: <=BE CommandStatus(INSERT 0 1)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl receiveRFQ
非常详细: <=BE ReadyForQuery(I)
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl execute
非常详细: simple execute, handler=org.postgresql.jdbc.PgStatement$StatementResultHandler@c46bcd4, maxRows=0, fetchSize=0, flags=17
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendParse
非常详细: FE=> Parse(stmt=null,query="insert into t1 values($1)",oids={701})
三月 31, 2024 3:59:17 下午 org.postgresql.core.v3.QueryExecutorImpl sendBind
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.9'::double precision)>,type=FLOAT8)
找出关键的几行:
非常详细: <=BE ParameterStatus(server_version = 11.22 [by Sean])
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.0'::double precision)>,type=FLOAT8)
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.1'::double precision)>,type=FLOAT8)
非常详细: FE=> Bind(stmt=null,portal=null,$1=<('48.9'::double precision)>,type=FLOAT8)
FE=> Parse(stmt=null,query="SET extra_float_digits = 3",oids={})
比较后的总结、模拟重现与深挖
从驱动层来看,发送过去的内容或指令应该是一样的。只是Server端对于类似于如下的binding,分别有精度损失或没有精度损失:
$1=<('48.1'::double precision)>,type=FLOAT8)
我们看看PG11下边的一些行为:
show extra_float_digits;extra_float_digits
--------------------0
(1 row)select '48.1'::float8;float8
--------48.1
(1 row)SET extra_float_digits = 3;
SET
mydb=# select '48.9'::float8;float8
---------------------48.8999999999999986
(1 row)
看到了吗?在extra_float_digits = 3;时,结果就出来了。'48.8999999999999986'
而到了PG12,结果是这样:
mydb=# show extra_float_digits;extra_float_digits
--------------------1
(1 row)mydb=# select '48.1'::double precision;float8
--------48.1
(1 row)mydb=# SET extra_float_digits = 3;
SET
mydb=# select '48.1'::double precision;float8
--------48.1
(1 row)
所以, 从上边的分析来看,是server端对于extra_float_digits = 3时,在字符串转到float8 (double precision)时的行为不一样导致的。
至此,真相大白。
我们也可以看下参数extra_float_digits的真实含义:
https://postgresqlco.nf/doc/zh/param/extra_float_digits/ :Sets the number of digits displayed for floating-point values
这个参数调整用于文本输出浮点值的位数,包括float4,float8以及几何数据类型。
如果值为1(默认值)或更高,浮点值被输出为最短-精度格式;参见datatype-float。实际生成的位数只取决于输出的值,而不取决于此参数的值。float8 值最多需要 17 位数字,float4值最多需要9位数字。这种格式既快速又精确,在正确读取时精确地保留了原始的二进制浮点值。为了历史兼容性,允许的值最大为3。
如果值为零或负,则输出四舍五入为给定的十进制精度。使用的精度是根据此参数的值减小的类型((
FLT_DIG
或DBL_DIG
,视情况而定)的标准位数。(例如,指定 -1 将导致float4 值输出四舍五入为 5 位有效数字,而float8值四舍五入为 14 位。) 此格式较慢,不会保留二进制浮点值的所有位,但可能令人更易于阅读。此参数的含义,以及其默认值,在 PostgreSQL 12 中发生了变化; 参见 datatype-float 以便进一步讨论。
我在:PostgreSQL, 留心对应的BigDecimal,Float,Double几种Java类型也有关于float8类型的详细介绍 。
总结
分析这类问题,在源码介入之前,通过两端的日志进行对比分析,往往也能抓到蛛丝马迹。进而可以进一步进行挖掘和分析。上边的Java代码,最后都可以通过简单的SQL片段来重现。
参考:
https://www.enterprisedb.com/blog/jdbc-logging-using-javautillogging
https://jdbc.postgresql.org/documentation/logging/
https://postgresqlco.nf/doc/zh/param/extra_float_digits/
相关文章:
挖一挖:PostgreSQL Java里的double类型存储到varchar精度丢失问题
前言 大概故事是这样的,PostgreSQL数据库,表结构: create table t1(a varchar);然后使用标准的Java jdbc去插入数据,其基本代码如下: import java.sql.*; public class PgDoubleTest {public static void main(Stri…...
函数对象基本使用
一、函数对象概念 1.重载函数调用操作符的类,其对象常称为函数对象 2.函数对象使用重载的()时,行为类似函数调用,也叫仿函数 本质: 函数对象(仿函数)是一个类,不是一个函数 二、函数对象使用 特点: 函…...
浅谈HTTP
浅谈HTTP 要通过netty实现HTTP服务器(或者客户端),首先你要了解HTTP协议。 HTTP在客户端 - 服务器计算模型中用作请求 - 响应协议。 例如,web浏览器可以是客户端,并且在托管网站的计算机上运行的应用程序可以是服务器。 客户端向服务器提交…...
HarmonyOS NEXT应用开发之@Provide装饰器和\@Consume装饰器:与后代组件双向同步
Provide和Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,Provide和Consume摆脱参数传递机制的束缚,实现跨层级传递。 其中Provide装饰的变…...
Docker 安装 | 部署MySQL 8.x 初始设置
1、准备工作 如果不想看前面的废话请直接右边目录跳到 运行容器 处 默认你已经有 docker 环境。 Windows 推荐 Docker Desktop (下载地址)并基于 WSL2 运行 Docker 环境 mac 推荐 Orbstack (下载地址)(这个很节省资源&…...
linux三剑客之流编辑器sed
sed(stream editor)是Linux和Unix系统中一个非常强大的文本处理工具。它主要用于对文本数据进行过滤和转换。sed 可以在不打开文件的情况下,直接对输入流进行操作,并且可以将结果输出到标准输出或文件。 基本语法: s…...
【Android Studio】上位机-安卓系统手机-蓝牙调试助手
【Android Studio】上位机-安卓系统手机-蓝牙调试助手 文章目录 前言AS官网一、手机配置二、移植工程三、配置四、BUG五、Java语言总结 前言 提示:以下是本篇文章正文内容,下面案例可供参考 AS官网 AS官网 一、手机配置 Android Studio 下真机调试 …...
怎样把学浪购买的课程下载下来
如何把学浪已购买的课程下载下来?这里就教大家一个方法,利用一个工具轻轻松松把视频下载下来 这个工具我打包成压缩包了,有需要的自己取一下 链接:https://pan.baidu.com/s/1y7vcqILToULrYApxfEzj_Q?pwdkqvj 提取码:kqvj --来自百度网盘超级会员V1…...
SD-WAN如何解决更有性价比地跨境网络问题
云桥通SD-WAN利用智能路由和负载均衡技术,优化数据传输路径,提高网络性能和可靠性。这意味着数据在跨国传输时可以更快到达目的地,减少延迟和丢包率。跨境SD-WAN提高了网络连接速度和质量,使用户能够更快地访问跨国业务所需的资源…...
第15章 File类与IO流
一 java.io.File类的使用 1.1 概述 File类及本章下的各种流,都定义在java.io包下。一个File对象代表硬盘或网络中可能存在的一个文件或者文件目录(俗称文件夹),与平台无关。(体会万事万物皆对象)File 能新…...
C语言基础语法-教案16(从小白到劝退之结构体初阶)
最近给大家争取到一个 深夜福利 保证你在深夜手机刷到 嘎嘎香~ 那就是 大流量卡 缺点:月租太便宜 185GB~ 100分钟通话时长~ 长期套餐~ 畅想自由的气息 流量自由的同时还拥有超长通话,而且免费领取。 名额有限,咱们废话不多说直接上…...
Linux:ip和ip协议的初步认识
文章目录 ip协议基本认识ip协议的报头网段划分ip的类型划分 ip协议基本认识 前面对于TCP的内容已经基本结束了,那么这也就意味着在传输层也已经结束了,那么下一步要进入的是的是网络层,网络层中也有很多种协议,这里主要进行解析的…...
Android12 简单的共享内存驱动实现 参考Ashmem
Android12 共享内存驱动实现 SOC:RK3568 system:Android12 概述: 1. 概述 Ashmem(Anonymous Shared Memory,Android 匿名共享内存),它基于 mmap 系统调用,可以让不同进程将同一段…...
物理安全和逻辑安全在信息安全中的重要作用
在信息时代,信息安全已经成为企业和个人不可或缺的重要组成部分。物理安全和逻辑安全作为信息安全的两大支柱,发挥着至关重要的作用。 什么是物理安全和逻辑安全? 物理安全是指通过技术手段,对计算机设备、网络设备、数据中心等…...
每日一题 --- 滑动窗口最大值[力扣][Go]
滑动窗口最大值 题目:239. 滑动窗口最大值 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1࿱…...
TensorBoard可视化+Confustion Matrix Drawing
for later~ 代码阅读 1. 加载trainset import argparse import logging import os import numpy as npimport torch from torch import distributed from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriterfrom backbones import get_…...
012——LED模块驱动开发(基于I.MX6uLL)
目录 一、 硬件原理图 二、 驱动程序 三、 应用程序 四、 Makefile 五、操作 一、 硬件原理图 又是非常经典的点灯环节 ,每次学新语言第一步都是hello world,拿到新板子或者学习新的操作系统,第一步就是点灯。 LED 的驱动方式࿰…...
基于springboot实现房屋租赁管理系统项目【项目源码+论文说明】计算机毕业设计
基于springboot实现房屋租赁系统演示 摘要 房屋是人类生活栖息的重要场所,随着城市中的流动人口的增多,人们对房屋租赁需求越来越高,为满足用户查询房屋、预约看房、房屋租赁的需求,特开发了本基于Spring Boot的房屋租赁系统。 …...
168.乐理基础-中古调式概述
如果到这五线谱还没记住还不认识的话去看102.五线谱-高音谱号与103.五线谱-低音谱号这两个里,这里面有五线谱对应的音名,对比着看 如果不认识调号去看112.五线谱的调号(一)、113.五线谱的调号(二)、114.快…...
【项目实战】【Docker】【Git】【Linux】部署V2rayA项目
今天着手了一个全新领域的项目,从完全没有头绪到成功运行,记录一下具体的部署流程 github项目链接V2rayA 一开始拿到以后完全没有抓手,去阅读了一下他的帮助文档 写着能用docker运行,就去下载了一个Docker配置了一下 拉取代码到…...
mac 切换 jdk
查看 mac 上都有哪些版本 /usr/libexec/java_home -V看准版本切换 按前缀切换 比如 export JAVA_HOME/usr/libexec/java_home -v 1.8这样会随机一个 1.8 的 如果想再确定一个比如 openjdk export JAVA_HOME/usr/libexec/java_home -v 1.8.0_292这个方式是临时的,…...
MD5加密返回32位密文字符串
前言: 项目中需要调用其他系统的 api 接口,接口使用的是按一定规则生成 MD5 密文作为签名来进行身份验证,本文仅记录 32 位 MD5 密文的生成方式,仅供参考。 什么是MD5 加密? MD5 加密是一种加密算法,MD5…...
npm常用命令技巧
NPM (Node Package Manager) 是 JavaScript 的包管理工具,广泛用于管理项目中的依赖。无论是前端项目还是Node.js后端项目,NPM 都扮演着重要的角色。本文将介绍 NPM 中常用的几个命令,并提供相应的代码示例。 1. 初始化项目:npm …...
intellij idea 使用git撤销(取消)commit
git撤销(取消) 未 push的 commit Git,选择分支后,右键 Undo Commit ,会把这个 commit 撤销。 git撤销(取消) 已经 push 的 commit 备份分支内容: 选中分支, 新建 分支,避免后续因为操作不当,导…...
【计算机网络】四层负载均衡和七层负载均衡
前言 1、分层方式 首先我们知道,在计算机网络中,常用的协议分层方式:OSI和TCP/IP,以及实际生产中使用的协议划分方式。 在OSI中,各层的职责如下: 应用层:对软件提供接口以使程序能使用网络服…...
IP-guard WebServer 任意文件读取漏洞复现
0x01 产品简介 IP-guard是由溢信科技股份有限公司开发的一款终端安全管理软件,旨在帮助企业保护终端设备安全、数据安全、管理网络使用和简化IT系统管理。 0x02 漏洞概述 由于IP-guard WebServer /ipg/static/appr/lib/flexpaper/php/view.php接口处未对用户输入的数据进行严…...
【IoTDB 线上小课 01】我们聊聊“金三银四”下的开源
关于 IoTDB,关于物联网,关于时序数据库,关于开源...你是否仍有很多疑问? 除了自己钻研文档,群里与各位“大佬”的沟通,你是否还希望能够有个学习“捷径”? 天谋科技发起社区小伙伴,正…...
2024053期传足14场胜负前瞻
2024053期售止时间为4月6日(周六)21点00分,敬请留意: 本期深盘多,1.5以下赔率1场,1.5-2.0赔率8场,其他场次是平半盘、平盘。本期14场难度中等。以下为基础盘前瞻,大家可根据自身判断…...
C语言------冒泡法排序
一.前情提要 1.介绍 冒泡法排序法: 1)冒泡排序(Bubble Sort)是一种简单的排序算法,它重复地遍历要排序的列表,一次比较相邻的两个元素,并且如果它们的顺序错误就将它们交换过来。重复这个过程直到没有需…...
C#(C Sharp)学习笔记_Enum枚举类型【十三】
什么是枚举类型 枚举类型(Enum) 是由基础整型数值类型的一组命名常量定义的值类型。枚举包含自己的值,但不能继承或传递继承。 语法 // enum enum_name // enum_name variable enum_name.enum_value// 定义一个枚举类型——例如: enum enum_name {va…...
网站开发模式分为/长春seo网站排名
06-9-27在网吧里,任何时间都会有人在吃饭,有人在睡觉,有人在玩。不论是清晨,中午,还是深夜,都有一些人挺不住了,他们用疲惫无神的双眼仔细注视着屏幕,仿佛创作中的马克思。他们是铁人…...
深圳做网站推广公司哪家好/制造企业网站建设
范式:英文名称是 Normal Form 第一范式 数据库表中的所有字段值都是不可分解的原子值 例如:这样一个表:【联系人】(姓名,性别,电话) 如果在实际场景中,一个联系人有家庭电话和公司…...
南昌网站排名优化费用/百度网盘私人资源链接
背景 服务器强制断电 -- 启动报错错误截图 解决办法 #: xfs_repair -v -L /dev/dm-0 #: reboot...
商城类网站设计制作/搜索引擎优化技术有哪些
例如: JSON字符串:var str1 { "name": "cxh", "sex": "man" }; JSON对象:var obj { "name": "cxh", "sex": "man" }; 1、在js中把json字符串转json对象的方法不止一种࿰…...
网站建设 年终总结/优化seo教程技术
要做微信小程序首先要对html,css,js有一定的基础,还有对微信小程序的API也要非常熟悉 我将该教程分为以下三篇 微信小程序日记——高仿知乎日报(上)微信小程序日记——高仿知乎日报(中)微信小程…...
外贸wordpress主题/app推广平台排行榜
燕山大学计算机组成原理硕士研究生入学考试大纲 燕山大学计算机组成原理硕士研究生入学考试大纲 考研加油站收集整理 http://doc.xuehai.net《计算机组成原理 》考研复习教学大纲【指定教学参考书】:计算机组成原理;哈尔滨工业大学:唐朔飞编著…...