java 从字符串中删除特定unicode范围的字符

ua4mk5z4  于 2023-08-01  发布在  Java
关注(0)|答案(5)|浏览(358)

我有一个程序,可以从twitter stream API真实的解析tweets。在存储它们之前,我将它们编码为utf8。某些字符在字符串中最终出现为?,??,还是?而不是它们各自的Unicode码并引起问题。经过进一步的调查,我发现有问题的字符来自"emoticon" block,U+1F 600- U+1F 64 F和“杂项Symbols And Pictographs" block,U+1F 300- U+1F 5 FF”。我尝试删除,但没有成功,因为匹配器最终替换了字符串中的几乎每个字符,而不仅仅是我想要的unicode范围。

  1. String utf8tweet = "";
  2. try {
  3. byte[] utf8Bytes = status.getText().getBytes("UTF-8");
  4. utf8tweet = new String(utf8Bytes, "UTF-8");
  5. }
  6. catch (UnsupportedEncodingException e) {
  7. e.printStackTrace();
  8. }
  9. Pattern unicodeOutliers = Pattern.compile("[\\u1f300-\\u1f64f]", Pattern.UNICODE_CASE | Pattern.CANON_EQ | Pattern.CASE_INSENSITIVE);
  10. Matcher unicodeOutlierMatcher = unicodeOutliers.matcher(utf8tweet);
  11. utf8tweet = unicodeOutlierMatcher.replaceAll(" ");

字符串
我可以做些什么来删除这些字符?

2izufjch

2izufjch1#

在正则表达式模式中添加求反运算符^。要过滤可打印字符,您可以使用以下表达式[^\\x00-\\x7F],您应该会得到所需的结果。

  1. import java.io.UnsupportedEncodingException;
  2. import java.util.regex.Matcher;
  3. import java.util.regex.Pattern;
  4. public class UTF8 {
  5. public static void main(String[] args) {
  6. String utf8tweet = "";
  7. try {
  8. byte[] utf8Bytes = "#Hello twitter  How are you?".getBytes("UTF-8");
  9. utf8tweet = new String(utf8Bytes, "UTF-8");
  10. } catch (UnsupportedEncodingException e) {
  11. e.printStackTrace();
  12. }
  13. Pattern unicodeOutliers = Pattern.compile("[^\\x00-\\x7F]",
  14. Pattern.UNICODE_CASE | Pattern.CANON_EQ
  15. | Pattern.CASE_INSENSITIVE);
  16. Matcher unicodeOutlierMatcher = unicodeOutliers.matcher(utf8tweet);
  17. System.out.println("Before: " + utf8tweet);
  18. utf8tweet = unicodeOutlierMatcher.replaceAll(" ");
  19. System.out.println("After: " + utf8tweet);
  20. }
  21. }

字符串
将产生以下输出:

  1. Before: #Hello twitter  How are you?
  2. After: #Hello twitter How are you?

编辑

为了进一步解释,您也可以继续以\u形式表示范围,如下所示[^\\u0000-\\u007F],它将匹配所有不是前128个UNICODE字符的字符(与之前相同)。如果要扩展范围以支持额外字符,可以使用UNICODE字符列表here
例如,如果你想包含带重音的元音(在西班牙语中使用),你应该将范围扩展到\u00FF,所以你有[^\\u0000-\\u00FF][^\\x00-\\xFF]

  1. Before: #Hello twitter  How are you? á é í ó ú
  2. After: #Hello twitter How are you? á é í ó ú

展开查看全部
ppcbkaq5

ppcbkaq52#

首先,在java中(严格遵循标准)将相关的unicode块指定为Character.UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS。在正则表达式中:

  1. s = s.replaceAll("\\p{So}+", "");

字符串

qco9c6ql

qco9c6ql3#

我试过这个。unicode范围从emoji ranges开始

  1. class EmojiEraser{
  2. private static final String EMOJI_RANGE_REGEX =
  3. "[\uD83C\uDF00-\uD83D\uDDFF]|[\uD83D\uDE00-\uD83D\uDE4F]|[\uD83D\uDE80-\uD83D\uDEFF]|[\u2600-\u26FF]|[\u2700-\u27BF]";
  4. private static final Pattern PATTERN = Pattern.compile(EMOJI_RANGE_REGEX);
  5. /**
  6. * Finds and removes emojies from @param input
  7. *
  8. * @param input the input string potentially containing emojis (comes as unicode stringfied)
  9. * @return input string with emojis replaced
  10. */
  11. public String eraseEmojis(String input) {
  12. if (Strings.isNullOrEmpty(input)) {
  13. return input;
  14. }
  15. Matcher matcher = PATTERN.matcher(input);
  16. StringBuffer sb = new StringBuffer();
  17. while (matcher.find()) {
  18. matcher.appendReplacement(sb, "");
  19. }
  20. matcher.appendTail(sb);
  21. return sb.toString();
  22. }
  23. }

字符串

展开查看全部
nmpmafwu

nmpmafwu4#

假设status.getText()返回一个java.lang.String...

  1. byte[] utf8Bytes = status.getText().getBytes("UTF-8");
  2. utf8tweet = new String(utf8Bytes, "UTF-8");

字符串
上述代码转换操作产生如下相同的结果:

  1. utf8tweet = status.getText();


Java字符串是隐式UTF-16。UTF-16和UTF-8共享相同的字符集(Unicode),因此从一个转换到另一个并返回原始数据。
Java正则表达式支持使用代理对的补充范围。您可以按照this question的答案中所述进行匹配。
正如eee在他的评论中指出的那样,你很可能有字体问题。字素是否可以显示通常取决于用户系统上可用的字体、所选择的字体以及渲染技术支持的字体替换形式。

nlejzf6q

nlejzf6q5#

如果你不想搞砸正则表达式,那么你可以只测试unicode blocks

  1. private static final Set<Character.UnicodeBlock> BLACKLIST=Set.of(
  2. Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS,
  3. Character.UnicodeBlock.EMOTICONS);
  4. public String sanitize(String verbatim) {
  5. int cps=verbatim.codePoints()
  6. .filter(cp -> !BLACKLIST.contains(Character.UnicodeBlock.of(cp)))
  7. .toArray();
  8. return new String(cps, 0, cps.length);
  9. }

字符串
此外,Java中的表情符号处理库现在相当不错,有些还可以处理象形文字,比如sigpwned/emoji4j。使用该库,您可以编写以下代码:

  1. public String sanitize(String verbatim) {
  2. return new GraphemeMatcher(verbatim).replaceAll(mr -> "");
  3. }


免责声明:我编写了这个库,所以我可能对它的实用性和简单性有偏见。:)

展开查看全部

相关问题