2010-09-02 88 views
12

Câu hỏi nói lên tất cả.Tải một tệp liên quan đến tệp jar thực thi

Đặc biệt trong trường hợp của tôi là thư mục làm việc hiện tại không phải là vị trí của tệp jar nhưng c:\Windows\system32 (Tệp jar của tôi được bắt đầu bằng các cửa sổ bằng menu chuột phải, tôi muốn chuyển đường dẫn của thư mục dưới dạng tham số vào bình).

Bây giờ tôi muốn tải tệp cấu hình có tên là config.xml trong cùng thư mục với bình. Mục đích của tập tin là, tất nhiên, để cung cấp các thiết lập cho bình. Điều quan trọng đối với tôi là tệp xml là bên ngoài của tệp jar để chỉnh sửa dễ dàng.

Tôi đang gặp khó khăn khi tải tệp đó. Windows thực thi dòng

cmd /k java -jar D:\pathToJarfile\unpacker-0.0.1-SNAPSHOT-jar-with-dependencies.jar 

Gọi toàn bộ điều với cmd /k để mở cửa sổ lệnh nhắc mở để tôi có thể xem đầu ra của bình.

tôi không thể sử dụng new File(".") hoặc System.getProperty("user.dir") cho đường dẫn tương đối như các chức năng này trở C:\Windows\system32\.C:\Windows\system32, tương ứng (đó là thư mục làm việc cho tất cả mọi thứ mà cửa sổ thực thi AFAIK).

Tôi cũng không thành công với Launcher.class.getResourceAsStream("/../config.xml"). Kể từ khi con đường đó bắt đầu với /, tìm kiếm bắt đầu tại nút gốc của bình. Đi tới ../config.xml trỏ chính xác đến tệp đó, nhưng cuộc gọi trả về null.

Ai đó có thể chỉ cho tôi đúng hướng không? Tôi thực sự bị mắc kẹt ở đây. tải thứ Tập tin này thực sự làm tôi phát cáu mọi ...

Yêu cầu của bản thân mình:

  • Tôi không muốn hardcode đường dẫn trong mã nguồn java
  • Tôi không muốn vượt qua đường dẫn tập tin như là một tham số cho java -jar cuộc gọi (không phải như một param đến main(String[] args) cũng không sử dụng -Dpath=d:\... để thiết lập một hệ thống tài sản)

Ngoài vấn đề ban đầu, tôi đã có một thời gian khó khăn để có maven2 nơi Class-Path: . vào MANIFEST.MF (Giải pháp mà BalusC đăng) khi sử dụng jar-with-dependencies. Vấn đề là dòng xuất hiện trong tệp MANIFEST của bình thường, nhưng không phải tệp MANIFEST của jar-with-dependencies.jar (2 tệp jar được tạo). Đối với bất cứ ai quan tâm làm thế nào tôi đã làm nó:

<plugin> 
    <artifactId>maven-assembly-plugin</artifactId> 
    <version>2.2-beta-5</version> 
    <configuration> 
     <archive> 
     <manifest> 
      <mainClass>${mainClass}</mainClass> 
      <addClasspath>true</addClasspath> 
      <!--at first, i tried to place the Class-Path entry 
       right here using <manifestEntries>. see below --> 
     </manifest> 
     </archive> 
     <descriptorRefs> 
     <descriptorRef>jar-with-dependencies</descriptorRef> 
     </descriptorRefs> 
    </configuration> 
    <executions> 
     <execution> 
     <goals> 
      <goal>attached</goal> 
     </goals> 
     <phase>package</phase> 
     <configuration> 
      <descriptorRefs> 
      <descriptorRef>jar-with-dependencies</descriptorRef> 
      </descriptorRefs> 
      <archive> 
      <manifest> 
       <mainClass>${mainClass}</mainClass> 
      </manifest> 
      <!--this is the correct placement --> 
      <manifestEntries> 
       <Class-Path>.</Class-Path> 
      </manifestEntries> 
      </archive> 
     </configuration> 
     </execution> 
    </executions> 
    </plugin> 

Trả lời

6

Để có được Launcher.class.getResourceAsStream("/../config.xml") để làm việc, bạn cần phải thêm đường đi của nó đến Class-Path xâm nhập của tập tin MANIFEST.MF của JAR. Đây là thực hành bình thường.

+1

nghe có vẻ đẹp hơn :-) –

+0

Tôi có cần đặt đường dẫn tuyệt đối vào 'MANIFEST.MF' hoặc không' ..' đủ? Sau này sẽ là mong muốn. Xin lỗi vì yêu cầu thay vì cố gắng, tôi không có IDE của tôi tại máy này. – f1sh

+1

Không, đường dẫn liên quan đến tệp JAR. Nếu bạn muốn có 'config.xml' trong cùng thư mục với tệp JAR, thì' Lớp-Đường dẫn: .' đủ (đừng quên thêm dòng trống vào cuối 'MANIFEST.MF'!) . Sau đó, bạn có thể lấy 'config.xml' bằng' getResourceAsStream ("config.xml") '. Hãy giữ nó đơn giản :) – BalusC

11

Dưới đây là một giải pháp có thể sử dụng Class.getProtectionDomain():

final Class<?> referenceClass = YourMainClass.class; 
final URL url = 
    referenceClass.getProtectionDomain().getCodeSource().getLocation(); 

try{ 
    final File jarPath = new File(url.toURI()).getParentFile(); 
    System.out.println(jarPath); // this is the path you want 
} catch(final URISyntaxException e){ 
    // etc. 
} 

YourMainClass có thể được thay thế bằng bất kỳ lớp trong jar của bạn.


Từ Class.getProtectionDomain() tài liệu:

Returns the ProtectionDomain of this class. 
If there is a security manager installed, this method first calls 
the security manager's checkPermission method with a 
RuntimePermission("getProtectionDomain") permission to ensure it's 
ok to get the ProtectionDomain. 

Returns: 
    the ProtectionDomain of this class 
Throws: 
    SecurityException - if a security manager exists and its 
    checkPermission method doesn't allow getting the ProtectionDomain. 
+1

Điều này thực sự thú vị khi biết trường hợp tôi cần đường dẫn trong mã. Hiện tại tôi không, vì vậy tôi sẽ cố gắng sử dụng câu trả lời của BalusC. – f1sh

Các vấn đề liên quan