Java JAR 파일에서 리소스에 대한 경로를 가져오는 방법
나는 자원으로 가는 길을 찾으려고 노력하고 있지만 운이 없었다.
IDE 및 JAR에서 모두 작동하지만 이렇게 하면 파일 내용만 얻을 수 있음:
ClassLoader classLoader = getClass().getClassLoader();
PrintInputStream(classLoader.getResourceAsStream("config/netclient.p"));
이렇게 하면:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("config/netclient.p").getFile());
결과는 다음과 같다.java.io.FileNotFoundException: file:/path/to/jarfile/bot.jar!/config/netclient.p (No such file or directory)
리소스 파일의 경로를 얻을 수 있는 방법이 있는가?
이건 고의야."파일"의 내용은 파일로 사용할 수 없을 수 있다.JAR 파일 또는 다른 종류의 리소스의 일부일 수 있는 클래스 및 리소스를 처리하고 있음을 기억하십시오.classloader는 자원에 파일 핸들을 제공할 필요가 없다. 예를 들어 jar 파일이 파일 시스템의 개별 파일로 확장되지 않았을 수 있다.
java.io을 얻어서 당신이 할 수 있는 모든 것.java.io이라면 스트림을 임시 파일로 복사하여 같은 작업을 할 수 있다.파일은 절대적으로 필요하다.
리소스를 로드할 때 다음 사항 간의 차이점을 확인하십시오.
getClass().getClassLoader().getResource("com/myorg/foo.jpg") //relative path
그리고
getClass().getResource("/com/myorg/foo.jpg")); //note the slash at the beginning
내 생각에, 이 혼란은 자원을 적재할 때 대부분의 문제를 야기하고 있는 것 같아.
또한 이미지를 로드할 때 보다 쉽게 사용할 수 있음getResourceAsStream()
:
BufferedImage image = ImageIO.read(getClass().getResourceAsStream("/com/myorg/foo.jpg"));
JAR 아카이브에서 (이미지가 아닌) 파일을 로드해야 하는 경우 다음을 시도해 보십시오.
File file = null;
String resource = "/com/myorg/foo.xml";
URL res = getClass().getResource(resource);
if (res.getProtocol().equals("jar")) {
try {
InputStream input = getClass().getResourceAsStream(resource);
file = File.createTempFile("tempfile", ".tmp");
OutputStream out = new FileOutputStream(file);
int read;
byte[] bytes = new byte[1024];
while ((read = input.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.close();
file.deleteOnExit();
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
} else {
//this will probably work in your IDE, but not from a JAR
file = new File(res.getFile());
}
if (file != null && !file.exists()) {
throw new RuntimeException("Error: File " + file + " not found!");
}
한 줄의 대답은 -이다.
String path = this.getClass().getClassLoader().getResource(<resourceFileName>).toExternalForm()
기본적으로 방법은 URL을 제공한다. 이 URL에서 호출하여 경로를 추출할 수 있다.
나는 이 문제를 해결하는데 시간을 보냈다. 왜냐하면 어떤 해결책도 효과가 없었기 때문이다, 이상하게도!작업 디렉토리는 특히 Windows 아래의 시작 메뉴에서 JAR(또는 해당 프로그램의 경우)을 실행하는 경우 JAR의 디렉토리가 아닌 경우가 많다.그래서 내가 한 일이 있는데, JAR에서 실행되는 것과 마찬가지로 JAR 외부에서 실행되는 .class 파일에도 해당된다. (Windows 7에서 테스트했을 뿐이다.)
try {
//Attempt to get the path of the actual JAR file, because the working directory is frequently not where the file is.
//Example: file:/D:/all/Java/TitanWaterworks/TitanWaterworks-en.jar!/TitanWaterworks.class
//Another example: /D:/all/Java/TitanWaterworks/TitanWaterworks.class
PROGRAM_DIRECTORY = getClass().getClassLoader().getResource("TitanWaterworks.class").getPath(); // Gets the path of the class or jar.
//Find the last ! and cut it off at that location. If this isn't being run from a jar, there is no !, so it'll cause an exception, which is fine.
try {
PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('!'));
} catch (Exception e) { }
//Find the last / and cut it off at that location.
PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(0, PROGRAM_DIRECTORY.lastIndexOf('/') + 1);
//If it starts with /, cut it off.
if (PROGRAM_DIRECTORY.startsWith("/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(1, PROGRAM_DIRECTORY.length());
//If it starts with file:/, cut that off, too.
if (PROGRAM_DIRECTORY.startsWith("file:/")) PROGRAM_DIRECTORY = PROGRAM_DIRECTORY.substring(6, PROGRAM_DIRECTORY.length());
} catch (Exception e) {
PROGRAM_DIRECTORY = ""; //Current working directory instead.
}
만일netclient.p
JAR 파일 안에 있는데 다른 파일 안에 위치하기 때문에 경로가 없을 겁니다.그 경우에, 당신이 가질 수 있는 가장 좋은 길은 정말이다.file:/path/to/jarfile/bot.jar!/config/netclient.p
.
이것은 항아리 자원의 불완전한 임시 파일 내용 복사를 방지하고 고유한 임시 파일 이름을 가지기 위해 스트림 플러시 및 닫힌 사용자 Tombart의 코드와 같다.
File file = null;
String resource = "/view/Trial_main.html" ;
URL res = getClass().getResource(resource);
if (res.toString().startsWith("jar:")) {
try {
InputStream input = getClass().getResourceAsStream(resource);
file = File.createTempFile(new Date().getTime()+"", ".html");
OutputStream out = new FileOutputStream(file);
int read;
byte[] bytes = new byte[1024];
while ((read = input.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
input.close();
file.deleteOnExit();
} catch (IOException ex) {
ex.printStackTrace();
}
} else {
//this will probably work in your IDE, but not from a JAR
file = new File(res.getFile());
}
항아리 파일 안의 경로를 이해해야 한다.
단순히 상대적인 것을 참고하라.그래서 만약 당신이 (내 파일)을 가지고 있다면.txt), 아래 foo.jar에 위치\src\main\resources
디렉토리(메이븐 스타일).다음과 같이 언급할 수 있다.
src/main/resources/myfile.txt
만약 당신이 당신의 항아리를 버리면jar -tvf myjar.jar
jar 파일 내에 출력 및 상대 경로가 표시되며, FORWARD SLASH를 사용한다.
나의 경우 Path 대신 URL 객체를 사용해 왔다.
파일
File file = new File("my_path");
URL url = file.toURI().toURL();
classloader를 사용하는 classpath의 리소스
URL url = MyClass.class.getClassLoader().getResource("resource_name")
내용을 읽어야 할 때 다음 코드를 사용할 수 있다.
InputStream stream = url.openStream();
그리고 InputStream을 사용하여 컨텐츠에 액세스할 수 있다.
A File은 파일 시스템의 파일을 추상화하는 것으로, 파일 시스템은 JAR의 내용이 무엇인지 전혀 알지 못한다.
URI를 사용해 보십시오. 자줏대감에서 유용할 수 있는 jar:/
규칙을 따르라!
/src/main/main/file
streamToFile(getClass().getClassLoader().getResourceAsStream("file"))
public static File streamToFile(InputStream in) {
if (in == null) {
return null;
}
try {
File f = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
f.deleteOnExit();
FileOutputStream out = new FileOutputStream(f);
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
return f;
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
return null;
}
}
다음과 같은 길이 내게 통했다.classpath:/path/to/resource/in/jar
private static final String FILE_LOCATION = "com/input/file/somefile.txt";
//Method Body
InputStream invalidCharacterInputStream = URLClassLoader.getSystemResourceAsStream(FILE_LOCATION);
이것으로부터 얻는 것이 가장 좋은 선택이다.파일이나 URL이 아닌 입력 스트림을 가져오면 JAR 파일에서 독립 실행형으로 작동한다.
시간이 좀 늦을 수도 있지만 내 라이브러리 KResourceLoader를 사용하여 항아리로부터 리소스를 가져오십시오.
File resource = getResource("file.txt")
jar의 resource 폴더(java/main/resource) 안에 파일을 추가(imports.xml이라는 xml 파일을 추가한 것으로 가정함)한 후 주입ResourceLoader
봄을 맹렬히 사용한다면.
@Autowired
private ResourceLoader resourceLoader;
inside tour function은 파일을 로드하기 위해 bellow 코드를 쓴다.
Resource resource = resourceLoader.getResource("classpath:imports.xml");
try{
File file;
file = resource.getFile();//will load the file
...
}catch(IOException e){e.printStackTrace();}
아마도 이 방법은 빠른 해결책을 위해 사용될 수 있을 것이다.
public class TestUtility
{
public static File getInternalResource(String relativePath)
{
File resourceFile = null;
URL location = TestUtility.class.getProtectionDomain().getCodeSource().getLocation();
String codeLocation = location.toString();
try{
if (codeLocation.endsWith(".jar"){
//Call from jar
Path path = Paths.get(location.toURI()).resolve("../classes/" + relativePath).normalize();
resourceFile = path.toFile();
}else{
//Call from IDE
resourceFile = new File(TestUtility.class.getClassLoader().getResource(relativePath).getPath());
}
}catch(URISyntaxException ex){
ex.printStackTrace();
}
return resourceFile;
}
}
에 있을 때jar
파일, 리소스는 파일 시스템 계층이 아닌 패키지 계층에 절대적으로 위치함.그래서 만약 당신이 수업이 있다면com.example.Sweet
이름이 지정된 리소스 로드./default.conf
그러면 리소스의 이름이 다음과 같이 지정됨/com/example/default.conf
.
하지만 항아리에 들어있다면 그건 파일이 아니야...
이 클래스 기능은 .jar 파일의 상대 파일 경로로 절대 파일 경로를 가져올 수 있다.
public class Utility {
public static void main(String[] args) throws Exception {
Utility utility = new Utility();
String absolutePath = utility.getAbsolutePath("./absolute/path/to/file");
}
public String getAbsolutePath(String relativeFilePath) throws IOException {
URL url = this.getClass().getResource(relativeFilePath);
return url.getPath();
}
}
대상 파일이 와 동일한 디렉토리인 경우Utility.java
, 당신의 입력은./file.txt
.
입력만 하는 경우/
에서 getAbsolutePath()를 한다./Users/user/PROJECT_NAME/target/classes/
. 이것은 당신이 이렇게 파일을 선택할 수 있다는 것을 의미함/com/example/file.txt
.
참조URL: https://stackoverflow.com/questions/941754/how-to-get-a-path-to-a-resource-in-a-java-jar-file
'programing' 카테고리의 다른 글
농담으로 Vue 필터 테스트 (0) | 2022.05.22 |
---|---|
Vuex 스토어가 Vue-roouter에서 정의되지 않음 (0) | 2022.05.22 |
JPA : 기본 쿼리 결과 집합을 POJO 클래스 집합으로 변환하는 방법 (0) | 2022.05.22 |
일반 자바에서 HTML 기호를 이스케이프하는 방법은? (0) | 2022.05.22 |
왜 argc가 'int'('부호화되지 않은 int'가 아닌) (0) | 2022.05.22 |