读取数据库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是 ...
随机推荐
- [C++]使用vector描述线性表定义及基本操作
#ifndef VECTORLIST_H #define VECTORLIST_H #include<iostream> #include"linearlist.h" ...
- 【jvm】03-写了final就是常量池了么
[jvm]03-写了final就是常量池了么 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点 ...
- rabbimq集群搭建报错:Error: unable TO perform an operation ON node 'rabbit@test3'. Please see diagnostics information AND suggestions below.
在搭建rabbitmq集群的时候,添加内存节点时,抛出异常:Error: unable TO perform an operation ON node 'rabbit@test3'. Please s ...
- PaperRead - Comparison of Fundamental Mesh Smoothing Algorithms for Medical Surface Models
几种常见平滑算法的实现可以参见: 几种网格平滑算法的实现 - Jumanco&Hide - 博客园 (cnblogs.com) 1 Introduction 图像空间中相关的组织和结构,变换成 ...
- Swoole 中使用 PDO 连接池、Redis 连接池、Mysqli 连接池
连接池使用说明 所有连接池的实现均基于 ConnectionPool 原始连接池: 连接池的底层原理是基于 Channel 的自动调度: 开发者需要自己保证归还的连接是可重用的: 若连接不可重用,需要 ...
- Flask_获取请求信息(三)
引用request的方法: from flask import request 与Django不同的是,flask是不需要将request对象作为第一个参数传入视图函数,他的request对象是来自于 ...
- Go语言系列之函数
函数是组织好的.可重复使用的.用于执行指定任务的代码块.本文介绍了Go语言中函数的相关内容. 函数 Go语言中支持函数.匿名函数和闭包,并且函数在Go语言中属于"一等公民". 函数 ...
- 关于less使用初学者常犯错误
1.多层嵌套 2.定义变量复用性不高 3.方法定义多余参数.
- Spring Security 接口认证鉴权入门实践指南
目录 前言 SpringBoot 示例 SpringBoot pom.xml SpringBoot application.yml SpringBoot IndexController SpringB ...
- MMI开机时间偏长
Mini版本开机时间长 Mini版本开机时间长1. Problem Description:2. Analysis:3. Solution:4. Summary: 1. Problem Descr ...