재밌고 어려운 IT를 이해해보자~!
버퍼 에러!!!!!!!!!!!!!!!!!!!!!!!!! 본문
아주아주아주아주아주아주아주 재밌고 신기한 에러를 발견했다!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!뒤늦게...
프로젝트 코드작성 후 테스트중에 nextInt(), nextLine()을 사용하여 생기는 개행문자(Enter, "\n" )를 먼저 받아들여 원하는 값을 못받는 에러를 만났다!
당연히 nextLine()을 입력받기 전 nextInt() 를 사용한 곳 이후의 버퍼를 비워주면 될 것 이라고 생각했다...................
자 먼저 개행문자를 받아들인 예시를 보자.
nextInt() 는 입력값으로 들어온 값 중에 Enter나 공백을 기준, 그 앞의 Int형 값을 가져온다.
위 코드의 경우 정수를 가져왔으며, 버퍼에 남아있는 값은 Enter "\n" 이다.
nextLine() 은 버퍼에 남은 것들을 문자열로 가져와버립니다.
그래서 Enter 값을 공백 문자열로 가져와버리고 끝나기 때문에 출력 단계로 넘어간 것이다.
예를 들어, 1를 입력하고 Enter를 입력하면 버퍼에 줄바꿈을 나타내는 1\n 이 존재한다. nextInt()는 개행문자를 제외하고 내용을 가져오기 때문에 1만 가져오고, 버퍼에는 개행문자 \n 이 남는 것이다.
이 다음에 nextLine()을 사용하면 공백과, 개행문자를 포함하기 때문에 개행문자만 가져오고 프로그램이 종료된다.
이를 해결하기 위해서는 nextLine()을 nextInt()밑에 한줄 추가해서 버퍼에 남아있던 개행문자는 nextLine()에 의해 입력되어 사라지고 새로 nextLine()을 실행해서 한줄을 받아오게 된다.
자이제 우리의 프로젝트 코드를 보자!
우리가 nextInt()를 사용하는 메서드는 2개이고, 제목과 내용을 nextLine()으로 입력받는 메서드가 존재한다.
게시판 번호 입력받기
public int inputBoardNum() {
System.out.print("게시글 번호를 입력해주세요 >> ");
int selectNum = 0;
try {
selectNum = sc.nextInt();
} catch (InputMismatchException e) {
e.printStackTrace();
sc.nextLine();
}
return selectNum;
}
번호 입력받기
public int inputNum() {
System.out.print("번호를 입력해주세요. >> ");
while (true) { // 번호 입력받기 범위 유효성 검사
try {
int chooseNum = sc.nextInt();
if (chooseNum < 0) { // 마이너스 값을 입력한 경우
System.out.print("유효하지 않은 번호입니다. >>");
continue;
} else { // 카테고리 범위 외의 정수를 입력한 경우
return chooseNum;
}
} catch (Exception e) { // 정수가 아닌 값을 입력한 경우
System.out.print("'정수'만 입력가능합니다. >>");
sc.nextLine();
}
}
}
제목, 내용 입력받기
// 게시글 제목과 내용 입력
public BoardDTO boardInsert() {
BoardDTO bDTO = new BoardDTO();
System.out.print("제목 입력을 입력해 주세요. >> ");
bDTO.setTitle(sc.nextLine());
System.out.print("내용을 입력해 주세요. >> ");
bDTO.setContents(sc.nextLine());
return bDTO;
}
자 이제 에러가 난 상황을 연출해보겠다!
CASE 1
로그인 이후 바로 게시글 작성을 했을 떄 !
번호를 입력받는 메서드를 통해 int를 리턴받아 Ctrl에서 사용하고
NextLine()을 통해 제목과 내용을 입력받는 메서드를 거쳐 DB에 INSERT되고 아무 문제가 없다.
CASE 2
게시글 전체 목록 출력 후
게시글 번호를 선택하고,
이전 화면으로 돌아간 후에
다시한번 게시글 작성을 했을때!
(문장도틀렸네)
제목 입력을 입력해 주세요 >>
이부분에서 개행문자 "\n"이 들어가는 바람에
바로 내용을 입력해달라는 문구가 나오는 것이다!
바로 게시글을 것도 번호입력 메서드를 거친 후에 입력하는 것이고,
게시글 목록 출력 후 이전화면으로 돌아온 후에 게시글을 작성하는 것도 번호입력 메서드를 거친 후에 입력하는 것으로 동일한하다! 아하~ 번호입력 메서드에서 nextInt를 받은 후에 버퍼에 남은 개행문자를 지워줘야겠다!
라고 생각해서 번호입력 메서드에 sc.nextLine()을 통해 버퍼를 지워줘봤지만,,, 동일한 에러가 발생한다.
그 외에도 아주 다양한 곳에서 버퍼를 비워봤지만 여전히 에러가발생한다!
뭐 가 문 제 일 까?
와,,,진짜 말이안돼 살려줘
InputNum() 과 InputBoardNum()을 완전히 동일하게 작성하여도 BoardNum쪽만 에러가 발생한다!!!!
public int inputNum() {
System.out.print("번호를 입력해주세요. >> ");
while (true) { // 번호 입력받기 범위 유효성 검사
try {
int chooseNum = sc.nextInt();
if (chooseNum < 0) { // 마이너스 값을 입력한 경우
System.out.print("유효하지 않은 번호입니다. >>");
continue;
} else { // 카테고리 범위 외의 정수를 입력한 경우
return chooseNum;
}
} catch (Exception e) { // 정수가 아닌 값을 입력한 경우
System.out.print("'정수'만 입력가능합니다. >>");
sc.nextLine();
}
}
}
public int inputBoardNum() {
System.out.print("게시글 번호를 입력해주세요. >> ");
while (true) { // 번호 입력받기 범위 유효성 검사
try {
int chooseNum = sc.nextInt();
if (chooseNum < 0) { // 마이너스 값을 입력한 경우
System.out.print("유효하지 않은 번호입니다. >>");
continue;
} else { // 카테고리 범위 외의 정수를 입력한 경우
return chooseNum;
}
} catch (Exception e) { // 정수가 아닌 값을 입력한 경우
System.out.print("'정수'만 입력가능합니다. >>");
sc.nextLine();
}
}
}
이게말이되나!!!!!!!!!!!!
두 메서드의 차이점을 분석해보자..
InputNum() -> CommonView 클래스 안에 존재
BoardInputNum() -> BoardView 클래스 안에 존재
BoardInsert() -> BoardView 클래스 안에 존재....
와... 이게 BoardInputNum() 메서드에서 사용한 nextInt()의 버퍼가 같은 클래스내에서 남아있어서 BoardInsert()실행시
제목에 엔터키값이 들어간 것 같다!!!!!!!!!!!!!!!!!!!!!!!!!!!
// 게시글 제목과 내용 입력
public BoardDTO boardInsert() {
if(sc.hasNextLine()) {
System.out.println("아오보드자시가!!");
}
BoardDTO bDTO = new BoardDTO();
System.out.print("제목 입력을 입력해 주세요. >> ");
bDTO.setTitle(sc.nextLine());
System.out.print("내용을 입력해 주세요. >> ");
bDTO.setContents(sc.nextLine());
return bDTO;
}
BoardInputNum() 에 hasNextLine()으로 입력받을게 있는지 확인했더니!
True가 발생했고 아오보드자시가!!! 가 출력되었다.
그리고 제목에는 엔터키 값이 들어간다!
결국엔,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
같은 클래스 내에서 사용하는 Scanner의 버퍼상태를 잘 확인해야 하는걸로 파악된다 아직까진!!!!!
재밌는 버그였지만 찾아내기까지 너무너무 힘들었다!
'JAVA Error Solution' 카테고리의 다른 글
NullPointerException (0) | 2024.01.17 |
---|---|
java.lang.IllegalArgumentException (0) | 2024.01.13 |
java.lang.IllegalStateException: Scanner closed (0) | 2024.01.01 |
SQLException ORA-12519, TNS:no appropriate service handler found (0) | 2023.12.22 |
NullPointerException (0) | 2023.12.20 |