从 Java 中的字符串中过滤非 MySQL Latin1 字符
Filtering non MySQL Latin1 Characters from a String in Java
我有一个使用 latin1 的 MySQL table,不幸的是我无法更改它。
在将字符串插入此 table 之前,我想检查字符串是否包含不属于 latin1 字符集的字符。这样我就可以将它从我的数据集中删除。
我该怎么做?
例如
boolean hasNonLatin1Chars = string.chars()
.anyMatch(c -> ...)
Basic Latin range 是 0020–007F
,因此您可以检查尝试替换非拉丁字符的第一个实例是否与原始 String
:
匹配
boolean hasNonLatin1Chars = string.equals((string.replaceFirst("[^\u0020-\u007F]", "")));
如果包含非拉丁字符,这将 return false
。
有 Latin-1 Supplement (00A0 — 00FF
)、Latin Extended-A (0100 — 017F
) 和 Latin Extended-B (0180 — 024F
),因此您可以根据需要修改范围.
为了保持简单和健壮,请利用 CharsetEncoder
:
/** replaces any invalid character in Latin1 by the character rep */
public static String latin1(String str, char rep) {
CharsetEncoder cs = StandardCharsets.ISO_8859_1.newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.replaceWith(new byte[] { (byte) rep });
try {
ByteBuffer b = cs.encode(CharBuffer.wrap(str));
return new String(b.array(), StandardCharsets.ISO_8859_1);
} catch (CharacterCodingException e) {
throw new RuntimeException(e); // should not happen
}
}
这将用替换字符 rep
(当然应该是有效的 Latin1 字符)替换 ISO_8859_1(= Latin1)中的每个无效字符集。
如果您可以接受默认替换 ('?'
),您可以使其更简单:
public static String latin1(String str) {
return new String(str.getBytes(StandardCharsets.ISO_8859_1),
StandardCharsets.ISO_8859_1);
}
例如:
public static void main(String[] args) {
String x = "hi Œmar!";
System.out.println("'" + x + "' -> '" + latin1(x,'?') + "'");
}
输出'hi Œmar!' -> 'hi ?mar!'
这种方法的一个可能缺点是,它只允许您用单个替换字符替换每个无效字符 - 您不能删除它或使用多字符序列。
如果你想要这个,并且有理由确定某个字符永远不会出现在你的字符串中,你可以使用通常的肮脏技巧 - 例如,假设 \u0000
永远不会出现:
/* removes invalid Latin1 charaters - assumes the zero character never appears */
public static String latin1removeinvalid(String str) {
return latin1(str,(char)0).replace("\u0000", "");
}
补充:如果你只想检查有效性,那就更简单了:
public static boolean isValidLatin1(String str) {
return StandardCharsets.ISO_8859_1.newEncoder().canEncode(str);
}
如果你的源数据一直是UTF8,那就这么说。然后你就两全其美了——音译为 latin1 的 UTF8 字符将被更改;那些没有的将以“?”的形式出现。
在 getConnection()
调用中使用它:
?useUnicode=yes&characterEncoding=UTF-8
不测试不良字符,不在代码中进行转换。 MySQL 自动完成所有工作。
我有一个使用 latin1 的 MySQL table,不幸的是我无法更改它。
在将字符串插入此 table 之前,我想检查字符串是否包含不属于 latin1 字符集的字符。这样我就可以将它从我的数据集中删除。
我该怎么做?
例如
boolean hasNonLatin1Chars = string.chars()
.anyMatch(c -> ...)
Basic Latin range 是 0020–007F
,因此您可以检查尝试替换非拉丁字符的第一个实例是否与原始 String
:
boolean hasNonLatin1Chars = string.equals((string.replaceFirst("[^\u0020-\u007F]", "")));
如果包含非拉丁字符,这将 return false
。
有 Latin-1 Supplement (00A0 — 00FF
)、Latin Extended-A (0100 — 017F
) 和 Latin Extended-B (0180 — 024F
),因此您可以根据需要修改范围.
为了保持简单和健壮,请利用 CharsetEncoder
:
/** replaces any invalid character in Latin1 by the character rep */
public static String latin1(String str, char rep) {
CharsetEncoder cs = StandardCharsets.ISO_8859_1.newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.replaceWith(new byte[] { (byte) rep });
try {
ByteBuffer b = cs.encode(CharBuffer.wrap(str));
return new String(b.array(), StandardCharsets.ISO_8859_1);
} catch (CharacterCodingException e) {
throw new RuntimeException(e); // should not happen
}
}
这将用替换字符 rep
(当然应该是有效的 Latin1 字符)替换 ISO_8859_1(= Latin1)中的每个无效字符集。
如果您可以接受默认替换 ('?'
),您可以使其更简单:
public static String latin1(String str) {
return new String(str.getBytes(StandardCharsets.ISO_8859_1),
StandardCharsets.ISO_8859_1);
}
例如:
public static void main(String[] args) {
String x = "hi Œmar!";
System.out.println("'" + x + "' -> '" + latin1(x,'?') + "'");
}
输出'hi Œmar!' -> 'hi ?mar!'
这种方法的一个可能缺点是,它只允许您用单个替换字符替换每个无效字符 - 您不能删除它或使用多字符序列。
如果你想要这个,并且有理由确定某个字符永远不会出现在你的字符串中,你可以使用通常的肮脏技巧 - 例如,假设 \u0000
永远不会出现:
/* removes invalid Latin1 charaters - assumes the zero character never appears */
public static String latin1removeinvalid(String str) {
return latin1(str,(char)0).replace("\u0000", "");
}
补充:如果你只想检查有效性,那就更简单了:
public static boolean isValidLatin1(String str) {
return StandardCharsets.ISO_8859_1.newEncoder().canEncode(str);
}
如果你的源数据一直是UTF8,那就这么说。然后你就两全其美了——音译为 latin1 的 UTF8 字符将被更改;那些没有的将以“?”的形式出现。
在 getConnection()
调用中使用它:
?useUnicode=yes&characterEncoding=UTF-8
不测试不良字符,不在代码中进行转换。 MySQL 自动完成所有工作。