webapp에 파일을로드하려고했지만을 FileNotFound
사용할 때 예외 가 발생했습니다 FileInputStream
. 그러나 동일한 경로를 사용하여 파일을로드 할 수있었습니다 getResourceAsStream()
. 두 방법의 차이점은 무엇이며 다른 하나는 작동하지 않는 이유는 무엇입니까?
답변
java.io.File
및 배우자들은 로컬 디스크 파일 시스템에 작용한다. 문제의 근본 원인은 상대 경로 java.io
가 현재 작업 디렉토리에 의존하기 때문입니다. 즉, JVM (웹 서버의 경우)이 시작된 디렉토리입니다. 예를 들어 이것은 C:\Tomcat\bin
완전히 다르거 나 전혀 달라도되지만 예상치 못한 결과 일 C:\Tomcat\webapps\contextname
수도 있습니다. 일반적인 이클립스 프로젝트에서는 그렇습니다 C:\Eclipse\workspace\projectname
. 다음과 같은 방법으로 현재 작업 디렉토리에 대해 배울 수 있습니다.
System.out.println(new File(".").getAbsolutePath());
그러나 작업 디렉토리는 프로그래밍 방식으로 제어 할 수 없습니다. 당신은 정말 사용을 선호한다 절대 에 경로를 File
대신 상대 경로의 API. 예 :C:\full\path\to\file.ext
.
Java (웹) 응용 프로그램의 절대 경로를 하드 코딩하거나 추측하고 싶지 않습니다. 이는 이식성 문제 일뿐입니다 (즉, 시스템 X에서는 실행되지만 시스템 Y에서는 실행되지 않음). 일반적인 방법은 이러한 종류의 리소스를 classpath 에 배치하거나 클래스 경로에 전체 경로를 추가하는 것입니다 (Eclipse와 같은 IDE에서 각각 src
폴더 및 “빌드 경로”). 이 방법으로 ClassLoader
by ClassLoader#getResource()
또는의 도움으로 그들을 잡을 수 있습니다 ClassLoader#getResourceAsStream()
. 우연의 일치로 클래스 경로의 “루트”를 기준으로 파일을 찾을 수 있습니다. 웹 응용 프로그램 (또는 여러 클래스 로더를 사용하는 다른 응용 프로그램)에서는에서 ClassLoader
반환 한대로 사용하는 것이 좋습니다Thread.currentThread().getContextClassLoader()
컨텍스트를 “외부”로 볼 수 있도록 대해 .
webapps의 또 다른 대안은 ServletContext#getResource()
및 대응 ServletContext#getResourceAsStream()
입니다. web
폴더를 포함하여 webapp 프로젝트 의 공용 폴더에있는 파일에 액세스 할 수 있습니다 /WEB-INF
. 은 ServletContext
상속에 의해 서블릿에서 사용할 수 있습니다getServletContext()
방법, 당신은있는 그대로 호출 할 수 있습니다.
또한보십시오:
답변
getResourceAsStream
이미 배운대로 웹 앱에 올바른 방법입니다.
웹 앱을 WAR로 패키지화하면 파일 시스템에서 읽을 수 없기 때문입니다. 이것은 웹앱을 패키징하는 올바른 방법입니다. 절대 파일 경로 또는 앱 서버가 설치된 위치에 의존하지 않기 때문에 이식성이 뛰어납니다.
답변
FileInputStream은 작업 디렉토리 와 관련하여 생성자에 전달하는 파일 경로를로드합니다. Java 프로세스 를 . 일반적으로 웹 컨테이너에서는 bin
폴더 와 유사 합니다.
getResourceAsStream()
응용 프로그램의 classpath에서 상대적인 파일 경로를로드합니다 .
답변
FileInputStream
클래스는 기본 파일 시스템과 직접 작동합니다. 해당 파일이 실제로 존재하지 않으면 파일을 열 수 없습니다. 이 getResourceAsStream()
방법은 다르게 작동합니다. ClassLoader
호출 된 클래스를 사용하여 자원을 찾아로드하려고 시도합니다 . 예를 들어 jar
파일에 포함 된 리소스를 찾을 수 있습니다.
답변
classname.getResourceAsStream ()은 classname의 클래스 로더를 통해 파일을로드합니다. 클래스가 jar 파일에서 온 경우 자원이로드 될 위치입니다.
FileInputStream은 파일 시스템에서 파일을 읽는 데 사용됩니다.
답변
여기에서는 File Read (java.io) 및 Resource Read (ClassLoader.getResourceAsStream ())로 표시하여 사용법을 분리하여 여기에 있습니다.
파일 읽기-1
. 로컬 파일 시스템에서 작동합니다. 2. 현재 JVM 시작 디렉토리에서 요청한 파일을 루트로 찾으려고 시도합니다. / dev / files 또는 C : \ Data와 같이 미리 결정된 위치에서 처리하기 위해 파일을 사용할 때 이상적입니다.
리소스 읽기-1
. 클래스 경로 2에서 작동합니다. 현재 또는 상위 클래스 로더 클래스 경로에서 파일 / 자원을 찾으려고 시도합니다. 3. war 또는 jar와 같은 패키지 파일에서 파일을로드 할 때 이상적입니다.