17

TwitterストリームAPIからリアルタイムでツイートを解析するプログラムがあります。それらを保存する前に、utf8 としてエンコードしています。特定の文字は、?、??、または ??? として文字列に表示されます。それぞれの Unicode コードの代わりに、問題を引き起こします。さらに調査したところ、問題のある文字は「絵文字」ブロックU+1F600 - U+1F64F と「その他の記号と絵文字」ブロックU+1F300 - U+1F5FF にあることがわかりました。削除しようとしましたが、目的の Unicode 範囲だけでなく、マッチャーが文字列内のほぼすべての文字を置き換えてしまったため、失敗しました。

String utf8tweet = "";
        try {
            byte[] utf8Bytes = status.getText().getBytes("UTF-8");

            utf8tweet = new String(utf8Bytes, "UTF-8");

        } 
        catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
Pattern unicodeOutliers = Pattern.compile("[\\u1f300-\\u1f64f]", Pattern.UNICODE_CASE | Pattern.CANON_EQ | Pattern.CASE_INSENSITIVE);
Matcher unicodeOutlierMatcher = unicodeOutliers.matcher(utf8tweet);
utf8tweet = unicodeOutlierMatcher.replaceAll(" ");

これらの文字を削除するにはどうすればよいですか?

4

4 に答える 4

35

正規表現パターンに否定演算子を追加し^ます。印刷可能な文字をフィルタリングするには、次の式[^\\x00-\\x7F]を使用できます。目的の結果が得られるはずです。

import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class UTF8 {
    public static void main(String[] args) {
        String utf8tweet = "";
        try {
            byte[] utf8Bytes = "#Hello twitter  How are you?".getBytes("UTF-8");

            utf8tweet = new String(utf8Bytes, "UTF-8");

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        Pattern unicodeOutliers = Pattern.compile("[^\\x00-\\x7F]",
                Pattern.UNICODE_CASE | Pattern.CANON_EQ
                        | Pattern.CASE_INSENSITIVE);
        Matcher unicodeOutlierMatcher = unicodeOutliers.matcher(utf8tweet);

        System.out.println("Before: " + utf8tweet);
        utf8tweet = unicodeOutlierMatcher.replaceAll(" ");
        System.out.println("After: " + utf8tweet);
    }
}

次の出力が得られます。

Before: #Hello twitter  How are you?
After: #Hello twitter   How are you?

編集

さらに説明すると\u、次の方法で範囲を表現し続けることもできます[^\\u0000-\\u007F]。これは、最初の 128 の UNICODE 文字以外のすべての文字に一致します (前と同じ)。追加の文字をサポートするために範囲を拡張したい場合は、こちらの UNICODE 文字リストを使用して行うことができます。

たとえば、アクセント付きの母音 (スペイン語で使用) を含めたい場合は、範囲を\u00FFに拡張する必要があるため、[^\\u0000-\\u00FF]orがあり[^\\x00-\\xFF]ます。

Before: #Hello twitter  How are you? á é í ó ú
After: #Hello twitter   How are you? á é í ó ú
于 2012-08-17T21:33:11.690 に答える
24

まず、関係する Unicode ブロックは Java で (厳密に標準に従って) Character.UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHSとして指定されます。正規表現では:

s = s.replaceAll("\\p{So}+", "");
于 2012-08-18T00:07:30.010 に答える
7

これを試しました。Unicode 範囲はemoji 範囲からのものです

    class EmojiEraser{

    private static final String EMOJI_RANGE_REGEX =
                "[\uD83C\uDF00-\uD83D\uDDFF]|[\uD83D\uDE00-\uD83D\uDE4F]|[\uD83D\uDE80-\uD83D\uDEFF]|[\u2600-\u26FF]|[\u2700-\u27BF]";
        private static final Pattern PATTERN = Pattern.compile(EMOJI_RANGE_REGEX);

        /**
         * Finds and removes emojies from @param input
         * 
         * @param input the input string potentially containing emojis (comes as unicode stringfied)
         * @return input string with emojis replaced
         */
        public String eraseEmojis(String input) {
            if (Strings.isNullOrEmpty(input)) {
                return input;
            }
            Matcher matcher = PATTERN.matcher(input);
            StringBuffer sb = new StringBuffer();
            while (matcher.find()) {
                matcher.appendReplacement(sb, "");
            }
            matcher.appendTail(sb);
            return sb.toString();
        }
}
于 2015-09-06T04:53:06.097 に答える
0

status.getText()返品を仮定するとjava.lang.String...

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

上記のトランスコーディング操作は、次と同じ結果を生成します。

utf8tweet = status.getText();

Java 文字列は暗黙的に UTF-16 です。UTF-16 と UTF-8 は同じ文字セット (Unicode) を共有しているため、一方から他方への変換と元のデータへの変換は元のデータになります。

Java の正規表現は、サロゲート ペアを使用した補助範囲をサポートしています。この質問への回答で説明されているように、それらを一致させることができます。

eeeのコメントにあるように、フォントに問題がある可能性が高いです。書記素を表示できるかどうかは、通常、ユーザーのシステムで使用できるフォント、選択したフォント、およびレンダリング テクノロジがサポートするフォント置換の形式によって異なります。

于 2012-08-17T21:55:56.510 に答える