如何为 java 中的 UTF8 字符串做子串?
How to do substring for UTF8 string in java?
假设我有以下字符串:Rückruf ins Ausland 我需要将它插入到最大大小为 10 的数据库中。
我在 java 中做了一个普通的子字符串,它在 中提取了这个字符串 Rückruf,它有 10 个字符。当它尝试插入此列时,出现以下 oracle 错误:
java.sql.SQLException: ORA-12899: value too large for column
"WAEL"."TESTTBL"."DESC" (actual: 11, maximum: 10)
The reason for this is that the database has a AL32UTF8 character set thus the ü will take 2 chars.
我需要在 java 中编写一个函数来执行此子字符串,但考虑到 ü 占用 2 个字节,因此在这种情况下返回的子字符串应为 Rückruf i(9 个字符)。有什么建议吗?
我认为在这种情况下最好的选择是在数据库级别进行子字符串化,直接在 SQL QUERY 上使用 Oracle SUBSTR 函数。
例如:
INSERT INTO ttable (colname) VALUES (SUBSTR( ?, 1, 10 ))
其中感叹号代表通过JDBC发送的SQL参数。
您可以在 java 中计算 String
的正确长度,将字符串转换为字节数组。
例如,请参见下面的代码:
System.out.println("Rückruf i".length()); // prints 9
System.out.println("Rückruf i".getBytes().length); // prints 10
如果当前字符集不是 UTF-8,请将代码替换为:
System.out.println("Rückruf i".length()); // prints 9
System.out.println("Rückruf i".getBytes("UTF-8").length); // prints 10
如果需要,您可以将 UTF-8 替换为您想要测试该字符集中字符串长度的字符集。
您需要使数据库中的编码与 java 字符串的编码匹配。或者,您可以使用 this 之类的内容转换字符串并获得与数据库中的编码匹配的长度。这将为您提供准确的字节数。否则,您仍然只是希望编码匹配。
String string = "Rückruf ins Ausland";
int curByteCount = 0;
String nextChar;
for(int index = 0; curByteCount +
(nextChar = string.substr(index,index + 1)).getBytes("UTF-8").length < trimmedBytes.length; index++){
curByteCount += nextChar.getBytes("UTF-8").length;
}
byte[] subStringBytes = new byte[10];
System.arraycopy(string.getBytes("UTF-8"), 0, subStringBytes, 0, curByteCount);
String trimed = new String(subStringBytes, "UTF-8");
这应该可以做到。它还不应在此过程中截断多字节字符。这里假设数据库是UTF-8编码。另一个假设是字符串实际上需要修剪。
如果你想 trim Java 中的数据,你必须编写一个函数,该函数 trim 使用所用的 db 字符集对字符串进行 trim 处理,类似于这个测试用例:
package test;
import java.io.UnsupportedEncodingException;
public class TrimField {
public static void main(String[] args) {
//UTF-8 is the db charset
System.out.println(trim("Rückruf ins Ausland",10,"UTF-8"));
System.out.println(trim("Rüückruf ins Ausland",10,"UTF-8"));
}
public static String trim(String value, int numBytes, String charset) {
do {
byte[] valueInBytes = null;
try {
valueInBytes = value.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
}
if (valueInBytes.length > numBytes) {
value = value.substring(0, value.length() - 1);
} else {
return value;
}
} while (value.length() > 0);
return "";
}
}
嘿,所有的 ASCII 字符都小于 128。你可以使用下面的代码。
public class Test {
public static void main(String[] args) {
String s= "Rückruf ins Ausland";
int length =10;
for(int i=0;i<s.length();i++){
if(!(((int)s.charAt(i))<128)){
length--;
}
}
System.out.println(s.substring(0,length));
}
}
您可以复制粘贴并检查它是否满足您的需要或它在任何地方中断。
如果它必须是 Java 你可以将字符串解析为字节和 trim 数组的长度。
String s = "Rückruf ins Ausland";
byte[] bytes = s.getBytes("UTF-8");
byte[] bytes2 = new byte[10];
System.arraycopy(bytes, 0, bytes2, 0, 10);
String trim = new String(bytes2, "UTF-8");
以下可怕地通过完整的 Unicode 代码点遍历整个字符串,字符对(代理代码点)也是如此。
public String trim(String s, int length) {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
if (bytes.length <= length) {
return s;
}
int totalByteCount = 0;
for (int i = 0; i < s.length(); ) {
int cp = s.codePointAt(i);
int n = Character.charCount(cp);
int byteCount = s.substring(i, i + n)
.getBytes(StandardCharsets.UTF_8).length;
if (totalByteCount + byteCount) > length) {
break;
}
totalByteCount += byteCount;
i += n;
}
return new String(bytes, 0, totalByteCount);
}
还可以再优化一下
假设我有以下字符串:Rückruf ins Ausland 我需要将它插入到最大大小为 10 的数据库中。 我在 java 中做了一个普通的子字符串,它在 中提取了这个字符串 Rückruf,它有 10 个字符。当它尝试插入此列时,出现以下 oracle 错误:
java.sql.SQLException: ORA-12899: value too large for column "WAEL"."TESTTBL"."DESC" (actual: 11, maximum: 10) The reason for this is that the database has a AL32UTF8 character set thus the ü will take 2 chars.
我需要在 java 中编写一个函数来执行此子字符串,但考虑到 ü 占用 2 个字节,因此在这种情况下返回的子字符串应为 Rückruf i(9 个字符)。有什么建议吗?
我认为在这种情况下最好的选择是在数据库级别进行子字符串化,直接在 SQL QUERY 上使用 Oracle SUBSTR 函数。
例如:
INSERT INTO ttable (colname) VALUES (SUBSTR( ?, 1, 10 ))
其中感叹号代表通过JDBC发送的SQL参数。
您可以在 java 中计算 String
的正确长度,将字符串转换为字节数组。
例如,请参见下面的代码:
System.out.println("Rückruf i".length()); // prints 9
System.out.println("Rückruf i".getBytes().length); // prints 10
如果当前字符集不是 UTF-8,请将代码替换为:
System.out.println("Rückruf i".length()); // prints 9
System.out.println("Rückruf i".getBytes("UTF-8").length); // prints 10
如果需要,您可以将 UTF-8 替换为您想要测试该字符集中字符串长度的字符集。
您需要使数据库中的编码与 java 字符串的编码匹配。或者,您可以使用 this 之类的内容转换字符串并获得与数据库中的编码匹配的长度。这将为您提供准确的字节数。否则,您仍然只是希望编码匹配。
String string = "Rückruf ins Ausland";
int curByteCount = 0;
String nextChar;
for(int index = 0; curByteCount +
(nextChar = string.substr(index,index + 1)).getBytes("UTF-8").length < trimmedBytes.length; index++){
curByteCount += nextChar.getBytes("UTF-8").length;
}
byte[] subStringBytes = new byte[10];
System.arraycopy(string.getBytes("UTF-8"), 0, subStringBytes, 0, curByteCount);
String trimed = new String(subStringBytes, "UTF-8");
这应该可以做到。它还不应在此过程中截断多字节字符。这里假设数据库是UTF-8编码。另一个假设是字符串实际上需要修剪。
如果你想 trim Java 中的数据,你必须编写一个函数,该函数 trim 使用所用的 db 字符集对字符串进行 trim 处理,类似于这个测试用例:
package test;
import java.io.UnsupportedEncodingException;
public class TrimField {
public static void main(String[] args) {
//UTF-8 is the db charset
System.out.println(trim("Rückruf ins Ausland",10,"UTF-8"));
System.out.println(trim("Rüückruf ins Ausland",10,"UTF-8"));
}
public static String trim(String value, int numBytes, String charset) {
do {
byte[] valueInBytes = null;
try {
valueInBytes = value.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
}
if (valueInBytes.length > numBytes) {
value = value.substring(0, value.length() - 1);
} else {
return value;
}
} while (value.length() > 0);
return "";
}
}
嘿,所有的 ASCII 字符都小于 128。你可以使用下面的代码。
public class Test {
public static void main(String[] args) {
String s= "Rückruf ins Ausland";
int length =10;
for(int i=0;i<s.length();i++){
if(!(((int)s.charAt(i))<128)){
length--;
}
}
System.out.println(s.substring(0,length));
}
}
您可以复制粘贴并检查它是否满足您的需要或它在任何地方中断。
如果它必须是 Java 你可以将字符串解析为字节和 trim 数组的长度。
String s = "Rückruf ins Ausland";
byte[] bytes = s.getBytes("UTF-8");
byte[] bytes2 = new byte[10];
System.arraycopy(bytes, 0, bytes2, 0, 10);
String trim = new String(bytes2, "UTF-8");
以下可怕地通过完整的 Unicode 代码点遍历整个字符串,字符对(代理代码点)也是如此。
public String trim(String s, int length) {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
if (bytes.length <= length) {
return s;
}
int totalByteCount = 0;
for (int i = 0; i < s.length(); ) {
int cp = s.codePointAt(i);
int n = Character.charCount(cp);
int byteCount = s.substring(i, i + n)
.getBytes(StandardCharsets.UTF_8).length;
if (totalByteCount + byteCount) > length) {
break;
}
totalByteCount += byteCount;
i += n;
}
return new String(bytes, 0, totalByteCount);
}
还可以再优化一下