Bir Dizenin yalnızca ASCII içerip içermediğini nasıl kontrol edebilirim?


120

Karakter bir harf ise çağrı Character.isLetter(c)geri döner true. Ancak, a'nın Stringyalnızca ASCII'nin temel karakterlerini içerip içermediğini hızlıca bulmanın bir yolu var mı?

Yanıtlar:


128

Gönderen Guava ileriye 19.0, aşağıdakileri kullanabilirsiniz:

boolean isAscii = CharMatcher.ascii().matchesAllOf(someString);

Bu , artık kullanımdan kaldırılan tekli yerine matchesAllOf(someString)fabrika yöntemine dayanan yöntemi kullanır .ascii()ASCII

Burada ASCII ASCII karakter içeren dahil basılamayan karakterler daha düşük 0x20, bu uzantıların, satır besleme / geri dönüş olarak değil, aynı zamanda (boşluk) BELkodu ile 0x07ve DELkod ile 0x7F.

Bu kod, önceki sürümlerin yorumlarında kod noktaları belirtilmiş olsa bile, kod noktaları yerine karakterleri yanlış kullanır. Neyse ki, değeri U+010000veya üzerinde olan kod noktası oluşturmak için gereken karakterler, ASCII aralığı dışında bir değere sahip iki vekil karakter kullanır. Dolayısıyla yöntem, emoji içeren dizeler için bile ASCII'yi test etmede hala başarılıdır.

ascii()Yöntem içermeyen önceki Guava sürümleri için şunları yazabilirsiniz:

boolean isAscii = CharMatcher.ASCII.matchesAllOf(someString);

31
+1 Başka bir üçüncü taraf kitaplığına ihtiyacınız yoksa iyi olsa da Colin'in yanıtı çok daha kısa ve çok daha okunabilir. Üçüncü taraf kütüphaneleri önermek tamamen tamamdır ve olumsuz oyla cezalandırılmamalıdır.
Jesper

1
Ayrıca CharMatchers'ın gerçekten inanılmaz derecede güçlü olduğunu ve bundan daha fazlasını yapabileceğini belirtmeliyim. Ek olarak, ASCII'nin yanı sıra önceden tanımlanmış daha birçok CharMatcher ve özel olanlar oluşturmak için harika fabrika yöntemleri vardır.
ColinD

7
CharMatcher.ASCIIşu anda kullanımdan kaldırıldı ve Haziran 2018'de kaldırılmak üzere.
thisarattr

108

Bunu java.nio.charset.Charset ile yapabilirsiniz .

import java.nio.charset.Charset;

public class StringUtils {

  public static boolean isPureAscii(String v) {
    return Charset.forName("US-ASCII").newEncoder().canEncode(v);
    // or "ISO-8859-1" for ISO Latin 1
    // or StandardCharsets.US_ASCII with JDK1.7+
  }

  public static void main (String args[])
    throws Exception {

     String test = "Réal";
     System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));
     test = "Real";
     System.out.println(test + " isPureAscii() : " + StringUtils.isPureAscii(test));

     /*
      * output :
      *   Réal isPureAscii() : false
      *   Real isPureAscii() : true
      */
  }
}

Bir dizedeki ASCII olmayan karakteri algılama


10
CharsetEncoder'ı statik hale getirmenin iyi bir fikir olduğunu sanmıyorum çünkü belgelere göre "Bu sınıfın örnekleri birden çok eşzamanlı iş parçacığı tarafından kullanım için güvenli değildir."
pm_labs

@paul_sns, haklısınız CharsetEncoder iş parçacığı için güvenli değil (ama Charset öyle), bu yüzden onu statik yapmak iyi bir fikir değil.
RealHowTo

11
Java 1.7 veya üstü ile StandardCharsets.US_ASCIIbunun yerine kullanılabilir Charset.forName("US-ASCII").
Julian Lettner

@RealHowTo Correct çözümleri yorumlara güvenmek zorunda kalmamalı, bu sorunu gidermeye özen göstermeli ve belki de StandardCharsets? Başka bir cevap gönderebilirim ama bu çok takdir edilen cevabı düzeltmeyi tercih ederim.
Maarten Bodewes

77

Kitaplığa bağlı değil, normal ifade kullanmanın başka bir yolu da burada.

Bu tek satırı kullanabilirsiniz:

text.matches("\\A\\p{ASCII}*\\z")

Tam örnek program:

public class Main {
    public static void main(String[] args) {
        char nonAscii = 0x00FF;
        String asciiText = "Hello";
        String nonAsciiText = "Buy: " + nonAscii;
        System.out.println(asciiText.matches("\\A\\p{ASCII}*\\z"));
        System.out.println(nonAsciiText.matches("\\A\\p{ASCII}*\\z"));
    }
}

15
\\ A - Girişin başlangıcı ... \\ p {ASCII} * - Herhangi bir zamanda herhangi bir ASCII karakteri ... \\ z - Girişin sonu
Arne Deutsch

@ArneDeutsch Cevabı iyileştirip, referanslar \P{Print}ve \P{Graph}+ bir açıklama eklememin bir sakıncası var mı? Neden ihtiyacınız var \Ave \z?
Maarten Bodewes

Bu normal ifade nedir? $ 'In dizenin sonu olduğunu biliyorum, ^ start, \\ A \\ p \\ z hiçbirini hiç duymadım, referansı javadoc'a ekleyebilir misiniz?
deathangel908

@ deathangel908 \ A girişin başlangıcıdır. \ z girdinin sonudur. ^ ve $ MULTILINE modunda farklı davranır ve DOTALL, \ A ve \ z'nin davranışını değiştirir. Bkz stackoverflow.com/a/3652402/1003157
Raymond Naseef

58

Dizeyi yineleyin ve tüm karakterlerin 128'den küçük bir değere sahip olduğundan emin olun.

Java Dizeleri kavramsal olarak UTF-16 olarak kodlanır. UTF-16'da, ASCII karakter seti 0-127 değerleri olarak kodlanır ve ASCII olmayan herhangi bir karakterin (birden fazla Java karakterinden oluşabilir) kodlamasının 0-127 sayılarını içermemesi garanti edilir.


27
Java 1.8 ile şunları yapabilirsiniz:str.chars().allMatch(c -> c < 128)
Julian Lettner

7
Yazdırılabilir karakterler istiyorsanız c >= 0x20 && c < 0x7F, 7 bit kodlamanın ilk 32 değeri kontrol karakterleridir ve son değer (0x7F) olduğundan test etmek isteyebilirsiniz DEL.
Maarten Bodewes

15

Veya kodu IDN'den kopyalarsınız sınıfından .

// to check if a string only contains US-ASCII code point
//
private static boolean isAllASCII(String input) {
    boolean isASCII = true;
    for (int i = 0; i < input.length(); i++) {
        int c = input.charAt(i);
        if (c > 0x7F) {
            isASCII = false;
            break;
        }
    }
    return isASCII;
}

1
Bu, 2 karakterli unicode ile bile çalışır çünkü 1. karakter> = U + D800
k3b

Ancak ASCII'de yazdırılamayan karakterler içerdiğine dikkat edin (bu doğrudur, ancak beklenmeyebilir). Elbette ve return falseyerine doğrudan kullanmak mümkündür . isASCII = falsebreak
Maarten Bodewes

Bu Oracle JDK kodudur. Kopyalama yasal sorunlara neden olabilir.
Arne Deutsch

11

Apache'nin commons-lang3'ü, bu sorun da dahil olmak üzere her tür "sorun" için değerli yardımcı / kolaylık yöntemleri içerir.

System.out.println(StringUtils.isAsciiPrintable("!@£$%^&!@£$%^"));

1
Dize sekme veya satır besleme karakterleri (\ t \ r \ n) içeriyorsa, AsciiPrintable'ın false değerini döndürdüğünü unutmayın.
TampaHaze

@TampaHaze thats çünkü dahili olarak, her karakter değerinin 32 ila 127 arasında olup olmadığını kontrol ediyor. Bunun yanlış olduğunu düşünüyorum. 0'dan 127'ye kadar kontrol etmeliyiz
therealprashant

1
@therealprashant yöntem adı isAscii olsaydı sana katılıyorum. Ancak isAsciiPrintable olarak adlandırılan yöntem, 0 ile 31 arasındaki karakterleri bilerek hariç tutmuş olabileceklerini ima eder.
TampaHaze

4

bunu dene:

for (char c: string.toCharArray()){
  if (((int)c)>127){
    return false;
  } 
}
return true;

"Bunu dene" her zaman olumsuz oy alır. Bu ne geliyor do ? Neler dahildir ve ne değildir? Bu arada, hafıza boyutunu da ikiye katladığın için olumsuz oy alırdın.
Maarten Bodewes

1

Dizeyi yineleyin ve karakteri almak için charAt () kullanın. Sonra bunu int olarak ele alın ve beğendiğiniz bir unicode değerine (ASCII'nin bir üst kümesi) sahip olup olmadığına bakın.

Sevmediğin ilk anda ara ver.


1
private static boolean isASCII(String s) 
{
    for (int i = 0; i < s.length(); i++) 
        if (s.charAt(i) > 127) 
            return false;
    return true;
}

Yalnızca kod cevabı, lütfen bunun ne işe yaradığını, yani bu kontrolü yaparsanız yazdırılamayan karakterler ve tanımlanmamış bir karakter (0x7F) içerdiğini belirtin.
Maarten Bodewes

Bu, uzun süredir devam eden programım ilgilendiğim herhangi bir karakteri bulamadığında beni ısırmış olabilir. charAtdöndürür a char. Bir chartürün int'ten büyük olup olmadığını önce int'e dönüştürmeden doğrudan test edebilir misiniz , yoksa testiniz otomatik olarak dönüştürmeyi mi yapıyor? Belki yapabilirsin ve belki yapar? Devam ettim ve şöyle bir int bu dönüştürülen: if ((int)s.charAt(i) > 127). Sonuçlarımın farklı olup olmadığından emin değilim ama çalışmasına izin verdiğimde daha iyi hissediyorum. Göreceğiz: - \
harperville

0

Mümkün oldu. Oldukça sorun.

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;

public class EncodingTest {

    static CharsetEncoder asciiEncoder = Charset.forName("US-ASCII")
            .newEncoder();

    public static void main(String[] args) {

        String testStr = "¤EÀsÆW°ê»Ú®i¶T¤¤¤ß3¼Ó®i¶TÆU2~~KITEC 3/F Rotunda 2";
        String[] strArr = testStr.split("~~", 2);
        int count = 0;
        boolean encodeFlag = false;

        do {
            encodeFlag = asciiEncoderTest(strArr[count]);
            System.out.println(encodeFlag);
            count++;
        } while (count < strArr.length);
    }

    public static boolean asciiEncoderTest(String test) {
        boolean encodeFlag = false;
        try {
            encodeFlag = asciiEncoder.canEncode(new String(test
                    .getBytes("ISO8859_1"), "BIG5"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return encodeFlag;
    }
}

0

Bu, String yalnızca ASCII karakterleri içeriyorsa true, içermediğinde false döndürür.

Charset.forName("US-ASCII").newEncoder().canEncode(str)

ASCII olmayanları kaldırmak istiyorsanız, aşağıdaki kod parçacığı:

if(!Charset.forName("US-ASCII").newEncoder().canEncode(str)) {
                        str = str.replaceAll("[^\\p{ASCII}]", "");
                    }

-2
//return is uppercase or lowercase
public boolean isASCIILetter(char c) {
  return (c > 64 && c < 91) || (c > 96 && c < 123);
}

Bir kod sadece 4 magics ve ne herhangi bir açıklama ile cevap yapar . Lütfen ayarlayınız.
Maarten Bodewes
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.