2017-12-21 1 views
2

문자열의 첫 번째 기호를 표시해야합니다. 이에 대한 simpliest 코드는 다음과 같습니다문자열의 첫 번째 기호를 얻는 방법

String text = "test string"; 
char firstSymbol = text[0]; 

을하지만 문자 예를 "\uD83D\uDC68" (U+1F468)의 경우, 16 비트에 맞지 않으면이 작동하지 않습니다. 문자의 절반 만 반환되며 물음표로 렌더링됩니다.

String text = "test string"; 
int codePoint = text.codePointAt(0); 
char[] chars = Character.toChars(codePoint); 
String firstSymbol = new String(chars); 

이는 유니 코드로 표현 된 모든 문자에 잘 적용됩니다. 그러나 유니 코드 문자 시퀀스가 ​​하나의 심볼로 표시됩니다. 위의 코드를 실행하면 "\uD83D\uDC68\u200D\uD83D\uDCBB"() 에서처럼 기호의 일부만 표시됩니다. 이 경우 결과는 전체 문자열이되고 싶습니다. 그런 경우 어떻게 처리 할 수 ​​있습니까?


물론 charAt() 물론 내 잘못이어야합니다. 그러나 char은 UTF-16으로 인코딩되며 여러 문자를 포함 할 수 없습니다. 첫번째 예는이 같아야

String text = "test string"; 
char firstSymbol = text.charAt(0); 

하나 개의 심볼에 대한 또 다른 예는 힘든 "\u0D23\u0D4D\u200D"이다 (ണ്). 끝에는 두 개의 문자와 너비가없는 결합자가 있습니다.


나는 ICU4J에서 내려 android.icu 라이브러리를 사용하려고했지만, 불행하게도 그것은 API (24) 또한 그것은 경우 문자를 가입하지 않는 즉, 두 번째 예제와 같은 결과를 생성부터에만 지원됩니다 너비가 0 인 결합 자 (joiner)가 그들 사이에 있습니다.

int breakIterator = BreakIterator.getCharacterInstance(); 
breakIterator.setText(text); 
int begin = breakIterator.first(); 
int end = breakIterator.next(); 
String firstSymbol = text.substring(begin, end); 
+2

을 "그러나이 문자가 16 비트에 맞지 않으면 작동하지 않습니다. "-> (char firstSymobl = text [0];) 구문이 잘못되어 작동하지 않습니다. 나는 당신이 "text.charAt (0)'("16 비트 이상 "문제를 수정하지 않을 것임)을 사용하려고 생각한다고 생각합니다. – Turing85

+0

text.substring (0,1)을 사용하면 string의 첫 번째 문자를 줄 수 있습니다. 하지만 그렇게하기 전에 문자열이 null이 아닌지 확인하십시오. – Lucky

+0

@Lucky 그것은 'char'가 아닌 size 1의'String'을 반환합니다.'String'으로부터 문자를 얻는 메소드는'charAt (int index)'입니다. – Nathan

답변

2

\u200D은 유니 코드 코드 포인트 U+200D ZERO WIDTH JOINER입니다. 또한

String text = ...; 
StringBuilder sequence = new StringBuilder(text.length()); 
boolean isInJoin = false; 
int codePoint; 

for (int i = 0; i < text.length(); i = text.offsetByCodePoints(i, 1)) 
{ 
    codePoint = text.codePointAt(i); 

    if (codePoint == 0x200D) 
    { 
     isInJoin = true; 
     if (sequence.length() == 0) 
      continue; 
    } 
    else 
    { 
     if ((sequence.length() > 0) && (!isInJoin)) break; 
     isInJoin = false; 
    } 

    sequence.appendCodePoint(codePoint); 
} 

if (isInJoin) 
{ 
    for(int i = sequence.length()-1; i >= 0; --i) 
    { 
     if (sequence.charAt(i) == 0x200D) 
      sequence.deleteCharAt(i); 
     else 
      break; 
    } 
} 

String firstSymbols = sequence.toString(); 

: 당신이 가입 코드 포인트의 시퀀스를 추출 할 경우, 당신은 당신이 비에 합류 코드 포인트, 예를 들면 발생할 때까지 수동으로 문자열을 반복해야 할 것

String text = ...; 
boolean isInJoin = false; 
int start = 0, length = 0, next; 
int codePoint; 

for (int i = 0; i < text.length(); i = next) 
{ 
    codePoint = text.codePointAt(i); 

    if (codePoint == 0x200D) 
    { 
     isInJoin = true; 
     if (length == 0) 
     { 
      next = text.offsetByCodePoints(i, 1); 
      start = next; 
      continue; 
     } 
    } 
    else 
    { 
     if ((length > 0) && (!isInJoin)) break; 
     isInJoin = false; 
    } 

    next = text.offsetByCodePoints(i, 1); 
    length += (next - i); 
} 

if (isInJoin) 
{ 
    for(int i = length-1; i >= 0; --i) 
    { 
     if (text.charAt(i) == 0x200D) 
      --length; 
     else 
      break; 
    } 
} 

String firstSymbols = text.substring(start, start+length); 
3

나는 당신이 split 수, 그림 이모티콘 가입 Zero-width joiner(\u200D) 문자를 사용하는 것으로 나타났습니다 당신이 문자로 String :

String[] result = text.split("\u200D"); 

그리고 다음 방법으로 첫 번째 문자 수 :

String firstSymbol = result[0]; 
+0

제로 너비의 결합자를 언급 해 주셔서 감사합니다. 이에 대해 자세히 알아 보겠습니다. 그러나 결과를 올바르게 표시 할 수 있도록 결합 된 이모티콘을 모두 가져와야합니다.문자열을 반복하고 제로 너비의 결합 자로 분리 된 경우 이모티콘에 가입하려고합니다. – fdermishin

+1

'String'을 제로 너비 결합 자로 분리하면 문자열 배열을 얻게되며, 반복을 통해 이모티콘을 하나씩 가져올 수 있습니다. –

+0

구현 한 적이 있지만 너무 많은 구석이 나타나면 제대로 작동하지 않습니다. 업데이트 된 질문을보십시오. – fdermishin

관련 문제