包含中文的字符串定长分割方案

本文探讨了在数据库中处理大字段clob的问题,尤其是当内容包含中文时。通过分析UTF-8编码规则,提出了一种切分方案,确保中文的可阅读性同时有效利用存储空间。在4000字节长度限制下,通过判断边界字节是否为多字节字符并适当调整,实现了字符串的定长切分,保证了切分后的字符串与原始字符串相同。
摘要由CSDN通过智能技术生成

背景

我们知道在数据库中字符串类型有定长的char, 变长的varchar, 以及大字段 clob(oracle 中最大支持到 4GB) 等。正常情况下,像身份证号、手机号这类我们设计为char,地址设计为 varchar,还有长文本设计为 clob 基本就满足了日常需要。

我们知道表中一条记录是一个存储块,那么 clob 字段也会存储在这个块中吗?在 Oracle 中当 clob 字段长度不超过 4000 个字节时是这样的,超过 4000 会开辟新的空间来存储 clob。clob 大小按照 4000 的2的幂进行开辟,换句话说,当 clob 字段长度为 4001 时 clob 字段占用的大小为 8000, 当为 8001 时占用的大小为 16000,在字段更大时空间浪费情况更为严重。

那么能不能降大的 clob 字段拆成若干个小的字段呢?比如 4000,如果内容都是 ASCII 字符时相当容易,直接按照 4000 切分即可,那么包含中文呢?如何保证中文的可阅读性,又充分利用空间呢?

中文 UTF-8 编码

当前主流的编码方式为 UTF-8,这种编码方式能够容纳所有中文。UTF-8的编码规则如下:
在这里插入图片描述
由上图不难发现:单字节时候,该字节的二进制是 0 开头;多字节时候字节有1开头,并且该字符的第一个字节从高位期连续 1 的个数,表示该字符占用多少个字节,比如双字节字符第一个字节是 110开头,三字节字符第一个字节是1110 开头等等。

切分方案

基于上述 UTF-8 的编码理论,我们可以做如下切分方案(以切分4000个长度为例):

  1. 判断4000 边界字节是否为单字节,如果是直接切分;
  2. 多字节情况只需要从边界字节 4000 开始一次向前判断是否为多字节第一个字节即可:我们可以根据该字节的前两位是否为 0b11 进行判断,最多向左移动 5 个字节。

之所以不会出现向左移动 6 个字节是因为切分前先判断了是否恰好切分。

编码实现

public static void main(String[] args) {
   
        List<String> stringList = new ArrayList<>();
        String str2 = getRandomString(100000); // 随机生成字符串的个数
        byte[] sbytes = str2.getBytes(StandardCharsets.UTF_8);
        int length = 4000; // 要切分的长度
        int start = 0;
        int byteStart = 0b11;
        int cur = start + length;

        while(true){
   
            if (start < sbytes.length &&  start + length >= sbytes.length){
   
                int copyLenght = sbytes.length - start;
                byte[] temp = new byte[copyLenght];
                System.arraycopy(sbytes, start, temp, 0, copyLenght);
                stringList.add(new String(temp));
                break;
            }
            if(sbytes[cur - 1] 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值