// 导入java.util下的所有类
import java.io.*;
/**
* Description:
* <br>Webside: <a >GitHub Of ZallerTing</a>
* <br>Date: 2016-12-21
* @author Zaller.Ting zallerting@gmail.com
* @version 1.0
* 微信/Wechat: ZALLER-TING
* QQ: 851509660
* Location:Kunshan
* 实现输入(待截取字串,开始截取字节索引,截取字节长度)后,输出截取字节长度子串,不出现半个中文字符(?)
*/
public class CutStringByByte {
// 表示开始截取字节索引,首字符索引,字串最大长度,字串最大字节长度,子串长度,子串字节长度,前部分截取字节长度,截取字节长度,半个中文字符数量,临时变量
protected static int startByteIndex, firstStrIndex, maxStrLen, maxByteLen, subLen, subByteLen, beforeCutByteLen, cutByteLen, halfHanNum, tmp;
// 表示键盘输入的一行数据,待截取字串,截取子串变量
protected static String inputStr, beCutStr, subStr;
// 表示键盘输入的单个字符变量
protected static char ch;
// 表示键盘输入的一行数据组成的数组
protected static String[] inputStrArr;
// 表示以GBK编码方式解析的字节数组
protected static byte bytesByGBK[];
// 判断截取字节索引及截取字节长度是否在有效范围
protected static boolean isProperIndex, isProperLen;
// 判断是否为数值型字符串的方法(正数)
protected static boolean isNumbericStr(String inputStr) {
for(int i = 0; i < inputStr.length(); i++) {
// 返回指定索引处的字符
ch = inputStr.charAt(i);
if(ch < 46 || ch > 57) {
return false;
}
}
return true;
}
// 判断是否为数值型字符串的方法(负数)
protected static boolean isNegativeStr(String inputStr) {
for(int i = 0; i < 1; i++) {
ch = inputStr.charAt(i);
if(ch == '-') {
return true;
}
}
return false;
}
// 统计半个中文字符的数量
protected static int halfHanNum(int startByteIndex) {
// 初始化halfHanNum变量
halfHanNum = 0;
for(int i = 0; i <= startByteIndex; i++) {
// 字节索引对应值小于0时halfHanNum加1
if(bytesByGBK < 0) {
++halfHanNum;
}
}
return halfHanNum;
}
// 找出需要截取子串第1个字符索引
protected static int find1stStrIndex(int startByteIndex, String subStr) {
// 统计半个中文字符的数量
halfHanNum(startByteIndex);
// startByteIndex字节索引对应字符为非中文单字节字符, 取subStr最后1个字符
if(bytesByGBK[startByteIndex] > 0) {
firstStrIndex = subStr.length() > 0 ? subStr.length() - 1 : 0;
// startByteIndex字节索引为中文字符第1个字节, 取subStr后面1个字符
} else if(halfHanNum % 2 == 1){
firstStrIndex = subStr.length();
// startByteIndex字节索引为中文字符第2个字节, 取subStr后面1个字符
} else if(halfHanNum % 2 == 0){
firstStrIndex = subStr.length();
}
return firstStrIndex;
}
// 从指定字节索引startByteIndex截取cutByteLen长度的子串方法
public static void subStr(String beCutStr, int startByteIndex, int cutByteLen) throws IOException {
/**
* 分两部分计算:
* 一.截取从索引startByteIndex开始的maxStrLen长度的子串:
* 1.截取从索引0开始的startByteIndex+1长度的子串;
* 2.找出需要截取子串的第1个字符索引firstStrIndex;
* 3.截取从索引firstStrIndex开始的maxStrLen长度的子串;
*
* 二.截取从索引startByteIndex开始的cutByteLen长度的子串:
* 1.重新计算需要截取字串最大长度maxStrLen;
* 2.截取从索引firstStrIndex开始的cutByteLen长度的子串;
* 3.返回从startByteIndex字节索引截取cutByteLen长度的子串subStr;
*/
/**
* 第一部分:截取从索引startByteIndex开始的maxStrLen长度的子串
*/
// 字串最大长度
maxStrLen = beCutStr.length();
// 字串最大字节长度
maxByteLen = beCutStr.getBytes().length;
// 前一部分截取字节长度
beforeCutByteLen = startByteIndex > 0 ? startByteIndex + 1 : 0;
// 从索引[0]截取长度[beforeCutByteLen]的子串
subStr = beCutStr.substring(0, beforeCutByteLen > maxStrLen ? maxStrLen : beforeCutByteLen);
// 子串字节长度
subByteLen = subStr.getBytes("GBK").length;
// 子串字节长度赋给临时变量tmp
tmp = subByteLen;
// 前部分截取字节长度小于子串字节长度时
while(beforeCutByteLen < subByteLen) {
// 临时变量减1
--tmp;
subStr = beCutStr.substring(0, tmp > maxStrLen ? maxStrLen : tmp);
subByteLen = subStr.getBytes("GBK").length;
}
// 找出需要截取子串第1个字符索引
find1stStrIndex(startByteIndex, subStr);
// 找出需要截取子串
subStr = beCutStr.substring(firstStrIndex, maxStrLen);
/**
* 第二部分:截取从索引startByteIndex开始的cutByteLen长度的子串
*/
// 子串字节长度
subByteLen = subStr.getBytes("GBK").length;
// 重新计算需要截取字串最大长度
maxStrLen = maxStrLen - firstStrIndex;
// 子串字节长度赋给临时变量tmp
tmp = subByteLen;
// 需要截取字节长度小于子串字节长度时
while(cutByteLen < subByteLen) {
// 需要截取字节长度减1
--tmp;
subStr = subStr.substring(0, tmp > maxStrLen ? maxStrLen : tmp);
subByteLen = subStr.getBytes("GBK").length;
}
System.out.println("“" + beCutStr + "” 从第" + startByteIndex + "字节索引截取" + cutByteLen + "字节的子串为: " + subStr + "\n");
}
// 主方法,程序的入口
public static void main(String[] args) throws IOException {
System.out.println("【本软件实现从指定字节索引截取指定字节长度子串的功能】\n");
System.out.print(" 以【待截字串,开始截取字节索引,截取字节长度】格式输入 :");
// 获取键盘输入字符串
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while((inputStr = br.readLine()) != null) {
// 通过英文逗号分隔键盘输入的字符串
inputStrArr = inputStr.split(",");
// 将键盘输入的第1个参数以"GBK"编码形式译码成1个字节数组
bytesByGBK = inputStrArr[0].getBytes("GBK");
// 判断是否键盘输入包含英文逗号且以逗号分隔的字符串中第1个不为null
if(inputStr.contains(",") && !inputStr.contains(",") && inputStrArr[0] != null) {
// 判断是否键盘输入第2个及第3个均为数值型字符串
if(isNumbericStr(inputStrArr[1]) && isNumbericStr(inputStrArr[2])) {
// 转换数值型字符串为对应数值
startByteIndex = Integer.parseInt(inputStrArr[1]);
cutByteLen = Integer.parseInt(inputStrArr[2]);
// 判断键盘输入的第2个及第3个数值是否在合理范围内
isProperIndex = startByteIndex >= 0 && startByteIndex <= bytesByGBK.length ? true : false;
isProperLen = cutByteLen >= 0 && cutByteLen <= bytesByGBK.length - startByteIndex ? true : false;
// 再判断截取字串字节索引及字节长度是否正确
if(isProperIndex) {
if(isProperLen) {
// 从指定索引位置截取指定字节长度的子串
subStr(inputStrArr[0], startByteIndex, cutByteLen);
} else {
System.out.println("截取字节长度输入有误!");
}
} else {
System.out.println("开始截取字节索引输入有误!");
}
// 判断是否键盘输入第2个及第3个均为负数值型字符串
} else if(isNegativeStr(inputStrArr[1]) && isNegativeStr(inputStrArr[2])){
System.out.println("开始截取字节索引及截取字节长度均输入有误!");
} else if(isNegativeStr(inputStrArr[1]) && !isNegativeStr(inputStrArr[2])){
System.out.println("开始截取字节索引输入有误!");
} else if(!isNegativeStr(inputStrArr[1]) && isNegativeStr(inputStrArr[2])){
System.out.println("截取字节长度输入有误!");
}
// 判断是否键盘输入包含中文逗号
} else if(inputStr.contains(",")) {
System.out.println("请以英文逗号分隔字串、字节索引、字节长度!");
} else {
System.out.println("待截取字串输入为空!");
}
System.out.print(" 以【待截字串,开始截取字节索引,截取字节长度】格式输入 :");
}
}
}
|