文字列にASCIIのみが含まれているかどうかを確認するにはどうすればよいですか?


120

文字が文字の場合、呼び出しCharacter.isLetter(c)は戻りますtrue。しかしString、ASCIIの基本文字のみが含まれているのかどうかをすばやく見つける方法はありますか?

回答:


128

グアバ 19.0以降、使用することがあります。

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

これは、現在非推奨となっているmatchesAllOf(someString)メソッドascii()ではなく、ファクトリメソッドに依存するメソッドを使用します。ASCIIシングルトンます。

ここで、ASCIIには、タブ、改行/改行などの(スペース)より下の印刷不可能な文字含むすべてのASCII文字が含ま0x20れますが、BELコード0x07とコードも含まDELれます0x7F

以前のバージョンのコメントにコードポイントが示されている場合でも、このコードはコードポイントではなく文字を誤って使用します。幸いにも、U+010000以上の値を持つコードポイントを作成するために必要な文字は、ASCII範囲外の値を持つ2つの代理文字を使用します。したがって、このメソッドは、絵文字を含む文字列であっても、ASCIIのテストに成功します。

ascii()メソッドのない以前のGuavaバージョンの場合、次のように記述できます。

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

31
+1別のサードパーティのライブラリが必要ないのは良いことですが、Colinの答えははるかに短く、読みやすくなっています。サードパーティのライブラリを提案することは完全に問題なく、反対票で罰せられるべきではありません。
Jesper

1
また、CharMatcherは本当に信じられないほど強力で、これ以上のことができることも指摘しておきます。さらに、ASCII以外にも多くの事前定義されたCharMatcherがあり、カスタムのものを作成するための優れたファクトリメソッドがあります。
ColinD 2010

7
CharMatcher.ASCIIは現在非推奨であり、2018
。– thisarattr 2017

108

java.nio.charset.Charsetでそれを行うことができます 。

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
      */
  }
}

文字列内の非ASCII文字を検出する


10
ドキュメントによれば、「このクラスのインスタンスは、複数の同時スレッドで使用するのに安全ではない」ので、CharsetEncoderを静的にするのは良い考えではないと思います。
pm_labs 2012年

@paul_sns、あなたは正しいCharsetEncoderはスレッドセーフではありません(しかしCharsetはそうです)ので、静的にすることはお勧めできません。
RealHowTo

11
Java 1.7以降では、のStandardCharsets.US_ASCII代わりに使用できますCharset.forName("US-ASCII")
Julian Lettner、2014

@RealHowTo正しい解決策はコメントに依存する必要はなく、この問題を修正するために注意し、に基づいてワンライナーメソッドを使用する必要がありStandardCharsetsますか?別の回答を投稿することもできますが、この高く評価されている回答を修正したいと思います。
Maarten Bodewes 2018年

77

これは、ライブラリに依存せずに正規表現を使用する別の方法です。

次の1行を使用できます。

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

サンプルプログラム全体:

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-入力の開始... \\ p {ASCII} *-いつでも任意のASCII文字... \\ z-入力の終了
Arne Deutsch

@ArneDeutsch回答を改善し、参照\P{Print}\P{Graph}説明を含めてもよろしいですか?なぜあなたは必要ですか\A\z
Maarten Bodewes

その正規表現とは何ですか?$は文字列の終わり、^は始まり、\\ A \\ p \\ zのどちらも聞いたことがないことは知っています。javadocへの参照を添付していただけますか?
deathangel908

@ deathangel908 \ Aは入力の開始です。\ zは入力の終わりです。^と$はMULTILINEモードでは異なる動作をし、DOTALLは\ Aと\ zの動作を変更します。stackoverflow.com/a/3652402/1003157を
Raymond Naseef

58

文字列を反復処理し、すべての文字の値が128未満であることを確認します。

Java文字列は概念的にはUTF-16としてエンコードされます。UTF-16では、ASCII文字セットは値0〜127としてエンコードされ、非ASCII文字(複数のJava文字で構成される場合があります)のエンコードでは、0〜127の数字が含まれないことが保証されます。


27
Javaの1.8を使用すると、行うことができます:str.chars().allMatch(c -> c < 128)
ジュリアンLettner

7
印刷可能な文字が必要な場合c >= 0x20 && c < 0x7Fは、7ビットエンコーディングの最初の32の値が制御文字であり、最後の値(0x7F)がであるため、テストする必要がある場合がありDELます。
Maarten Bodewes 2015

15

または、IDNクラスからコードをコピーします。

// 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
最初の文字が> = U + D800
k3b

ただし、ASCIIで印刷できない文字が含まれていることに注意してください(これは正しいですが、予期されていない場合があります)。もちろん、およびを使用するreturn false代わりに、直接使用することもできます。isASCII = falsebreak
Maarten Bodewes 2018年

これはOracle JDKのコードです。コピーすると法的な問題が発生する可能性があります。
Arne Deutsch

11

Apacheのcommons-lang3には、この問題を含むあらゆる種類の「問題」に対する有用なユーティリティ/便利なメソッドが含まれています。

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

1
文字列にタブまたは改行文字(\ t \ r \ n)が含まれている場合、isAsciiPrintableはfalseを返すことに注意してください。
TampaHaze

@TampaHazeは、内部的に、すべての文字値のチェックが32から127の間であるためです。これは間違っていると思います。0から127までチェックする必要があります
therealprashant 19/07/17

1
@therealprashantメソッド名がisAsciiだった場合、同意します。しかしisAsciiPrintable命名されている方法は、彼らが意図的に除外されている可能性があることを31文字以内で0を意味します
TampaHaze

4

これを試して:

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

「これを試す」は常に反対票を獲得します。これは何をしますか?何が含まれ、何が含まれていませんか?ちなみに、メモリのサイズも2倍になるので、反対票が出ます。
Maarten Bodewes

1

文字列を反復処理し、charAt()を使用してcharを取得します。次に、それをintとして扱い、Unicode値(ASCIIのスーパーセット)が適切かどうかを確認します。

あなたが好きではない最初の休憩。


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

コードのみの回答。これが何をするかを示してください。つまり、このチェックを実行する場合は、印刷できない文字と未定義の文字(0x7F)が含まれていることを示してください。
Maarten Bodewes

私の長期実行プログラムが興味のある文字を見つけられなかった後、これは私を噛んだかもしれません。 charAtを返しますcharchar最初にintに変換せずに、型がintより大きいかどうかを直接テストできますか、それともテストで自動的に変換が行われますか?たぶん、できるかもしれませんし、そうでしょう 私は先に進み、これを次のようなintに変換しました:if ((int)s.charAt(i) > 127)。結果が異なるかどうかはわかりませんが、実行した方が良いと思います。:-\
harperville

0

それは可能でした。かなり問題です。

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

文字列にASCII文字のみが含まれている場合はtrueを返し、含まれていない場合はfalseを返します。

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

非ASCIIを削除する場合は、次のスニペットです。

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

コードは4つの魔法でのみ応答し、それ何をするかの説明はありません。調整してください。
Maarten Bodewes
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.