JAva漢字付き文字列をバイトで切り取る解法
10469 ワード
インタフェースで使用されるoracleフィールドの長さが固定バイト数であるため、送信された文字列は、データベースフィールドの合計バイト数よりも大きいと推定され、データベースバイト数よりも小さい文字列が切り取られます.
自分でネット上の例を参考にして、再帰呼び出しを整えておけばいいです.切り取った文字のバイト長はデータベースのバイト長と小さくなければなりません.つまり、最後の文字が漢字であれば、前に切り取るしかありません.
よくある面接問題
文字列を切り取る関数を作成し、文字列とバイト数を入力し、バイトで切り取った文字列として出力します.しかし、漢字が半分に切られないことを保証するには、「私ABC」4のように、「私AB」に切るべきで、「私ABC漢DEF」を入力し、6、「私ABC+漢の半分」ではなく「私ABC」に出力すべきだ.
現在、多くの流行言語、例えばC#、Java内部で採用されているのはUnicode 16(UCS 2)符号化であり、この符号化ではすべての文字が2文字であるため、切り取る文字列が中、英語、数字が混合されていると、次の文字列のような問題が発生する.
String s=「a加bはcに等しく、a等1、bが2に等しい場合、c等3」
上の文字列には漢字もあれば、英語の文字も数字もあります.上位6バイトの文字を切り取る場合は「aプラスb等」であるべきだが、上位6文字をsubstring法で切り取ると「aプラスbがcに等しい」となる.この問題は、substring法が2バイトの漢字を1バイトの文字(UCS 2文字)として扱うためである.
英語のアルファベットと中国語の漢字は異なる符号化フォーマットの下で、占有するバイト数も異なり、以下の例を通じて、いくつかの一般的な符号化フォーマットの下で、1つの英語のアルファベットと1つの中国語の漢字がそれぞれ何バイトを占めているかを見ることができます.
実行結果は次のとおりです.
1.英字:A 2.バイト数:1;コード:GB 2312 3.バイト数:1;コード:GBK 4.バイト数:1;コード:GB 18030 5.バイト数:1;コード:ISO-8859-1 6.バイト数:1;コード:UTF-8 7.バイト数:4;コード:UTF-16 8.バイト数:2;コード:UTF-16 BE 9.バイト数:2;コード:UTF-16 LE 10.日文汉字:人11.バイト数:2;コード:GB 2312 12.バイト数:2;コード:GBK 13.バイト数:2;コード:GB 18030 14.バイト数:1;コード:ISO-8859-1 15.バイト数:3;エンコード:UTF-8 16.バイト数:4;コード:UTF-16 17.バイト数:2;コード:UTF-16 BE 18.バイト数:2;コード:UTF-16 LE
UTF-16 BEとUTF-16 LEは、UNICODコードファミリーの2つのメンバーである.UNICODE規格は、UTF-8、UTF-16、UTF-32の3種類の符号化フォーマットを定義し、UTF-8、UTF-16、UTF-16 BE、UTF-16 LE、UTF-32 BE、UTF-32 LEの7種類の符号化スキームを共有している.JAVAで採用されている符号化方式はUTF-16 BEである.上記の例の実行結果から、GB 2312、GBK、GB 18030の3つの符号化フォーマットは、いずれも問題の要件を満たすことができることがわかる.以下では,GBK符号化を例として解く.
Stringクラスのsubstring(int beginIndex,int endIndex)メソッドを直接使用することはできません.文字で切り取られているからです.'私も「Z」も文字として扱われていますが、lengthは1です.実際、私たちは中国語の漢字と英語のアルファベットを区別できれば、この問題は解決しますが、それらの違いは、中国語の漢字は2バイトで、英語のアルファベットは1バイトです.
自分でネット上の例を参考にして、再帰呼び出しを整えておけばいいです.切り取った文字のバイト長はデータベースのバイト長と小さくなければなりません.つまり、最後の文字が漢字であれば、前に切り取るしかありません.
/**
* ,
* ,
* , , ,
* @param s
*
* @param num
*
* @return String
* @throws UnsupportedEncodingException
*/
public static String idgui(String s,int num)throws Exception{
int changdu = s.getBytes("UTF-8").length;
if(changdu > num){
s = s.substring(0, s.length() - 1);
s = idgui(s,num);
}
return s;
}
よくある面接問題
文字列を切り取る関数を作成し、文字列とバイト数を入力し、バイトで切り取った文字列として出力します.しかし、漢字が半分に切られないことを保証するには、「私ABC」4のように、「私AB」に切るべきで、「私ABC漢DEF」を入力し、6、「私ABC+漢の半分」ではなく「私ABC」に出力すべきだ.
現在、多くの流行言語、例えばC#、Java内部で採用されているのはUnicode 16(UCS 2)符号化であり、この符号化ではすべての文字が2文字であるため、切り取る文字列が中、英語、数字が混合されていると、次の文字列のような問題が発生する.
String s=「a加bはcに等しく、a等1、bが2に等しい場合、c等3」
上の文字列には漢字もあれば、英語の文字も数字もあります.上位6バイトの文字を切り取る場合は「aプラスb等」であるべきだが、上位6文字をsubstring法で切り取ると「aプラスbがcに等しい」となる.この問題は、substring法が2バイトの漢字を1バイトの文字(UCS 2文字)として扱うためである.
英語のアルファベットと中国語の漢字は異なる符号化フォーマットの下で、占有するバイト数も異なり、以下の例を通じて、いくつかの一般的な符号化フォーマットの下で、1つの英語のアルファベットと1つの中国語の漢字がそれぞれ何バイトを占めているかを見ることができます.
import
java.io.UnsupportedEncodingException;
public
class
EncodeTest {
/**
*
*
* @param s
*
* @param encodingName
*
*/
public
static
void
printByteLength(String s, String encodingName) {
System.out.print(
" :"
);
try
{
System.out.print(s.getBytes(encodingName).length);
}
catch
(UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(
"; :"
+ encodingName);
}
public
static
void
main(String[] args) {
String en =
"A"
;
String ch =
" "
;
//
System.out.println(
" :"
+ en);
EncodeTest.printByteLength(en,
"GB2312"
);
EncodeTest.printByteLength(en,
"GBK"
);
EncodeTest.printByteLength(en,
"GB18030"
);
EncodeTest.printByteLength(en,
"ISO-8859-1"
);
EncodeTest.printByteLength(en,
"UTF-8"
);
EncodeTest.printByteLength(en,
"UTF-16"
);
EncodeTest.printByteLength(en,
"UTF-16BE"
);
EncodeTest.printByteLength(en,
"UTF-16LE"
);
System.out.println();
//
System.out.println(
" :"
+ ch);
EncodeTest.printByteLength(ch,
"GB2312"
);
EncodeTest.printByteLength(ch,
"GBK"
);
EncodeTest.printByteLength(ch,
"GB18030"
);
EncodeTest.printByteLength(ch,
"ISO-8859-1"
);
EncodeTest.printByteLength(ch,
"UTF-8"
);
EncodeTest.printByteLength(ch,
"UTF-16"
);
EncodeTest.printByteLength(ch,
"UTF-16BE"
);
EncodeTest.printByteLength(ch,
"UTF-16LE"
);
}
}
実行結果は次のとおりです.
1.英字:A 2.バイト数:1;コード:GB 2312 3.バイト数:1;コード:GBK 4.バイト数:1;コード:GB 18030 5.バイト数:1;コード:ISO-8859-1 6.バイト数:1;コード:UTF-8 7.バイト数:4;コード:UTF-16 8.バイト数:2;コード:UTF-16 BE 9.バイト数:2;コード:UTF-16 LE 10.日文汉字:人11.バイト数:2;コード:GB 2312 12.バイト数:2;コード:GBK 13.バイト数:2;コード:GB 18030 14.バイト数:1;コード:ISO-8859-1 15.バイト数:3;エンコード:UTF-8 16.バイト数:4;コード:UTF-16 17.バイト数:2;コード:UTF-16 BE 18.バイト数:2;コード:UTF-16 LE
UTF-16 BEとUTF-16 LEは、UNICODコードファミリーの2つのメンバーである.UNICODE規格は、UTF-8、UTF-16、UTF-32の3種類の符号化フォーマットを定義し、UTF-8、UTF-16、UTF-16 BE、UTF-16 LE、UTF-32 BE、UTF-32 LEの7種類の符号化スキームを共有している.JAVAで採用されている符号化方式はUTF-16 BEである.上記の例の実行結果から、GB 2312、GBK、GB 18030の3つの符号化フォーマットは、いずれも問題の要件を満たすことができることがわかる.以下では,GBK符号化を例として解く.
Stringクラスのsubstring(int beginIndex,int endIndex)メソッドを直接使用することはできません.文字で切り取られているからです.'私も「Z」も文字として扱われていますが、lengthは1です.実際、私たちは中国語の漢字と英語のアルファベットを区別できれば、この問題は解決しますが、それらの違いは、中国語の漢字は2バイトで、英語のアルファベットは1バイトです.
package gwd.com.singletTest;
import java.io.UnsupportedEncodingException;
public class SubstringTest {
/**
*
*
* @param c
*
* @return true ,false
* @throws UnsupportedEncodingException
* JAVA
*/
public static boolean isChineseChar(char c)throws UnsupportedEncodingException {
// 1,
// , ,
return String.valueOf(c).getBytes("UTF-8").length > 2;
}
/**
*
*
* @param orignal
*
* @param count
*
* @return
* @throws UnsupportedEncodingException
* JAVA
*/
public static String substring(String orignal, int count) throws UnsupportedEncodingException {
int chineseCount=0;
int originalCount=count;
StringBuffer buff=null;
int currentCount=0;
// null,
if (orignal != null && !"".equals(orignal)) {
// GBK
orignal = new String(orignal.getBytes(), "UTF-8");//
// 0,
if (count > 0 && count < orignal.getBytes("UTF-8").length) {
buff = new StringBuffer();
char c;
ok:
for (int i = 0; i < count-1; i++) {
c = orignal.charAt(i);
// System.out.println(count);
if (SubstringTest.isChineseChar(c)) {
System.out.println(count);
System.out.println(buff);
// , 2
if (count+chineseCount*2<=originalCount) {
buff.append(c);
count=count-2;
++chineseCount;
System.out.println(c);
System.out.println(" "+chineseCount);
}else if (count+(chineseCount)*2>originalCount) {
break ok;
}
}else {
buff.append(c);
}
}
// System.out.println(new String(buff.toString().getBytes("GBK"),"UTF-8"));
return new String(buff.toString().getBytes(),"UTF-8");
}
}
return orignal;
}
/**
*
*
* @param orignal
*
* @param count
*
* @return
* @throws UnsupportedEncodingException
* JAVA
*/
public static String gsubstring(String orignal, int count) throws UnsupportedEncodingException {
// null,
if (orignal != null && !"".equals(orignal)) {
// GBK
orignal = new String(orignal.getBytes(), "GBK");
// 0,
if (count > 0 && count < orignal.getBytes("GBK").length) {
StringBuffer buff = new StringBuffer();
char c;
for (int i = 0; i < count; i++) {
c = orignal.charAt(i);
buff.append(c);
if (SubstringTest.isChineseChar(c)) {
// , 1
count=count-2;
}
}
return buff.toString();
}
}
return orignal;
}
/**
* ,
* ,
*
* @param s
*
* @param num
*
* @return String
*/
public static String idgui(String s,int num){
int changdu = s.getBytes().length;
if(changdu > num){
s = s.substring(0, s.length() - 1);
s = idgui(s,num);
}
return s;
}
public static void main(String[] args) throws Exception{
//
String s = " ZWR ILU JAVA";
System.out.println(" :" + s + " : : " + s.getBytes().length);
//System.out.println(" 6 :" + SubstringTest.substring(s, 6));
// System.out.println(" 6 :" + SubstringTest.gsubstring(s, 6));
//System.out.println(" 4 :" + SubstringTest.substring(s, 4));
System.out.println(" 13 :" + SubstringTest.substring(s, 13));
System.out.println(" 13 :" + SubstringTest.idgui(s, 13));
// System.out.println(" 12 :" + SubstringTest.gsubstring(s, 11));
}
}