如何替换 Java 中不可打印的 Unicode 字符?
Posted
技术标签:
【中文标题】如何替换 Java 中不可打印的 Unicode 字符?【英文标题】:How can I replace non-printable Unicode characters in Java? 【发布时间】:2011-09-06 03:20:36 【问题描述】:以下内容将替换 ASCII 控制字符([\x00-\x1F\x7F]
的简写):
my_string.replaceAll("\\pCntrl", "?");
以下内容将替换所有 ASCII 不可打印字符([\pGraph\x20]
的简写),包括重音字符:
my_string.replaceAll("[^\\pPrint]", "?");
但是,它们都不适用于 Unicode 字符串。有没有人有从 unicode 字符串中删除不可打印字符的好方法?
【问题讨论】:
作为附录:Unicode 通用类别列表可以在UAX #44中找到 Fastest way to strip all non-printable characters from a Java String的可能重复 @Stewart:嗨,除了标题,你看过问题/答案了吗?!? @Stewart:其他问题仅涵盖不可打印字符的 ascii 子集!!! 【参考方案1】:my_string.replaceAll("\\pC", "?");
查看更多关于Unicode regex。 java.util.regexPattern
/String.replaceAll
支持他们。
【讨论】:
至少在 java 1.6 中,不支持它们。 download.oracle.com/javase/6/docs/api/java/util/regex/… ...我也试过你的台词,除了缺少反斜杠之外,它显然根本不起作用。 这有效:char c = 0xFFFA; String.valueOf(c).replaceAll("\\pC", "?");
也在 Unicode 支持 部分的模式查找的 javadoc 中,说它支持类别
还有一些不可见的空白字符(如 0x0200B),它们是 \pZs 组的一部分。不幸的是,这个也包括正常的空格。对于那些试图过滤不应该包含任何空格的输入字符串的人,字符串s.replaceAll("[\\pC\\pZ]", "")
将起到魅力
这就是我要找的,我正在尝试replaceAll("[^\\u0000-\\uFFFF]", "")
,但没有成功
注意:这里介绍的这个解决方案(有 150 个赞成票)还删除了您可能不想被替换的换行符。【参考方案2】:
Op De Cirkel 大体上是对的。他的建议在大多数情况下都会奏效:
myString.replaceAll("\\pC", "?");
但如果myString
可能包含非 BMP 代码点,那么它会更复杂。 \pC
包含 \pCs
的代理代码点。上述替换方法有时会仅替换一半代理对,从而破坏非 BMP 代码点。这可能是 Java 错误而不是预期行为。
使用其他组成类别是一种选择:
myString.replaceAll("[\\pCc\\pCf\\pCo\\pCn]", "?");
但是,不属于一对的单独代理字符(每个代理字符都有一个分配的代码点)将不会被删除。非正则表达式方法是我知道正确处理\pC
的唯一方法:
StringBuilder newString = new StringBuilder(myString.length());
for (int offset = 0; offset < myString.length();)
int codePoint = myString.codePointAt(offset);
offset += Character.charCount(codePoint);
// Replace invisible control characters and unused code points
switch (Character.getType(codePoint))
case Character.CONTROL: // \pCc
case Character.FORMAT: // \pCf
case Character.PRIVATE_USE: // \pCo
case Character.SURROGATE: // \pCs
case Character.UNASSIGNED: // \pCn
newString.append('?');
break;
default:
newString.append(Character.toChars(codePoint));
break;
【讨论】:
【参考方案3】:您可能对Unicode categories "Other, Control" 和可能 "Other, Format" 感兴趣(不幸的是后者似乎同时包含不可打印和可打印字符)。
在 Java 正则表达式中,您可以分别使用 \pCc
和 \pCf
来检查它们。
【讨论】:
好吧,太糟糕了 java 表达式没有它们,但至少我现在得到了列表......总比没有好。谢谢【参考方案4】:以下方法可实现您的目标
public static String removeNonAscii(String str)
return str.replaceAll("[^\\x00-\\x7F]", "");
public static String removeNonPrintable(String str) // All Control Char
return str.replaceAll("[\\pC]", "");
public static String removeSomeControlChar(String str) // Some Control Char
return str.replaceAll("[\\pCntrl\\pCc\\pCf\\pCo\\pCn]", "");
public static String removeFullControlChar(String str)
return removeNonPrintable(str).replaceAll("[\\r\\n\\t]", "");
【讨论】:
【参考方案5】:我为此使用了这个简单的函数:
private static Pattern pattern = Pattern.compile("[^ -~]");
private static String cleanTheText(String text)
Matcher matcher = pattern.matcher(text);
if ( matcher.find() )
text = text.replace(matcher.group(0), "");
return text;
希望这是有用的。
【讨论】:
【参考方案6】:根据 Op De Cirkel 和 noackjr 的回答,以下是我对一般字符串清理所做的工作:1. 修剪前导或尾随空格,2. dos2unix , 3. mac2unix, 4. 删除除空格之外的所有“不可见的Unicode字符”:
myString.trim.replaceAll("\r\n", "\n").replaceAll("\r", "\n").replaceAll("[\\pCc\\pCf\\pCo\\pCn&&[^\\s]]", "")
使用 Scala REPL 测试。
【讨论】:
【参考方案7】:我建议它删除下面的不可打印字符而不是替换它
private String removeNonBMPCharacters(final String input)
StringBuilder strBuilder = new StringBuilder();
input.codePoints().forEach((i) ->
if (Character.isSupplementaryCodePoint(i))
strBuilder.append("?");
else
strBuilder.append(Character.toChars(i));
);
return strBuilder.toString();
【讨论】:
【参考方案8】:支持的多语言
public static String cleanUnprintableChars(String text, boolean multilanguage)
String regex = multilanguage ? "[^\\x00-\\xFF]" : "[^\\x00-\\x7F]";
// strips off all non-ASCII characters
text = text.replaceAll(regex, "");
// erases all the ASCII control characters
text = text.replaceAll("[\\pCntrl&&[^\r\n\t]]", "");
// removes non-printable characters from Unicode
text = text.replaceAll("\\pC", "");
return text.trim();
【讨论】:
【参考方案9】:我重新设计了电话号码 +9 (987) 124124 的代码 Extract digits from a string in Java
public static String stripNonDigitsV2( CharSequence input )
if (input == null)
return null;
if ( input.length() == 0 )
return "";
char[] result = new char[input.length()];
int cursor = 0;
CharBuffer buffer = CharBuffer.wrap( input );
int i=0;
while ( i< buffer.length() ) //buffer.hasRemaining()
char chr = buffer.get(i);
if (chr=='u')
i=i+5;
chr=buffer.get(i);
if ( chr > 39 && chr < 58 )
result[cursor++] = chr;
i=i+1;
return new String( result, 0, cursor );
【讨论】:
以上是关于如何替换 Java 中不可打印的 Unicode 字符?的主要内容,如果未能解决你的问题,请参考以下文章