读取数据库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是 ...
随机推荐
- uniapp云打包之后华为手机推送角标不显示(有推送没角标)
小米手机上有角标,华为和OPPO没有角标 解决方法: 华为手机添加权限(可通过反编译或者离线打包添加) < uses - permission android:name="com.hu ...
- <数据结构>XDOJ314.完全二叉树的子树
问题与解答 问题描述 对一棵完全二叉树,采用自上而下.自左往右的方式从1开始编号,我们已知这个二叉树的最后一个结点是n,现在的问题是结点m所在的子树一共包括多少个结点? 输入格式 输入数据包括多行,每 ...
- 开源实践 | 携程在OceanBase的探索与实践
写在前面:选型考虑 携程于1999年创立,2016-2018年全面推进应用 MySQL 数据库,前期线上业务.前端技术等以 SQL Server 为主,后期数据库逐步从 SQL Server 转到开源 ...
- 解决VirtualBox 运行时报内存不能written
在VirtualBox 虚拟机中安装系统的时候,突然报"0x00000000指令,该内存不能written",只能强制停止,这个问题要怎么解决呢? 解决办法是恢复系统主题3个dll ...
- linux(CentOS7) 之 MySQL 5.7.30 下载及安装
一.下载 1.百度搜索mysql,进入官网(或直接进入官网https://www.mysql.com) 2.选择 downloads 3.翻到最下面,选择MySQL Community (GPL) D ...
- 初识python 之 爬虫:使用正则表达式爬取“糗事百科 - 文字版”网页数据
初识python 之 爬虫:使用正则表达式爬取"古诗文"网页数据 的兄弟篇. 详细代码如下: #!/user/bin env python # author:Simple-Sir ...
- centos7-collabora-office(在线文档编辑)
1.wget https://www.collaboraoffice.com/repos/CollaboraOnline/CODE-centos7/repodata/repomd.xml.key &a ...
- HDU 2044 一只小蜜蜂... (斐波那契数列)
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2044 题目分析:其实仔细读题就会发现其中的规律, 其中:这是一个典型的斐波那契数列. 代码如下: #i ...
- JNDI和JDBC的区别
最近也是遇见了JNDI这个概念,查了一下,网上的说法太官方,所以参考下一位老哥的博客总结下 JDBC 看到最多的就是,Java Database Connectivity (JDBC)是一个标准的Ja ...
- 关于在Vue中使用WebScoket的随笔
声明:请勿直接复制粘贴抄袭文章,若有需要,请规范转载,注明出处,谢谢! ---------------------------------------------------------------- ...