簡體   English   中英

如何從字符串中刪除非 ASCII 字符?

[英]How can non-ASCII characters be removed from a string?

我有字符串"A função""Ãugent" ,其中我需要用空字符串替換çãÃ等字符。

如何從我的字符串中刪除那些非 ASCII 字符?

我嘗試使用以下 function 來實現它,但它無法正常工作。 一個問題是不需要的字符被空格字符取代。

public static String matchAndReplaceNonEnglishChar(String tmpsrcdta) {
    String newsrcdta = null;
    char array[] = Arrays.stringToCharArray(tmpsrcdta);
    if (array == null)
        return newsrcdta;

    for (int i = 0; i < array.length; i++) {
        int nVal = (int) array[i];
        boolean bISO =
                // Is character ISO control
                Character.isISOControl(array[i]);
        boolean bIgnorable =
                // Is Ignorable identifier
                Character.isIdentifierIgnorable(array[i]);
        // Remove tab and other unwanted characters..
        if (nVal == 9 || bISO || bIgnorable)
            array[i] = ' ';
        else if (nVal > 255)
            array[i] = ' ';
    }
    newsrcdta = Arrays.charArrayToString(array);

    return newsrcdta;
}

這將搜索並替換所有非ASCII字母:

String resultString = subjectString.replaceAll("[^\\x00-\\x7F]", "");

FailedDev 的回答很好,但可以改進。 如果要保留 ascii 等效項,則需要先規范化:

String subjectString = "öäü";
subjectString = Normalizer.normalize(subjectString, Normalizer.Form.NFD);
String resultString = subjectString.replaceAll("[^\\x00-\\x7F]", "");

=> will produce "oau"

這樣,像“öäü”這樣的字符將被映射到“oau”,這至少保留了一些信息。 如果沒有規范化,生成的字符串將為空白。

這將是 Unicode 解決方案

String s = "A função, Ãugent";
String r = s.replaceAll("\\P{InBasic_Latin}", "");

\\p{InBasic_Latin}是包含以Unicode范圍U + 0000..U + 007F的所有字母(見的Unicode塊regular-expression.info

\\P{InBasic_Latin}是否定的\\p{InBasic_Latin}

你可以嘗試這樣的事情。 字母的特殊字符范圍從 192 開始,因此您可以在結果中避免此類字符。

String name = "A função";

StringBuilder result = new StringBuilder();
for(char val : name.toCharArray()) {
    if(val < 192) result.append(val);
}
System.out.println("Result "+result.toString());

或者您可以使用下面的函數從字符串中刪除非 ascii 字符。 您將了解內部工作。

private static String removeNonASCIIChar(String str) {
    StringBuffer buff = new StringBuffer();
    char chars[] = str.toCharArray();

    for (int i = 0; i < chars.length; i++) {
        if (0 < chars[i] && chars[i] < 127) {
            buff.append(chars[i]);
        }
    }
    return buff.toString();
}

一個易於閱讀、可打印的 ascii 流解決方案:

String result = str.chars()
    .filter(c -> isAsciiPrintable((char) c))
    .mapToObj(c -> String.valueOf((char) c))
    .collect(Collectors.joining());

private static boolean isAsciiPrintable(char ch) {
    return ch >= 32 && ch < 127;
}

轉換為“_” .map(c -> isAsciiPrintable((char) c)? c: '_')

32 到 127 相當於正則表達式[^\\x20-\\x7E] (來自對正則表達式解決方案的評論)

isAsciiPrintable 的來源: http://www.java2s.com/Code/Java/Data-Type/ChecksifthestringcontainsonlyASCIIprintablecharacters.htm

[更新解決方案]

可以與“Normalize”(規范分解)和“replaceAll”一起使用,用適當的字符替換它。

import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.regex.Pattern;

public final class NormalizeUtils {

    public static String normalizeASCII(final String string) {
        final String normalize = Normalizer.normalize(string, Form.NFD);

        return Pattern.compile("\\p{InCombiningDiacriticalMarks}+")
                      .matcher(normalize)
                      .replaceAll("");
    } ...

如果您使用的是Google Guava庫,則可以使用CharMatcher.retainFrom

String s = "A função";
String stripped = CharMatcher.ascii().retainFrom(s);
System.out.println(stripped); // Prints "A funo"

ASCII表包含128個代碼,共有95個可打印字符,其中只有52個字符是字母:

  • [0-127] ASCII 碼
    • [32-126]可打印字符
      • [48-57]位數[0-9]
      • [65-90]大寫字母[AZ]
      • [97-122]小寫字母[az]

您可以使用String.codePoints方法獲取此字符串字符的int值的流並filter非 ASCII字符:

String str1 = "A função, Ãugent";

String str2 = str1.codePoints()
        .filter(ch -> ch < 128)
        .mapToObj(Character::toString)
        .collect(Collectors.joining());

System.out.println(str2); // A funo, ugent

或者您可以明確指定字符范圍。 例如過濾掉除字母以外的所有內容

String str3 = str1.codePoints()
        .filter(ch -> ch >= 'A' && ch <= 'Z'
                || ch >= 'a' && ch <= 'z')
        .mapToObj(Character::toString)
        .collect(Collectors.joining());

System.out.println(str3); // Afunougent

另請參閱:如何在密碼驗證中不使用特殊字符(無正則表達式)?

String s = "A função";
String stripped = s.replaceAll("\\P{ASCII}", "");
System.out.println(stripped); // Prints "A funo"

或者

private static final Pattern NON_ASCII_PATTERN = Pattern.compile("\\P{ASCII}");

public static String matchAndReplaceNonEnglishChar(String tmpsrcdta) {
    return NON_ASCII_PATTERN.matcher(s).replaceAll("");
}

public static void main(String[] args) {
    matchAndReplaceNonEnglishChar("A função"); // Prints "A funo"
}

解釋

方法String.replaceAll(String regex, String replacement)用給定的替換字符串替換給定正則表達式(regex) 的所有實例。

用給定的替換替換此字符串中與給定正則表達式匹配的每個子字符串。

Java 具有匹配任何 ASCII 字符的"\\p{ASCII}"正則表達式構造,以及匹配任何非 ASCII 字符的反向"\\P{ASCII}" "\\p{ASCII}"正則表達式構造。 然后可以用空字符串替換匹配的字符,有效地將它們從結果字符串中刪除。

String s = "A função";
String stripped = s.replaceAll("\\P{ASCII}", "");
System.out.println(stripped); // Prints "A funo"

有效正則表達式構造的完整列表記錄在Pattern類中。

注意:如果您要在一次運行中多次調用此模式,則直接使用已編譯的Pattern會更有效率,而不是String.replaceAll 這樣模式只編譯一次並重用,而不是每次調用replaceAll

public class AsciiStripper {
    private static final Pattern NON_ASCII_PATTERN = Pattern.compile("\\P{ASCII}");
    
    public static String stripNonAscii(String s) {
        return NON_ASCII_PATTERN.matcher(s).replaceAll("");
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM