1.背景
之前的标题是【JAVA反序列化QT序列化内容】,觉得太大太绕,最后改为现在的标题。
本篇内容是对用JAVA解析QT(用的是QDataSteam)所输出(序列化)的内容的小结。
本文涉及类型包括:QString、QDateTime。
2. 相关技术
相关技术可以从2个方面阐述:QT的序列化和JAVA的文件读取。
(2.1)QT序列化
QT序列化相关文档:Serializing Qt Data Types,下面表格中内容是为摘录:
Qt Data Types | Serializing |
---|---|
QDate | Julian day (quint32) |
QDateTime | - Date (QDate) - Time (QTime) - 0 for Qt::LocalTime, 1 for Qt::UTC (quint8) |
QString | If the string is null: 0xFFFFFFFF (quint32) Otherwise: The string length in bytes (quint32) followed by the data in UTF-16 |
QTime | Milliseconds since midnight (quint32) |
对于相同技术栈的QT,序列化和反序列化,只需设置适合的QT版本即可。
但对于JAVA,就没那么简单了,特别是组合类型,例如上图中的QDateTime、QString。
- QDateTime类型内容,分为3个部分,固定为9字节:日期(4字节描述的朱利安天数)、时间(4字节描述的从0点的毫秒数)和时间规格标识(1字节)。
- QString类型内容,分为2个部分,长度为变长:字符串长度(4字节)和数据内容(按UTF-16)编码。
(2.2)JAVA的文件读取
(2.2.1)JAVA读取QString
final long length1 = this.fileUtil.readAsDword(fisRaw, isBigEndian, TAG0);
final String title = this.fileUtil.readAsStr(fisRaw, (int)length1, "utf-16", TAG0);
代码中,需要关注2点:
- 字节序(方法readAsDword的参数isBigEndian即是)
- 字符串的编码(方法readAsStr的参数"utf-16"即是)
(2.2.2)JAVA读取QDateTime
// Julian day (quint32)
final long julianDayNumber1 = this.fileUtil.readAsDword(fisRaw, isBigEndian, TAG0);
// Milliseconds since midnight (quint32)
final long mss1 = this.fileUtil.readAsDword(fisRaw, isBigEndian, TAG0);
// 0 for Qt::LocalTime, 1 for Qt::UTC (quint8)
final int flag1 = (255-this.fileUtil.readAsByte(fisRaw, TAG0));
Date dt11 = this.dtUtil.getDate((int)julianDayNumber1);
Date dt12 = this.dtUtil.getTime((int)mss1);
代码的核心有2点:
- 按照朱利安按天(Julian day)转换成公历日期
- 毫秒数转时间
(1)依据朱利安日数获取公历日期
/** 依据朱利安日数获取公历日期 */
public Date getDate(int jdn) {
Calendar cal = Calendar.getInstance();
cal.set(-4712, 0, 1);
cal.add(Calendar.DAY_OF_YEAR, jdn);
return cal.getTime();
}
对于(-4712, 0, 1)中的参数,涉及2点:第1是朱利安天的定义,第2是JAVA系统对年、月、日的序号的约定。
(2)依据毫秒数(从零点开始)计算时间
public Date getTime(int ms) {
Calendar cal = Calendar.getInstance();
cal.set(0, 0, 0, 0, 0, 0);
cal.set(Calendar.MILLISECOND, ms);
return cal.getTime();
}
3. 小结
本文涉及跨技术栈QT & JAVA,既然是不同的2个系统,则存在及较多不一致的约定。
例如QT系统中不存在年数为0,但JAVA系统是许可的。年、月、日的序号也不一致。