파일을 통한 입출력을 테스트하던 중, 크게 두 가지 오류가 발생했다.
문제 해결 과정을 설명하기에 앞서 오류 발생 코드는 다음과 같다.
Calculator는 파일에 쓰여진 숫자를 라인단위로 읽고, 그 합을 모두 더하는 클래스이다.
실행 과정
1. Calculator 객체 생성
2. calcSum 함수의 매개변수로 "numbers.txt" 파일의 경로를 넘김
3. calcSum함수는 매개변수로 넘어온 경로의 파일을 읽고, sum을 리턴함
4. 리턴 값이 10과 일치하는지 검사
첫번째 오류
문제 상황
getResource() 메서드가 null 값을 반환하여 getPath() 함수를 호출할 수 없다는 오류가 발생한다.
문제 원인
getClass.getResource()는 호출한 클래스 패키지를 기준으로 상대경로를 탐색 하는데, 탐색 결과 "numbers.txt"를 찾지 못한 거 같다.
해결 방법
발견한 해결책은 두 가지였다.
1. getClass().getClassLoader().getResource("numbers.txt")
2. getClass().getResource("/numbers.txt")
첫 번째 방법은 getClassLoader를 이용한 방법으로, numbers.txt의 절대경로를 가져온다.
두 번째 방법은 getResource 매개변수로 앞에 "/"를 포함시키면 루트경로부터 numbers.txt를 찾아서 경로를 가져온다.
두 해결책을 보면, 어째서 getClass().getResource("numbers.txt")는 안 되는 지 아직도 모르겠다.
잘 아시는 분이 계신다면 알려주시면 감사하겠습니다 ㅠㅠ
두 번째 오류
위 NullPointerException을 해결한 후 바로 곧바로 직면한 두 번째 오류이다.
문제 상황
경로에서 파일을 찾을 수 없다는 오류이다.
문제 원인
분명 getResource를 통해 경로를 얻어왔고, 해당 경로에는 분명 파일이 존재하는데 왜 파일을 찾지 못한다는 걸까?
원인을 이해하려면 먼저 아래 코드의 이해가 필요하다.
calcSum의 매개변수는 String 타입의 filePath이다.
getClass().getResource("/numbers.txt").getPath()
즉, 위 코드는 String을 반환하는 것을 의미한다.
하나하나 따져보자.
getClass() : 해당 객체의 Class 정보를 조회하고, class 타입을 리턴한다.(class 이름이 class임)
getResource(String name) : Class 클래스의 메서드로, name 이름을 가진 파일의 경로를 URL 객체로 반환한다.
getPath() : URL 클래스의 메서드로, 넘어온 경로를 문자열 경로로 반환한다.
1. getClass로 Calculator 클래스 정보를 얻어온다
2. getResource로 주어진 이름의 파일 경로를 찾는다.
3. URL 객체로 반환된 값을 getPath()를 통해 문자열로 바꿔준다.
위 순서대로 경로를 찾아 문자열을 얻어온다.
문제될 것이 없어 보이는데, 어디서 문제가 발생한 것인가..
문제는 바로, 2번 과정에서 발생한다
getResource의 반환 객체인, URL 객체로부터 경로를 획득할 시, 인코딩된 경로가 반환된다.
URL 인코딩 전
/Toby Spring/user/out/test/resources/numbers.txt
URL 인코딩 후
/Toby%20Spring/user/out/test/resources/numbers.txt
따라서 인코딩된 경로의 파일을 찾으려고 하니 찾을 수 없었던 것이다.
해결 방법
한글과 공백을 포함한 경로를 굳이 사용하기 위해서 품을 들이는 것 보다
경로상에 한글이나 공백이 없는 것이 가장 베스트가 아닐까 싶다..
따라서 파일 이름을 Tody Spring -> Tody_Spring으로 바꾸었다.
하.. 이 초록 불 보려고 얼마나 시간이 들었는가 ....
참고 :
https://junhyunny.github.io/java/get-file-path-and-precaution/
https://docs.oracle.com/javase/8/docs/api/
https://stackoverflow.com/questions/4301329/java-class-getresource-returns-null
'트러블 슈팅' 카테고리의 다른 글
hibernate가 기존 DB 테이블을 재생성하는 문제 (0) | 2024.08.05 |
---|---|
JPA Entity 매핑 관련 오류(java.sql.SQLNonTransientConnectionException) (0) | 2024.05.27 |
DB 연동을 위한 도커 경로 설정 문제 (1) | 2024.05.27 |
Docker build context와 파일 인식 (0) | 2024.05.13 |
[Spring webFlux] Unable to load io.netty.resolver.dns.macos ... 오류 (0) | 2024.03.28 |