如何检查字符串是不是仅包含 ASCII?

Posted

技术标签:

【中文标题】如何检查字符串是不是仅包含 ASCII?【英文标题】:How to check if a String contains only ASCII?如何检查字符串是否仅包含 ASCII? 【发布时间】:2011-04-04 20:16:18 【问题描述】:

如果字符是字母,则调用 Character.isLetter(c) 返回 true。但是有没有办法快速找到String 是否只包含ASCII 的基本字符?

【问题讨论】:

【参考方案1】:

这是另一种方法,不依赖于库,而是使用正则表达式。

你可以使用这一行:

text.matches("\\A\\pASCII*\\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\\pASCII*\\z"));
        System.out.println(nonAsciiText.matches("\\A\\pASCII*\\z"));
    

理解正则表达式:

li \\A : 输入开始 \\pASCII : 任意 ASCII 字符 *:所有重复 \\z:输入结束

【讨论】:

\\A - 输入开始 ... \\pASCII* - 任何时候的任何 ASCII 字符 ...\\z - 输入结束 @ArneDeutsch 你介意我改进答案并包含对\PPrint\PGraph 的引用+ 描述吗?为什么需要\A\z 那个正则表达式是什么?我知道 $ 是字符串的结尾,^ 是开始,从来没有听说过 \\A \\p \\z,你能附上对 javadoc 的引用吗? @deathangel908 \A 是输入的开始。 \z 是输入的结尾。 ^ 和 $ 在 MULTILINE 模式下的行为不同,并且 DOTALL 改变 \A 和 \z 的行为。见***.com/a/3652402/1003157【参考方案2】:

在 Kotlin 中:

fun String.isAsciiString() : Boolean =
    this.toCharArray().none  it < ' ' || it > '~' 

【讨论】:

【参考方案3】:

在 Java 8 及更高版本中,可以将String#codePointsIntStream#allMatch 结合使用。

boolean allASCII = str.codePoints().allMatch(c -> c < 128);

【讨论】:

【参考方案4】:

如果 String 只包含 ASCII 字符则返回 true,否则返回 false

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

如果你想删除非 ASCII ,这里是 sn-p:

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

【讨论】:

Vanilla Java,简单易读,这个答案有什么不喜欢的?虽然,为了避免“US-ASCII”中的拼写错误:StandardCharsets.US_ASCII.newEncoder().canEncode(str)【参考方案5】:

您可以使用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
      */
  

Detect non-ASCII character in a String

【讨论】:

我不认为将 CharsetEncoder 设为静态是一个好主意,因为根据文档“此类的实例对于多个并发线程的使用是不安全的。” @paul_sns,你说得对,CharsetEncoder 不是线程安全的(但 Charset 是),因此将其设为静态不是一个好主意。 Java 1.7 或更高版本可以使用StandardCharsets.US_ASCII 而不是Charset.forName("US-ASCII") @RealHowTo 正确的解决方案不应该依赖 cmets,小心解决这个问题,也许使用基于 StandardCharsets 的 oneliner 方法?我可以发布另一个答案,但我宁愿修复这个高度赞赏的答案。【参考方案6】:

从Guava19.0 起,您可以使用:

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

这使用了 matchesAllOf(someString) 方法,该方法依赖于工厂方法 ascii(),而不是现在已弃用的 ASCII 单例。

这里 ASCII 包括所有 ASCII 字符包括低于0x20(空格)的不可打印字符,例如制表符、换行符/回车符,还有代码为0x07BELDEL 代码为0x7F

此代码错误地使用字符而不是代码点,即使代码点在早期版本的 cmets 中指示。幸运的是,创建具有 U+010000 或更大值的代码点所需的字符使用两个具有 ASCII 范围之外的值的代理字符。所以该方法仍然可以成功地测试 ASCII,即使是包含表情符号的字符串。

对于没有 ascii() 方法的早期 Guava 版本,您可以编写:

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

【讨论】:

+1 虽然不需要其他第三方库就很好,但 Colin 的回答更短且更具可读性。建议第三方库是完全可以的,不应以反对票来惩罚。 我还应该指出,CharMatchers 确实非常强大,而且可以做的远不止这些。此外,除了 ASCII 之外,还有更多预定义的 CharMatchers,以及用于创建自定义的出色工厂方法。 CharMatcher.ASCII 现已弃用,将于 2018 年 6 月删除。【参考方案7】:
private static boolean isASCII(String s) 

    for (int i = 0; i < s.length(); i++) 
        if (s.charAt(i) > 127) 
            return false;
    return true;

【讨论】:

仅代码回答,请说明这是做什么的,即如果您执行此检查,它包括不可打印字符和未定义字符 (0x7F)。 在我长时间运行的程序未能找到任何感兴趣的字符后,这可能会咬我。 charAt 返回 char。您是否可以直接测试类型 char 是否大于 int 而无需首先转换为 int,或者您的测试是否会自动进行覆盖?也许你可以,也许它可以?我继续将其转换为 int,如下所示:if ((int)s.charAt(i) &gt; 127)。不确定我的结果是否有任何不同,但让它运行我感觉更好。我们会看到:-\【参考方案8】:

来自 Apache 的 commons-lang3 包含针对各种“问题”的有价值的实用程序/便利方法,包括这个问题。

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

【讨论】:

请注意,如果字符串包含制表符或换行符 (\t \r \n),isAsciiPrintable 返回 false。 @TampaHaze 那是因为在内部,它检查每个字符值是否在 32 到 127 之间。我认为那是错误的。我们应该检查从 0 到 127 @therealprashant 如果方法名称是 isAscii 我同意你的看法。但是被命名为 isAsciiPrintable 的方法意味着它们可能故意排除了字符 0 到 31。【参考方案9】:

这是可能的。好问题。

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;
    

【讨论】:

【参考方案10】:
//return is uppercase or lowercase
public boolean isASCIILetter(char c) 
  return (c > 64 && c < 91) || (c > 96 && c < 123);

【讨论】:

一个代码只回答了 4 个魔法,没有解释它做了什么。请调整。【参考方案11】:

试试这个:

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

return true;

【讨论】:

“试试这个”总是被否决。这做什么?包括什么,不包括什么?顺便说一句,因为你的内存大小也增加了一倍,所以会被否决。【参考方案12】:

或者你从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;

【讨论】:

这甚至适用于 2-char-unicode,因为第一个字符 >= U+D800 但请注意,它包含 ASCII 中的不可打印字符(这是正确的,但可能不是预期的)。当然可以直接使用return false,而不是使用isASCII = falsebreak 这是来自 Oracle JDK 的代码。复制可能会导致法律问题。【参考方案13】:

遍历字符串并确保所有字符的值都小于 128。

Java 字符串在概念上被编码为 UTF-16。在 UTF-16 中,ASCII 字符集被编码为值 0 - 127,并且任何非 ASCII 字符(可能包含多个 Java 字符)的编码都保证不包含数字 0 - 127

【讨论】:

使用 Java 1.8 你可以做到:str.chars().allMatch(c -&gt; c &lt; 128) 如果您想要可打印的字符,您可能需要测试 c &gt;= 0x20 &amp;&amp; c &lt; 0x7F,因为 7 位编码的前 32 个值是控制字符,最终值 (0x7F) 是 DEL【参考方案14】:

遍历字符串,并使用 charAt() 获取字符。然后把它当作一个int,看看它是否有你喜欢的unicode值(ASCII的超集)。

在你不喜欢的第一个休息。

【讨论】:

以上是关于如何检查字符串是不是仅包含 ASCII?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查给定的 c++ 字符串或 char* 是不是仅包含数字?

如何使用正则表达式检查用户输入是不是仅包含特殊字符?

如何获得正则表达式来检查字符串是不是仅包含字母字符 [a-z] 或 [A-Z]?

如何验证字符串是不是仅包含字母、数字、下划线和破折号?

如何检查Python中的字符串是不是为ASCII?

检查字符串是不是仅包含特定字符? [复制]