자바(SE)

자바 trim() 메서드 버그?

  • -

알고리즘 문제를 풀다가 황당한 상황에 빠져서 기록에 남긴다.

습관처럼 테스트케이스를 드래그해서 콘솔에 붙여 넣었다.

1      
6     
6      
1 5    
3 4    
5 4
4 2
4 6
5 2

그런데 첫 라인에 공백이 있었고 다음의 코드는 실패했다.

BufferedReader br = new BufferedReader(new StringReader(src));
int n = Integer.parseInt(br.readLine());
        
Exception in thread "main" java.lang.NumberFormatException: For input string: "1      "
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at se.code.d4.p5643_키순서.Solution.main(Solution.java:14)
        

공백이 있다니 trim()을 한방 먹여주면 해결될것 같았지만 

int n = Integer.parseInt(br.readLine().trim());

Exception in thread "main" java.lang.NumberFormatException: For input string: "1      "
	at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.base/java.lang.Integer.parseInt(Integer.java:652)
	at java.base/java.lang.Integer.parseInt(Integer.java:770)
	at se.code.d4.p5643_키순서.Solution.main(Solution.java:14)

 결과는 동일했다. java trim 메서드가 버그가 있다는 이야긴가?

당연히 그럴리는 없다. ㅜㅜ

 

문장을 구성하는 각 char들을 출력해보니 아래의 결과를 얻었다.

String line = br.readLine();
for(int i=0; i<line.length(); i++) {
	char c = line.charAt(i);
	System.out.printf("int: %d, char: ]%c[, %b\n", 0+c, c, Character.isWhitespace(c));
}

int: 49, char: ]1[, false
int: 160, char: ] [, false
int: 160, char: ] [, false
int: 160, char: ] [, false
int: 160, char: ] [, false
int: 160, char: ] [, false
int: 160, char: ] [, false

분명히 공백인데 Character.isWhitespace()를 보면 공백은 아니다. 그런데 희안한건 int로 변환한 값이 160이다. 즉 아스키 코드(~127)가 아니다.

 

unicode 160에 매핑된 키는 no-break space(줄바꿈 없는 공백: \u00A0)로 html에서 공백을 나타낼 때 사용하는 nbsp이다. 이런 값이 오는것도 신기한데 그 값이 공백이 아닌것은 더 신기하다. 

trim 메서드의 설명에 보면 trim은 white space를 제거해주는데 \u0020 이하의 space character를 대상으로 한다. 따라서 \u00A0은 대상이 아니다.

이 문자열을 처리하기 위해서는 replace로 대체시켜야 한다.

int tc = Integer.parseInt(br.readLine().replace("\u00a0", ""));

Character 클래스의 isWhitespace() 메서드를 보면 어떤 문자를 공백문자로 인식하는지 알 수 있다.

It is a Unicode space character (SPACE_SEPARATOR, LINE_SEPARATOR, or PARAGRAPH_SEPARATOR) 
     but is not also a non-breaking space ('\u00A0', '\u2007', '\u202F').
It is '\t', U+0009 HORIZONTAL TABULATION.
It is '\n', U+000A LINE FEED.
It is '\u000B', U+000B VERTICAL TABULATION.
It is '\f', U+000C FORM FEED.
It is '\r', U+000D CARRIAGE RETURN.
It is '\u001C', U+001C FILE SEPARATOR.
It is '\u001D', U+001D GROUP SEPARATOR.
It is '\u001E', U+001E RECORD SEPARATOR.
It is '\u001F', U+001F UNIT SEPARATOR.

\u00A0는 안된단다.

 

특히 웹을 통해서 전달되는 데이터가 있다면 조심할 필요가 있다.

'자바(SE)' 카테고리의 다른 글

Integer 사용 시 주의점  (0) 2020.08.07
[자료구조]Queue - add vs offer  (0) 2019.12.22
ObjectInputStream 생성 시 주의점  (0) 2019.08.07
Gson과 Json을 이용한 타입 파라미터 처리  (0) 2019.08.07
JSON 문자열 처리  (0) 2019.08.07
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.