插入数据库截取字节长度

背景:oracle数据库。储存编码UTF-8.

需求:如果字段超出数据库字段长度,那么截取字符串后储存到数据库中。

字段长 4000

最开始计划直接使用java String.subString,然后一想,好像不对,汉字长大概是占3个字节。如果有汉字的话,肯定超长了。然后就找了找有没有工具类可以直接截取数据库长度的方法,没有找到。

只能自己写了。网上找了找UTF8相关文章,发现UTF8规则如下。

        1字节:0xxxxxxx 
2字节:110xxxxx 10xxxxxx 
3字节:1110xxxx 10xxxxxx 10xxxxxx 
4字节:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 
5字节:111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 

6字节:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 

程序想法,找到字符串一共占多少字节,

然后从最大限制长度找到最大的合法字符。例如本例子就是4000.

如果是0xxxxxxx,直接返回4000.

如果是10xxxxxx ,则长度-1,

如果是110xxxxx,则规则长度是当前长度+1,然后跟限制长度比较。

如果是1110xxxx ,则规则长度是当前长度+2,然后跟限制长度比较。等等。。。。


代码如下,(ps:代码比较乱,不漂亮。) 经过测试好像没问题,有问题再改。

package com.test;

import java.nio.charset.Charset;
import java.util.Arrays;

public class TruncateUTF {
	
	public static void main(String[] args) {

		String test = "1你好你好测试测试。123123";
		int length = test.getBytes(Charset.forName("UTF-8")).length;
		
		for (int i = 1; i<=length+10; i++){
			System.out.printf("length is %d, sub string is %s \n", i , truncateUTFString(test, i));
		}
	}
	
	public static String truncateUTFString(String str, int length){
		byte bytes[] = str.getBytes(Charset.forName("UTF-8"));
		int l = getMaxAvailableLength(str, length);
		System.out.printf("the length is %s , the available length is %s \n", length, l );
		return new String (Arrays.copyOfRange(bytes, 0, l), Charset.forName("UTF-8"));
	} 
	
	public static int getMaxAvailableLength(String str, int length){
		
		byte [] bytes = str.getBytes(Charset.forName("UTF-8"));
		if (bytes.length <= length){
			return bytes.length;
		}
		
		int maxLength = length;
		
		while(length > 0){
			if (bytes[length] >= (byte)0x00 && bytes[length] <= (byte)0x7f){
				return  getMaxLength(maxLength, length , 0);
			}else if (bytes[length] >= (byte)0x80 && bytes[length] <= (byte)0xBF){
				length --;
				continue ;
			}else if (bytes[length] >= (byte)0xC0 && bytes[length] <= (byte)0xDF){
				return getMaxLength(maxLength, length , 1);
			}else if (bytes[length] >= (byte)0xE0 && bytes[length] <= (byte)0xEF){
				return getMaxLength(maxLength, length , 2);
			}else if (bytes[length] >= (byte)0xF0 && bytes[length] <= (byte)0xF7){
				return getMaxLength(maxLength, length , 3);
			}else if (bytes[length] >= (byte)0xF8 && bytes[length] <= (byte)0xFB){
				return getMaxLength(maxLength, length , 4);
			}else if (bytes[length] >= (byte)0xFC && bytes[length] <= (byte)0xFD){
				return getMaxLength(maxLength, length , 5);
			}
		}
		
		return 0;
	}
	
	public static int getMaxLength(int maxLength, int length, int gap){
		if (length + gap >= maxLength){
			return length ;
		} else {
			return maxLength;
		}
	}
	
	/*
	 * 	1字节:0xxxxxxx  00 7f 
		2字节:110xxxxx 10xxxxxx c0 df
		3字节:1110xxxx 10xxxxxx 10xxxxxx e0 ef 
		4字节:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx f0 f7
		5字节:111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx f8 fb
		6字节:1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx  fc fd
	*/
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值