Java'da yazdırılamayan Unicode karakterlerini nasıl değiştirebilirim?


89

Aşağıdakiler ASCII kontrol karakterlerinin yerini alacaktır (kısaltması [\x00-\x1F\x7F]):

my_string.replaceAll("\\p{Cntrl}", "?");

Aşağıdakiler, [\p{Graph}\x20]aksanlı karakterler dahil olmak üzere tüm ASCII yazdırılamayan karakterlerin (kısaltması ) yerini alacaktır :

my_string.replaceAll("[^\\p{Print}]", "?");

Ancak, Unicode dizeleri için hiçbiri çalışmaz. Yazdırılamayan karakterleri bir unicode dizesinden kaldırmanın iyi bir yolu olan var mı?


2
Ek olarak: Unicode Genel Kategorileri listesi UAX # 44
McDowell


1
@Stewart: merhaba, başlığın yanında soru / cevaplara baktınız mı?!?
dagnelies

1
@Stewart: bu diğer soru yalnızca yazdırılamayan karakterlerin ascii alt kümesini kapsar !!!
dagnelies

Yanıtlar:


136
my_string.replaceAll("\\p{C}", "?");

Unicode regex hakkında daha fazla bilgi edinin . java.util.regexPattern/ String.replaceAllonları destekliyor.


En azından java 1.6'da onlar için destek yok. download.oracle.com/javase/6/docs/api/java/util/regex/… ... Ayrıca satırınızı da denedim ve bir ters eğik çizgiyi kaçırmanın yanı sıra, açıkça işe yaramıyor.
dagnelies

Bu işe yarıyor: Unicode destek bölümündeki char c = 0xFFFA; String.valueOf(c).replaceAll("\\p{C}", "?");desen için javadoc'ta da kategorileri desteklediğini söylüyor
Op De Cirkel

Haklısın! Özür dilerim. Fark etmedim çünkü Zl Zp kategorilerini eklemek zorunda kaldım çünkü bunlar çoğunlukla sorunların kaynağıydı. Mükemmel çalışıyor. Tekrar oylayabilmem için lütfen yayınınızda küçük bir düzenleme yapar mısınız?
dagnelies

6
Ayrıca \ p {Zs} grubunun parçası olan görünmez boşluk karakterleri (0x0200B gibi) vardır. Ne yazık ki, bu aynı zamanda normal beyaz boşlukları da içeriyor. Boşluk içermemesi gereken bir girdi dizesini filtrelemeye çalışanlar için, dize s.replaceAll("[\\p{C}\\p{Z}]", "")cazibesini sağlayacak
Andrey L

1
Aradığım buydu, replaceAll("[^\\u0000-\\uFFFF]", "")
deniyordum

58

Op De Cirkel çoğunlukla haklı. Önerisi çoğu durumda işe yarayacaktır:

myString.replaceAll("\\p{C}", "?");

Ancak myStringBMP olmayan kod noktaları içerebilirse, o zaman daha karmaşıktır. \p{C}yedek kod noktalarını içerir \p{Cs}. Yukarıdaki değiştirme yöntemi, bazen vekil çiftin yalnızca yarısını değiştirerek BMP olmayan kod noktalarını bozar. Bunun amaçlanan davranıştan ziyade bir Java hatası olması mümkündür.

Diğer kurucu kategorileri kullanmak bir seçenektir:

myString.replaceAll("[\\p{Cc}\\p{Cf}\\p{Co}\\p{Cn}]", "?");

Ancak, bir çiftin parçası olmayan tek vekil karakterler (her vekil karakterin atanmış bir kod noktası vardır) kaldırılmayacaktır. Düzgün olmayan bir yaklaşım, doğru şekilde işlemeyi bildiğim tek yoldur \p{C}:

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:     // \p{Cc}
        case Character.FORMAT:      // \p{Cf}
        case Character.PRIVATE_USE: // \p{Co}
        case Character.SURROGATE:   // \p{Cs}
        case Character.UNASSIGNED:  // \p{Cn}
            newString.append('?');
            break;
        default:
            newString.append(Character.toChars(codePoint));
            break;
    }
}

8

Unicode kategorileri "Diğer, Kontrol" ve muhtemelen "Diğer, Biçim" ilginizi çekebilir (ne yazık ki ikincisi hem yazdırılamayan hem de yazdırılabilir karakterler içeriyor gibi görünüyor).

Java düzenli ifadelerinde sırasıyla \p{Cc}ve \p{Cf}tuşlarını kullanarak bunları kontrol edebilirsiniz .


Pekala, çok kötü java ifadelerinde yok, ama en azından şu anda listeye sahibim ... hiç yoktan iyidir. teşekkürler
dagnelies

5

hedefiniz için darbe yöntemleri

public static String removeNonAscii(String str)
{
    return str.replaceAll("[^\\x00-\\x7F]", "");
}

public static String removeNonPrintable(String str) // All Control Char
{
    return str.replaceAll("[\\p{C}]", "");
}

public static String removeSomeControlChar(String str) // Some Control Char
{
    return str.replaceAll("[\\p{Cntrl}\\p{Cc}\\p{Cf}\\p{Co}\\p{Cn}]", "");
}

public static String removeFullControlChar(String str)
{
    return removeNonPrintable(str).replaceAll("[\\r\\n\\t]", "");
} 

0

Bunun için bu basit işlevi kullandım:

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;
}

Umarım bu yararlıdır.


0

Op De Cirkel ve noackjr tarafından verilen yanıtlara dayanarak, genel dize temizliği için şunları yapıyorum: 1. Baştaki veya sondaki beyaz boşlukları kırpma, 2. dos2unix, 3. mac2unix, 4. Beyaz boşluklar dışındaki tüm "görünmez Unicode karakterlerini" kaldırma:

myString.trim.replaceAll("\r\n", "\n").replaceAll("\r", "\n").replaceAll("[\\p{Cc}\\p{Cf}\\p{Co}\\p{Cn}&&[^\\s]]", "")

Scala REPL ile test edilmiştir.


0

Değiştirmek yerine aşağıdaki gibi yazdırılamayan karakterleri kaldırmasını öneriyorum

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();
}

-4

Telefon numaraları için kodu yeniden tasarladım +9 (987) 124124 Java'da bir dizeden rakamları ayıklayın

 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 );
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.