读取数据库Blob类型的文本数据
开发一个查询功能时,遇到了一个ORM的问题:数据库字段是 Blob 类型,里面实际存储的是文本数据,Java 后端代码中用字符串 String 类型去接收这个字段的数据时,报错,提示没有对应的setter方法,类型不匹配;换成 byte[] 字节数组类型去接收这个字段的数据,依然报错,同样是找不到setter方法,类型不匹配;最后只好将Java中对应的变量类型改为 java.sql.Blob 类型去接收对应的数据,不报错了,但如何取获取其中的文本数据呢?
使用的代码如下:
private String getTextFromBlob(Blob blob) {
int i = 1;
byte btArr[] = new byte[0];
try {
while (i < blob.length()) {
byte[] bytes = blob.getBytes(i, 1024);
btArr = ArrayUtils.addAll(btArr, bytes);
i += 1024;
}
return new String(btArr, "GB2312");
} catch (Exception e) {
logger.error(e.getMessage(), e);
return null;
}
}
代码逻辑并不复杂,但其实这地方有一个坑,需要注意一下。
最开始的时候写的代码并不是这样,我在 while 循环里每次拿 1024 个字节的数据,然后使用 new String(bytes,"GB2312") 得到字符串,再用 StringBuilder 把每次循环得到的字符串拼接起来,最后 stringBuilder.toString() 返回完整的字符串内容。
写完之后,测试,没问题。但紧接着,我想到了一个问题:我每次拿1024个字节,会不会正好把组成一个汉字的两个字节拆分开呢?
答案是肯定的。虽然 GB2312 编码字符集固定使用 2 个字节来存储汉字,但是 GB2312字符集在存储 ASCII 字符的时候,用的是 1 个字节来存储。也就是说,对于英文字母、数字、英文标点,GB2312 用一个字节存储;对于中文,则使用两个字节存储。这样的话就没法保证每次拿1024个字节不会把某个汉字的两个字节拆分成两段。
因为数据库中的文字都比较短,没有超过一百个字的,程序每次拿1024个字节就把所有的内容都拿完了,所以在测试中返回的文本都是正常的。改了一下代码,把 1024 改成 10,每次拿10个字节,果然出现了乱码问题,文本中的部分中文出现了乱码,而其他部分的中文是正常的。
最后改成了上面的代码,每次依然拿固定长度的字节,然后把结果都放到一个 byte[] 字节数组里,等拿完所有的字节之后,使用 new String(bytes,"GB2312") 得到字符串,这样就避免了上面的问题。实际测试之后(每次拿10个字节),返回的文本正常,没有乱码。
当然这个代码并不完美,代码里使用 apache collections 包里的 ArrayUtils.addAll(byte[] b,byte[] c) 方法来把两个字节数据拼到一块,其内部的实现方法就是创建一个大数组,然后把两个数据的内容依次放进去,这样的话每次都要开辟一个新的内存空间,效率并不高,如果数据量大的话,会有很大的性能开销。
一个比较好的解决方案就是:自己定义一个大数组,每次循环把取到的内容放到这个大数组对应的位置上,避免每次都要 new 一个数组出来,性能更好。缺点就是代码逻辑会复杂一些。
总结:
在对字节流进行读取、拆分的时候,需要注意会不会把表示一个字符的几个字节给误拆分了,这样最后得到的内容会有部分乱码。像常见的GB2312、UTF-8、UTF-16等都是变长的方式进行字节存储,不能进行拆分;而像 UCS-2 这样的字符集,固定使用两个字节存储,按偶数进行拆分就没问题。
读取数据库Blob类型的文本数据的更多相关文章
- python 数据库 blob类型 转字符串
例如: 从数据库里读出了blob类型,如 z = b'61736467' 在py里转化成字符串:bytes.fromhex(z).decode('utf8')
- mysql数据库中导入txt文本数据的方法
安装好MySQL和Navicat 8 for MySQL 通过Navicat 8 for MySQL创建数据库test. 2 在数据库test上创建测试数据表student(主键ID,姓名,年龄,学 ...
- jsp页面file标签上传图片以及blob类型数据库存取。
我的jsp页面表单如下: <form name="form1" action="/YiQu/AddUserServlet?jurisdiction=1" ...
- python读取数据库并把数据写入本地文件
一,介绍 上周用jmeter做性能测试时,接口B传入的参数需要依赖接口A生成的借贷申请ID,接口A运行完需要把生成的借贷申请ID导出来到一个文件,作为参数传给接口B,刚开始的时候,手动去数据库倒, 倒 ...
- pandas.read_sql_query()读取数据库数据用chunksize的坑
最近一项工作需要读取数据库中1500万条数据,考虑到数据量太大,不方便直接一次性读取,不然会内存爆炸.想到用pandas.read_sql_query()里有一个chunksize可以分批返回chun ...
- 插入与读取Blob类型数据
BlobTest package com.aff.PreparedStatement; import java.io.File; import java.io.FileInputStream; imp ...
- 读取和写入blob类型数据
读写oracle blob类型 http://zyw090111.iteye.com/blog/607869 http://blog.csdn.net/jeryjeryjery/article/de ...
- 在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。
在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除. 作者:邵盛松 2009-09-05 前言 1关于的BLOB(Binary)数据的存储和读取功能主要参考了MSDN上的一篇& ...
- 使用PreparedStatement向数据表中插入、修改、删除、获取Blob类型的数据
使用PreparedStatement向数据表中插入.修改.删除.获取Blob类型的数据 2014-09-07 20:17 Blob介绍 BLOB类型的字段用于存储二进制数据 MySQL中,BLOB是 ...
随机推荐
- Tomcat 服务器的端口会与其他的服务器端口发生冲突,此时则需要修改 Tomcat 服务器的端口
查看相关知识 查看相关练习 Tomcat 服务器的端口会与其他的服务器端口发生冲突,此时则需要修改 Tomcat 服务器的端口 实现步骤: 1.找到 Tomcat 服务器安装目录下的 conf 文件夹 ...
- Java初学者作业——使用switch结构实现一个简单的购物计划
返回本章节 返回作业目录 需求说明: 使用switch结构实现一个购物计划,计划为:星期一.星期三.星期五购买伊利牛奶和面包,星期二.星期四购买苹果和香蕉,星期六.星期日购买啤酒和周黑鸭. 实现思路: ...
- 编写Java程序,创建一个 Person 类,该类中有一个类成员变量 country、一个实例变量 name 和另一个实例变量 age。
返回本章节 返回作业目录 需求说明: 创建一个 Person 类,该类中有一个类成员变量 country.一个实例变量 name 和另一个实例变量 age. country 表示地区,name 表示姓 ...
- SpringBoot集成MyBatis-Plus代码生成器(Dao)
1.说明 本文基于SpringBoot集成MyBatis-Plus代码生成器, 把原来生成Entity.Mapper.Mapper XML.Service.Controller等各个模块的代码, 修改 ...
- docker构建.net core运行的镜像
在docker很火的今天,越来越多的应用现在都在往docker上迁移,.net core怎么能落后? 项目要运行在docker上,我们需要先制作镜像,可以基于centos来制作,当然也可以基于Ubun ...
- Nginx入门--从核心配置与动静分离开始
写在前面 优化我们项目,服务器部署,不仅仅可以是分布式,Nginx一样可以通过动静分离,负载均衡来减轻我们服务器的压力.Nginx的知识链,学习周期相对比较长,博主也是刚刚入门,这篇就先从实现基础的动 ...
- .NET 微服务——CI/CD(4):避坑和一点经验
如果你看过之前几篇文章,应该已经Jenkins成功搭建了CICD环境,但是进入正式环境会有一些坑,不注意中招的话很难受,这里总结一下,避免重复消耗精力. 后门漏洞 Jenkins有后门,这是个老问题了 ...
- mysql 5.7.29 在centos7.6下超简单的本地yum源安装与配置
目录 生成yum源元数据 从网易镜像站下载MySQL 5.7 的 bundle包 创建文件 mysql-local.repo 执行yum install命令 生成yum源元数据 createrepo ...
- WebLogic任意文件上传漏洞(CVE-2019-2725)
一,漏洞介绍 1.1漏洞简介 Oracle weblogic反序列化远程命令执行漏洞,是根据weblogic的xmldecoder反序列化漏洞,只是通过构造巧妙的利用链可以对Oracle官方历年来针对 ...
- 机器学习|线性回归三大评价指标实现『MAE, MSE, MAPE』(Python语言描述)
原文地址 ?传送门 对于回归预测结果,通常会有平均绝对误差.平均绝对百分比误差.均方误差等多个指标进行评价.这里,我们先介绍最常用的3个: 平均绝对误差(MAE) 就是绝对误差的平均值,它的计算公式如 ...