黑马程序员技术交流社区
标题:
从一个字符串中按字节数截取一部分
[打印本页]
作者:
没说的话……
时间:
2014-12-12 17:20
标题:
从一个字符串中按字节数截取一部分
public class Test10 {
public static void main(String[] args) {
//调用函数,输出测试
System.out.println(mySubstring("HM程序员最强大",2));
System.out.println(mySubstring("HM程序员最强大",4));
System.out.println(mySubstring("HM程序员最强大",3));
System.out.println(mySubstring("HM程序员最强大",10));
}
//定义一个方法,接收原始字符串和需要截取的字节数,返回截取到的字符串
public static String mySubstring(String str,int count) {
//定义一个byte[]
byte[] bytes = null;
//获取字节数组时,指定为按GBK编码获取,需要处理不支持GBK的机子上的异常
try {
bytes = str.getBytes("GBK");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//判断输入的字节个数是不是正整数
if(count<0)
throw new RuntimeException("获取字节个数为负数,错误!");
//判断输入的字节个数是否大于原始字符串长度,是,则输出原字符串
else if(count>str.length())
return str;
//判断输入的字节个数是不是奇数
else if(count>0 && count%2==1) {
//是奇数,才判断要获取的最后一个字节是不是汉字的一半,通过负数判断
if((byte)bytes[count-1]<0){
//是汉字一半,就减一个字节
count--;
}
}
//获取要得到的新字节数组
byte[] newbytes=new byte[count];
for(int x=0;x<count;x++){
newbytes[x]=bytes[x];
}
//将新字节数组转回字符串,并返回
String newStr=new String(newbytes);
return newStr;
}
}
作者:
run_wind
时间:
2014-12-12 18:14
package com.itheima;
import java.io.IOException;
import java.util.Scanner;
/**
需求:编写函数,从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表)。
例如:从“HM程序员”中截取2个字节是“HM”,截取4个则是“HM程”,截取3个字节也要是"HM"而不要出现半个中文
思路: 输入一个字符串,和要截取的字数
定义一个函数,函数功能:从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表)
把字符串转成字节数组
因为中文GBK是返回两个负数,所以从最后一个开始往前遍历
定义一个计数器,遍历,如果便利到负数就+1。
如果负数个数为单数,那么为半个中文,舍弃,返回-1之前的数,转换成字符串输出
否则为一个中文,转换成字符串输出
@author run_wind
*/
class Test10
{
public static void main(String[] args) throws IOException
{
Scanner in = new Scanner(System.in);//获取键盘输入的实例
System.out.print("请输入字符串(直接回车默认HM程序员):");
String string = in.nextLine();
if (string.equals(""))
string = "HM程序员";
System.out.print("请输入截取的字节数:");
int byte_num = in.nextInt();
Test10 t10 = new Test10();
System.out.println(t10.getString(string, byte_num));
}
//函数功能:从一个字符串中按字节数截取一部分,但不能截取出半个中文(GBK码表)
public String getString(String str,int key) throws IOException
{
byte[] buf = str.getBytes("gbk");//编码
//因为中文GBK是返回两个负数,所以从最后一个开始往前遍历
//如果负数个数为单数,那么为半个中文,舍弃,否则为一个中文,返回
int count = 0;
for(int x=key-1; x>=0; x--)
{
if(buf[x]<0)
count++;
else
break;
}
if(count%2==0)//解码。如果为单数就是半个中文,要舍弃最后的数
return new String(buf,0,key,"gbk");
else
return new String(buf,0,key-1,"gbk");
}
}
复制代码
作者:
zeizeizeiaaa
时间:
2015-3-27 10:50
楼主的应该不对吧
作者:
lclxjzz
时间:
2015-4-11 15:24
学习了 楼主的对的
作者:
奋斗的黑马
时间:
2015-4-11 21:30
代码不对呀!出问题了
作者:
奋斗的黑马
时间:
2015-4-11 21:31
请输入一个字符串写
h中h国h好
请输入要截取的字符的个数
2
h?
请输入要截取的字符的个数
3
h?
作者:
愚翁
时间:
2015-6-17 17:09
写得很清楚,谢谢!
作者:
铿锵的小黑马
时间:
2015-8-19 15:43
我学过都忘了. .
作者:
xiao_D
时间:
2015-10-23 05:37
好low的代码啊
作者:
xiao_D
时间:
2015-10-23 05:40
run_wind 发表于 2014-12-12 18:14
计数器这个点子好, 往前遍历 这个不错哦
作者:
xiao_D
时间:
2015-10-23 05:42
lclxjzz 发表于 2015-4-11 15:24
学习了 楼主的对的
我就呵呵了 感谢楼主抛砖引玉
作者:
13453150836
时间:
2015-11-1 23:26
好多大神...
作者:
奔跑着
时间:
2015-12-2 18:31
public class Test10 {
public static void main(String[] args) throws UnsupportedEncodingException {
System.out.println("请输入一个字符串");
String s =new Scanner(System.in).nextLine();
System.out.println("请输入要截取的长度");
int n =new Scanner(System.in).nextInt();
cut(s,n);
}
private static void cut(String s, int n) throws UnsupportedEncodingException {
byte[] b = s.getBytes("gbk");
//定义cout1接收数组正数出现的次数
//定义cout2接受数组负数出现的次数
int cout1 = 0;
int cout2 =0;
for(int i = 0;i<=n-1;i++){
if(b[i]>0){
cout1+=1;
}else{
cout2+=1;
}
}
//正数出现说明是字符计入需截取长度中,负数出现一次则不计入,出现两次,说明是一个汉字,截取长度+1
int sum = cout1+ (int)(cout2/2);
String s3=s.substring(0, sum);
System.out.println(s3);
}
}
作者:
Id_820
时间:
2015-12-9 20:27
学习了,哈
作者:
AlvinDing
时间:
2016-12-26 14:19
// 导入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) {
ch = inputStr.charAt(0);
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(" 以【待截字串,开始截取字节索引,截取字节长度】格式输入 :");
}
}
}
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2