背景:公司生产线上出现异常,报的错是记录日志时数据库长度超出,导致异常,经查询发现是由于在计算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长度字符串的更多相关文章

  1. C#中字节数组byte[]和字符串string类型的相互转换

    C#中字节数组byte[]和字符串string类型的相互转换: string转byte[]: byte[] byteArray = System.Text.Encoding.Default.GetBy ...

  2. leetCode题解之寻找string中最后一个word的长度

    1.题目描述 返回一个 string中最后一个单词的长度.单词定义为没有空格的连续的字符,比如 ‘a’,'akkk'. 2.问题分析 从后向前扫描,如果string是以空格‘  ’结尾的,就不用计数, ...

  3. asp.net AES加密跟PHP的一致,将加密的2进制byte[]转换为16进制byte[] 的字符串获得

    <?php class AESUtil { public static function encrypt($input, $key) { $size = mcrypt_get_block_siz ...

  4. Application.StartupPath获取执行文件路径substring()取特定长度字符串取得根目录

    Application.StartupPath获取执行文件路径substring()取特定长度字符串取得根目录 2012-07-20 10:48 257人阅读 评论(0) 收藏 举报 path usi ...

  5. Java String类相关知识梳理(含字符串常量池(String Pool)知识)

    目录 1. String类是什么 1.1 定义 1.2 类结构 1.3 所在的包 2. String类的底层数据结构 3. 关于 intern() 方法(重点) 3.1 作用 3.2 字符串常量池(S ...

  6. String 对象是不动态改变长度的

    在java里 String 对象是不动态改变长度的,只有先转化成StringBuffer,插入处理后在转回. 如 StringBuffer str = new StringBuffer("T ...

  7. byte[] 与字符串转换

    //取值之后进行 StringBuffer buffer=new StringBuffer(); for (int i = 0; i < enBytes.length; i++) { if(i! ...

  8. C语言 realloc为什么要有返回值,realloc返回值具体解释/(解决随意长度字符串输入问题)。

    在C语言操作中会用到大量的内存操作,当中非经常常使用的一个是realloc(). 由字面意思能够知道,该函数的作用是用于又一次分配内存. 使用方式例如以下: NewPtr=(数据类型*)realloc ...

  9. C#利用 string.Join 泛型集合快速转换拼接字符串

    C#利用 string.Join 泛型集合快速转换拼接字符串 List<int> superior_list = new List<int>(); superior_list. ...

随机推荐

  1. devstack查看服务日志

    执行如下指令: $ screen -x stack 同时按ctrl和a键,然后同时按shift和'键(即"),就可以浏览到服务列表: 上下翻到要查看的服务,进入即可看到当前的运行日志.重启就 ...

  2. 【IDEA】IDEA 如何设置编辑器字体大小

    intellij idea 如何更改编辑器文本字体和大小   换上了intellij idea之后,第一件事就是想要改变下文字字体,因为在我这个27寸的2k分辨率的屏幕上,文字显然太小了. intel ...

  3. C#析构函数与垃圾回收

    析构函数基本语法 C# class Car { ~ Car() // destructor { // cleanup statements... } } 析构函数说明 不能在结构中定义析构函数.只能对 ...

  4. C#之GDI+

    1.使用Brushes填充矩形区域 Graphics g = e.Graphics; g.FillRectangle(Brushes.Green, , , , )); 2.使用LinearGradie ...

  5. c++ macro

     C++ Code  12345678910111213141516171819202122232425262728293031   /* version: 1.0 author: hellogise ...

  6. NGUI 不写一行代码实现翻拍效果

    正面UI添加一个TweenRotation组件,取消掉Active状态 ,To参数改成0,90,0) 背面UI添加一个TweenRotation组件,取消掉Active状态, From参数改成0,27 ...

  7. rsa加密解密

    2016年3月17日 17:21:08 星期四 现在越来越懒了.... 参考: http://www.xuebuyuan.com/1399981.html 左边是加密流程, 右边是解密流程 呃...有 ...

  8. We7 CMS研究

    我下载的we7 3.0是基于vs 2010的,官方网站也建议使用vs2010,但是我有追新的习惯,并相信vs 2013一定能够兼容vs2010的项目,于是在vs2013下打开解决方案并且全部升级,把目 ...

  9. Effective C++ -----条款12: 复制对象时勿忘其每一个成分

    Copying函数应该确保复制“对象内的所有成员变量”及“所有base class成分”. 不要尝试以某个copying函数实现另一个copying函数.应该将共同机能放进第三个函数中,并由两个cop ...

  10. JS match() 方法 使用

    javascript中的match函数是使用正则表达式对字符串进行查找,并将查找的结果作为数组返回,在实际开发中非常的有用,使用方法如下: stringObj.match(rgExp) 其中strin ...