String之-如何取得精确byte长度字符串
背景:公司生产线上出现异常,报的错是记录日志时数据库长度超出,导致异常,经查询发现是由于在计算byte长度时出了问题。
问题代码:
operatorLog.setOperAfterData(updateString.substring(0,updateString.getBytes("gbk").length > 1024?1024-(updateString.getBytes("gbk").length - updateString.length()):updateString.length()));
只有一行,这么长一行代码,压根没法看,分解成如下代码:
int defaultLen = updateString.length();
int gbkLen = updateString.getBytes("gbk").length;
operatorLog.setOperAfterData(updateString.substring(0,
defaultLen > 1024 ? 1024 - (gbkLen - defaultLen) : defaultLen));
笔者目地是想让保存的日志长度限制为1024个字节-byte(不管中文还是英文);当文本中出现中文,一个字符占用两个bytes,但是英文只占用一个byte,首先得计算出文字中包含的中文字符个数,知道差别后不难得出中文长度为:gbkLen - defaultLen,假设字符长度为1025,里面中文有5个,此时gbkLength = 1030, defaultLen = 1025,此时得出的子字符串为1024 - 5 = 1019个字符,其实此时能保证这1019能够存储在1024字节的数据库字段中,因为这1019字符长度肯定不会超过1024;这是作者想要的目地
发生问题场景:
当字符里全是中文的时候会出现什么问题,比如1025个汉字,那得到的字符将是1024 - 1025 = -1,那在取子串的时候updateString.substring(0, -1);,这个时候就发生了我们在生产上跑的异常,数组越界,不可能取索引为-1的元素的值
当时想的解决办法:
当时就有点被绕进去了,最后写出来的代码竟然和原作者差不多一样,只是在最前面加了先取原串的1024个字符,这样确实是当汉字长度小于1024时,问题都好解决,但是实际情况往往不是这样的
问题依然出现:
目标是为了取得1024个字节,但是取得的值完全不对,此时假设字符串长度为513,全为汉字,做为字符串存至数据库时会超出长度1024,此时字节长度为1026
简单解决:
最后由于我们只是简单的记录日志,不做过多处理,决定只取512长度,超过512就不取了
真正解决:
在网上搜索后找到真正的解决办法:
使用循环对字条串的每个字符进行是否为中文判断或都判断将字符一个个读出来,取到规定长度:
String.valueOf(c).getBytes("GBK").length > 1
参考:
http://jingyan.baidu.com/article/1709ad80d383d44634c4f0dc.html
http://www.cnblogs.com/myphoebe/archive/2011/12/20/2294171.html
引伸:
Q: oracle在对字符进行存储时到底使用的是哪种方式,bytes?char?
A: 在定义时,oracle默认是以byte定义的,就是说如果定义成varchar(20), 理论上来说只能存储10个汉字,但对不同编码方式来说,又不一样,一个汉字在oracle中可能会占3个byte,这个是由oracle本身决定,有方法可以解决此问题,在定义表格时这样字义
create table ABC_TABLE (A_FIELD varchar2(20 char))
就表示字段A_FIELD会以字符存储,而不是以字节,当然对数据库也可以进行配置,参考以下:
http://doingwell.iteye.com/blog/972938
http://blog.csdn.net/yh555/article/details/6890000
String之-如何取得精确byte长度字符串的更多相关文章
- C#中字节数组byte[]和字符串string类型的相互转换
C#中字节数组byte[]和字符串string类型的相互转换: string转byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBy ...
- leetCode题解之寻找string中最后一个word的长度
1.题目描述 返回一个 string中最后一个单词的长度.单词定义为没有空格的连续的字符,比如 ‘a’,'akkk'. 2.问题分析 从后向前扫描,如果string是以空格‘ ’结尾的,就不用计数, ...
- asp.net AES加密跟PHP的一致,将加密的2进制byte[]转换为16进制byte[] 的字符串获得
<?php class AESUtil { public static function encrypt($input, $key) { $size = mcrypt_get_block_siz ...
- Application.StartupPath获取执行文件路径substring()取特定长度字符串取得根目录
Application.StartupPath获取执行文件路径substring()取特定长度字符串取得根目录 2012-07-20 10:48 257人阅读 评论(0) 收藏 举报 path usi ...
- Java String类相关知识梳理(含字符串常量池(String Pool)知识)
目录 1. String类是什么 1.1 定义 1.2 类结构 1.3 所在的包 2. String类的底层数据结构 3. 关于 intern() 方法(重点) 3.1 作用 3.2 字符串常量池(S ...
- String 对象是不动态改变长度的
在java里 String 对象是不动态改变长度的,只有先转化成StringBuffer,插入处理后在转回. 如 StringBuffer str = new StringBuffer("T ...
- byte[] 与字符串转换
//取值之后进行 StringBuffer buffer=new StringBuffer(); for (int i = 0; i < enBytes.length; i++) { if(i! ...
- C语言 realloc为什么要有返回值,realloc返回值具体解释/(解决随意长度字符串输入问题)。
在C语言操作中会用到大量的内存操作,当中非经常常使用的一个是realloc(). 由字面意思能够知道,该函数的作用是用于又一次分配内存. 使用方式例如以下: NewPtr=(数据类型*)realloc ...
- C#利用 string.Join 泛型集合快速转换拼接字符串
C#利用 string.Join 泛型集合快速转换拼接字符串 List<int> superior_list = new List<int>(); superior_list. ...
随机推荐
- ubuntu14.04 server 安装vmware worktation 12
0) Do the basic system installation of Ubuntu 14.04 LTS (Server or Desktop) 1) wget the installer wg ...
- C# 毕业证书打印《三》
打印很关键的方法,打印方法DataPrint(),将你要打印的数据信息发送到打印机就可以了,打印机将自动处理. public void DataPrint() { try { PrintDocumen ...
- centos7删除已经安装的docker
centos下可以使用yum来删除docker. 列出docker包的具体的名字. $ yum list installed | grep docker docker-engine.x86_64 -0 ...
- iOS 关于AFNetworking ssl 待完成
先普及下基本知识,都是从网上搜到的,感谢原作者的辛勤付出! 原文链接 http://m.blog.csdn.net/blog/bytxl/8586830 x509是数字证书的规范,P7和P12是两种封 ...
- 使用mysqladmin ext了解MySQL运行状态【转】
摘要: mysqladmin是 MySQL一个重要的客户端,最常见的是使用它来关闭数据库,除此,该命令还可以了解MySQL运行状态.进程信息.进程杀死等.本文介绍一下如何使用 mysqladmin e ...
- poj 2389.Bull Math 解题报告
题目链接:http://poj.org/problem?id=2389 题目意思:就是大整数乘法. 题目中说每个整数不超过 40 位,是错的!!!要开大点,这里我开到100. 其实大整数乘法还是第一次 ...
- WCF重写ServiceHost,实现独立配置文件
有时我们需要将WCF的配置文件放在单独的配置文件中,而默认情况下WCF又是在web.config或app.config中去寻找服务配置.如果我们把配置文件放在另一个config文件中,如何让WCF知道 ...
- ListView之BaseAdapter的使用
话说开发用了各种Adapter之后感觉用的最舒服的还是BaseAdapter,尽管使用起来比其他适配器有些麻烦,但是使用它却能实现很多自己喜欢的列表布局,比如ListView.GridView.Gal ...
- 【leetcode】Insert Interval(hard)★
Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessa ...
- HDU 4950 Monster
题目链接 题意:有一个怪物的血量为h,人攻击怪物,每回合可以杀掉a滴血,再回b滴血,k个回合之后人会休息一回合,即人不攻击而怪物回b滴血,问能否杀死.翻译过来就是给定一个数h,每轮可以先减a再加b,k ...