답변:
java.text.Normalizer
이것을 처리하는 데 사용하십시오 .
string = Normalizer.normalize(string, Normalizer.Form.NFD);
// or Normalizer.Form.NFKD for a more "compatable" deconstruction
이렇게하면 모든 악센트 표시가 문자와 분리됩니다. 그런 다음 각 문자를 문자와 비교하고 그렇지 않은 문자는 버리십시오.
string = string.replaceAll("[^\\p{ASCII}]", "");
텍스트가 유니 코드 인 경우 대신 다음을 사용해야합니다.
string = string.replaceAll("\\p{M}", "");
유니 코드의 \\P{M}
경우 기본 글리프와 \\p{M}
일치 하고 (소문자)는 각 액센트와 일치합니다.
포인터와 대한 GarretWilson 덕분에 regular-expressions.info 큰 유니 코드 가이드.
string.replaceAll("\\p{M}", "")
. 자세한 내용은 regular-expressions.info/unicode.html 을 참조하십시오.
2011 년 현재 Apache Commons StringUtils.stripAccents (input)를 사용할 수 있습니다 (3.0부터).
String input = StringUtils.stripAccents("Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ");
System.out.println(input);
// Prints "This is a funky String"
노트 :
허용되는 답변 (Erick Robertson 's)은 Ø 또는 Ł에서 작동하지 않습니다. Apache Commons 3.5는 Ø에서도 작동하지 않지만 Ł에서는 작동합니다. Ø 에 대한 Wikipedia 기사를 읽은 후에 는 "O"로 대체해야할지 모르겠습니다. "z"뒤에 알파벳순으로 노르웨이어와 덴마크어로 별도의 문자가 있습니다. "스트립 악센트"접근 방식의 한계에 대한 좋은 예입니다.
@ virgo47의 솔루션은 매우 빠르지 만 대략적인 것입니다. 허용되는 답변은 정규화와 정규식을 사용합니다. 정규 표현식없이 정규 표현식과 정규 표현식에서 시간의 어느 부분을 차지했는지 궁금합니다 .ASCII가 아닌 문자를 모두 제거하면 정규 표현식없이 수행 할 수 있습니다.
import java.text.Normalizer;
public class Strip {
public static String flattenToAscii(String string) {
StringBuilder sb = new StringBuilder(string.length());
string = Normalizer.normalize(string, Normalizer.Form.NFD);
for (char c : string.toCharArray()) {
if (c <= '\u007F') sb.append(c);
}
return sb.toString();
}
}
코드 선명도의 감소가 장점이 있는지 확실하지는 않지만 char []에 작성하고 toCharArray ()를 호출하지 않으면 약간의 추가 속도 향상을 얻을 수 있습니다.
public static String flattenToAscii(String string) {
char[] out = new char[string.length()];
string = Normalizer.normalize(string, Normalizer.Form.NFD);
int j = 0;
for (int i = 0, n = string.length(); i < n; ++i) {
char c = string.charAt(i);
if (c <= '\u007F') out[j++] = c;
}
return new String(out);
}
이 변형은 노멀 라이저를 사용하는 것의 정확성과 테이블을 사용하는 것의 속도의 이점이 있습니다. 내 컴퓨터에서 이것은 허용되는 답변보다 약 4 배 빠르며 @ virgo47보다 6.6 배에서 7 배 느립니다 (허용 된 답변은 내 컴퓨터의 @ virgo47보다 약 26 배 느립니다).
out
j
문자열 객체를 구성하는 데 사용되기 전에 유효한 문자 수와 일치하도록 크기를 조정해야 합니다.
flattenToAscii
결과 "aa .."를 생성합니다. 여기서 점은 \ u0000을 나타냅니다. 그건 좋지 않다. 첫 번째 질문은 "비정규 화 가능"문자를 표현하는 방법입니다. 그것이?라고 말하거나 NULL 문자를 남겨 둘 수 있지만 어쨌든 (정규 솔루션과 마찬가지로) 올바른 위치를 유지해야합니다. 이를 위해 루프의 if는 다음과 같아야합니다. if (c <= '\u007F') out[j++] = c; else if (Character.isLetter(c)) out[j++] = '?';
그것은 조금 느려질 것이지만 처음에는 정확해야합니다. ;-)
isLetter
)가 옳지 않지만 더 잘 찾지 못했습니다. 나는 유니 코드 전문가가 아니므로 원래 문자를 대체하는 단일 문자 클래스를 더 잘 식별하는 방법을 모르겠습니다. 문자는 대부분의 응용 프로그램 / 사용에 적합합니다.
편집 : Java <6에 갇혀 있지 않고 속도가 중요하지 않거나 번역 테이블이 너무 제한적인 경우 David의 답변을 사용하십시오. 요점은 Normalizer
루프 내부의 변환 테이블 대신 (Java 6에 도입) 사용하는 것입니다.
이것이 "완벽한"솔루션은 아니지만, 범위 (우리의 경우 Latin1,2)를 알고 Java 6 이전에 작동했지만 (실제 문제는 아님) 가장 제안 된 버전 (아마도 수도 있고 그렇지 않을 수도 있음)보다 훨씬 빠를 때 효과적입니다. 문제가되지 않습니다) :
/**
* Mirror of the unicode table from 00c0 to 017f without diacritics.
*/
private static final String tab00c0 = "AAAAAAACEEEEIIII" +
"DNOOOOO\u00d7\u00d8UUUUYI\u00df" +
"aaaaaaaceeeeiiii" +
"\u00f0nooooo\u00f7\u00f8uuuuy\u00fey" +
"AaAaAaCcCcCcCcDd" +
"DdEeEeEeEeEeGgGg" +
"GgGgHhHhIiIiIiIi" +
"IiJjJjKkkLlLlLlL" +
"lLlNnNnNnnNnOoOo" +
"OoOoRrRrRrSsSsSs" +
"SsTtTtTtUuUuUuUu" +
"UuUuWwYyYZzZzZzF";
/**
* Returns string without diacritics - 7 bit approximation.
*
* @param source string to convert
* @return corresponding string without diacritics
*/
public static String removeDiacritic(String source) {
char[] vysl = new char[source.length()];
char one;
for (int i = 0; i < source.length(); i++) {
one = source.charAt(i);
if (one >= '\u00c0' && one <= '\u017f') {
one = tab00c0.charAt((int) one - '\u00c0');
}
vysl[i] = one;
}
return new String(vysl);
}
32 비트 JDK로 내 HW에서 테스트 한 결과 이것이 ~ 100ms에서 àèéľšťč89FDČ에서 aeelstc89FDC로 백만 번 변환을 수행하는 반면 Normalizer 방식은 3.7 초 (37x 느리게) 만듭니다. 요구 사항이 성능에 근접하고 입력 범위를 알고있는 경우이 기능이 적합 할 수 있습니다.
즐겨 :-)
System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("\\p{InCombiningDiacriticalMarks}+", ""));
나를 위해 일했다. 위의 스 니펫 출력은 "aee"를 제공합니다.
System.out.println(Normalizer.normalize("àèé", Normalizer.Form.NFD).replaceAll("[^\\p{ASCII}]", ""));
대체하지 않았다.
언어에 따라 악센트 (문자의 소리를 변경하는)로 간주되지 않지만 발음 구별 부호로 간주 될 수 있습니다.
https://ko.wikipedia.org/wiki/Diacritic#Languages_with_letters_include_diacritics
"보스니아 어와 크로아티아어는 č, ć, đ, š 및 ž의 기호를가집니다.이 기호는 별도의 문자로 간주되며 사전과 기타 문맥에서 단어가 알파벳 순서로 나열됩니다."
그것들을 제거하는 것은 본질적으로 단어의 의미를 바꾸거나 글자를 완전히 다른 단어로 바꾸는 것일 수 있습니다.
Strings equality check와 관련하여 동일한 문제에 직면했습니다. 비교 문자열 중 하나에는 ASCII 문자 코드 128-255가 있습니다.
즉, 비 분리 공간-[Hex-A0] Space [Hex-20]. HTML에 비 공백 공간을 표시합니다. 나는 다음을 사용했다
spacing entities
. 그들의 성격과 바이트는&emsp is very wide space[ ]{-30, -128, -125}, &ensp is somewhat wide space[ ]{-30, -128, -126}, &thinsp is narrow space[ ]{32} , Non HTML Space {}
String s1 = "My Sample Space Data", s2 = "My Sample Space Data"; System.out.format("S1: %s\n", java.util.Arrays.toString(s1.getBytes())); System.out.format("S2: %s\n", java.util.Arrays.toString(s2.getBytes()));
바이트 단위 출력 :
S1 : [77, 121,,
32
83, 97, 109, 112, 108, 101,,32
83, 112, 97, 99, 10132
,, 68, 97, 116, 97] S2 : [77, 121-30, -128, -125
,, 83, 97, 109, 112, 108, 101,,-30, -128, -125
83, 112, 97, 99, 101-30, -128, -125
,, 68, 97, 116, 97]
다른 공간과 바이트 코드에 아래 코드를 사용하십시오. wiki for List_of_Unicode_characters
String spacing_entities = "very wide space,narrow space,regular space,invisible separator";
System.out.println("Space String :"+ spacing_entities);
byte[] byteArray =
// spacing_entities.getBytes( Charset.forName("UTF-8") );
// Charset.forName("UTF-8").encode( s2 ).array();
{-30, -128, -125, 44, -30, -128, -126, 44, 32, 44, -62, -96};
System.out.println("Bytes:"+ Arrays.toString( byteArray ) );
try {
System.out.format("Bytes to String[%S] \n ", new String(byteArray, "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
for Java 용 유니 코드 문자열의 ASCII 음역. unidecode
String initials = Unidecode.decode( s2 );
➩ 사용 Guava
: Google Core Libraries for Java
.
String replaceFrom = CharMatcher.WHITESPACE.replaceFrom( s2, " " );
공간에 대한 URL 인코딩 의 경우 Guava laibrary를 사용하십시오.
String encodedString = UrlEscapers.urlFragmentEscaper().escape(inputString);
String.replaceAll()
some 일부와 함께 사용되는이 문제를 극복하기 위해 RegularExpression
.
// \p{Z} or \p{Separator}: any kind of whitespace or invisible separator.
s2 = s2.replaceAll("\\p{Zs}", " ");
s2 = s2.replaceAll("[^\\p{ASCII}]", " ");
s2 = s2.replaceAll(" ", " ");
java java.text.Normalizer.Form 사용 . 이 열거 형은 유니 코드 표준 부록 # 15- 유니 코드 정규화 양식에 설명 된 네 가지 유니 코드 정규화 형식과 이에 액세스하는 두 가지 방법의 상수를 제공 합니다.
s2 = Normalizer.normalize(s2, Normalizer.Form.NFKC);
Unidecode, Normalizer, StringUtils 와 같은 다양한 접근 방식에서 문자열 및 출력 테스트 .
String strUni = "Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß";
// This is a funky String AE,O,D,ss
String initials = Unidecode.decode( strUni );
// Following Produce this o/p: Tĥïŝ ĩš â fůňķŷ Šťŕĭńġ Æ,Ø,Ð,ß
String temp = Normalizer.normalize(strUni, Normalizer.Form.NFD);
Pattern pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
temp = pattern.matcher(temp).replaceAll("");
String input = org.apache.commons.lang3.StringUtils.stripAccents( strUni );
Unidecode 사용 은 best choice
아래에 표시된 내 최종 코드입니다.
public static void main(String[] args) {
String s1 = "My Sample Space Data", s2 = "My Sample Space Data";
String initials = Unidecode.decode( s2 );
if( s1.equals(s2)) { //[ , ] %A0 - %2C - %20 « http://www.ascii-code.com/
System.out.println("Equal Unicode Strings");
} else if( s1.equals( initials ) ) {
System.out.println("Equal Non Unicode Strings");
} else {
System.out.println("Not Equal");
}
}
Junidecode 제안 합니다 . 'Ł'와 'Ø'를 처리 할뿐만 아니라 중국어와 같은 다른 알파벳을 라틴 알파벳으로 변환하는 데에도 효과적입니다.
@David Conrad 솔루션은 노멀 라이저를 사용하여 가장 빠르게 시도했지만 버그가 있습니다. 기본적으로 악센트가 아닌 문자를 제거합니다. 예를 들어 중국어 문자와 같은 다른 문자는 모두 제거됩니다. 우리가 제거하고자하는 문자는 간격이 아닌 문자이며 최종 문자열에서 여분의 너비를 차지하지 않는 문자입니다. 이 폭이 0 인 문자는 기본적으로 다른 문자와 결합됩니다. 예를 들어,`처럼 문자로 분리 된 것을 볼 수 있다면, 공백 문자와 결합 된 것 같습니다.
public static String flattenToAscii(String string) {
char[] out = new char[string.length()];
String norm = Normalizer.normalize(string, Normalizer.Form.NFD);
int j = 0;
for (int i = 0, n = norm.length(); i < n; ++i) {
char c = norm.charAt(i);
int type = Character.getType(c);
//Log.d(TAG,""+c);
//by Ricardo, modified the character check for accents, ref: http://stackoverflow.com/a/5697575/689223
if (type != Character.NON_SPACING_MARK){
out[j] = c;
j++;
}
}
//Log.d(TAG,"normalized string:"+norm+"/"+new String(out));
return new String(out);
}
라이브러리가없는 경우 정규 표현식과 노멀 라이저를 사용 하는 가장 좋은 방법 중 하나는 다음 과 같습니다.
public String flattenToAscii(String s) {
if(s == null || s.trim().length() == 0)
return "";
return Normalizer.normalize(s, Normalizer.Form.NFD).replaceAll("[\u0300-\u036F]", "");
}
replaceAll ( "[^ \ p {ASCII}]", ""))보다 효율적이며 분음 부호가 필요하지 않은 경우 (예와 같이).
그렇지 않으면 p {ASCII} 패턴을 사용해야합니다.
문안 인사.
가장 좋은 해결책은 각 문자를 HEX로 변환하고 다른 HEX로 바꾸는 것입니다. 두 가지 유니 코드 입력이 있기 때문입니다.
Composite Unicode
Precomposed Unicode
예를 들어 Composite Unicode로 작성된 "Ồ"은 Precomposed Unicode로 작성된 "Ồ"과 다릅니다. 샘플 문자를 복사하여 변환하여 차이점을 확인할 수 있습니다.
In Composite Unicode, "Ồ" is combined from 2 char: Ô (U+00d4) and ̀ (U+0300)
In Precomposed Unicode, "Ồ" is single char (U+1ED2)
일부 은행에서 정보를 코어 뱅크 (보통 유니 코드를 지원하지 않음)로 보내기 전에 정보를 변환하기 위해이 기능을 개발했으며 최종 사용자가 여러 유니 코드 타이핑을 사용하여 데이터를 입력 할 때이 문제에 직면했습니다. 따라서 HEX로 변환하고 교체하는 것이 가장 신뢰할 수있는 방법이라고 생각합니다.
누군가 코 틀린에서 이것을하기 위해 고군분투하고 있다면,이 코드는 매력처럼 작동합니다. 불일치를 피하기 위해 .toUpperCase 및 Trim ()도 사용합니다. 그런 다음이 기능을 캐스팅합니다.
fun stripAccents(s: String):String{
if (s == null) {
return "";
}
val chars: CharArray = s.toCharArray()
var sb = StringBuilder(s)
var cont: Int = 0
while (chars.size > cont) {
var c: kotlin.Char
c = chars[cont]
var c2:String = c.toString()
//these are my needs, in case you need to convert other accents just Add new entries aqui
c2 = c2.replace("Ã", "A")
c2 = c2.replace("Õ", "O")
c2 = c2.replace("Ç", "C")
c2 = c2.replace("Á", "A")
c2 = c2.replace("Ó", "O")
c2 = c2.replace("Ê", "E")
c2 = c2.replace("É", "E")
c2 = c2.replace("Ú", "U")
c = c2.single()
sb.setCharAt(cont, c)
cont++
}
return sb.toString()
}
이 재미를 사용하려면 다음과 같이 코드를 캐스팅하십시오.
var str: String
str = editText.text.toString() //get the text from EditText
str = str.toUpperCase().trim()
str = stripAccents(str) //call the function