2012-12-05 29 views
24

Vì vậy, tôi đã tìm kiếm cao và thấp cho câu trả lời cho điều này và rõ ràng là không tìm thấy câu trả lời thỏa đáng.Cập nhật một tệp bên trong một JAR trong một thư mục cụ thể với lệnh jar

Vấn đề là tôi muốn cập nhật JAR (hoặc bất kỳ tệp nào cho vấn đề đó) bên trong JAR, nhưng tệp được cho là nằm bên trong cấu trúc thư mục mà tôi muốn tránh sao chép bên ngoài JAR để tôi có thể cập nhật nó.

Ví dụ:

Foo.jar (root directory) 
/
|->/folder1 
| 
|->/folder2 
| 
|->/foo 
    | 
    |-->/bar 
     | 
     |---->/baz 
       | 
       |------>file_to_update.jar 

Vì vậy, nếu tôi muốn cập nhật này bằng cách sử dụng jar lệnh, tôi sẽ phải đầu tiên tạo ra các cấu trúc thư mục giống nhau ngoài JAR và sau đó làm

jar -uf Foo.jar -C foo/bar/baz/file_to_update.jar 

Tuy nhiên tôi muốn tránh tạo cấu trúc thư mục này vì một số tệp nhất định có thể khá sâu và cũng vì tôi có thể cần phải cập nhật các tệp đã chọn trên JAR vùng chứa, vì vậy tôi không muốn tạo nhiều thư mục với một đặc tả cấu trúc ific chỉ để lệnh jar có thể cập nhật chúng.

Để đặt theo cách khác, tôi muốn nói lệnh jar để cập nhật tệp đích cụ thể bên trong thư mục đích cụ thể, sử dụng tệp nguồn cụ thể bên trong thư mục nguồn cụ thể.

I.e. một cái gì đó như

jar -uf Foo.jar -sourceFile /x/y/z/filetoupdate -destFile /a/b/c/filetoupdate 

(Tôi biết cú pháp này không hoạt động, nó chỉ là minh họa những gì tôi cần).

Việc này có thể thực hiện được không? Nó sẽ tấn công tôi rất kỳ quặc đến nỗi tôi hoàn toàn cần bắt chước toàn bộ cấu trúc thư mục khi lệnh jar có thể tìm thấy kết quả phù hợp cho nó hoặc thứ gì đó, vì tôi có thể cần phải cập nhật tệp bên trong cấu trúc thư mục là 100 thư mục sâu. Điều đó sẽ quá phức tạp để sinh sản chỉ để cập nhật tệp.

Ngoài ra, tôi biết một tiện ích ZIP thông thường có thể được sử dụng, nhưng tiện ích tôi có sẵn trong Linux không cập nhật tệp ngay cả khi nó đã làm (khi mở lại bình, nó có phiên bản cũ nguyên vẹn) và ngay bây giờ tôi không thể tìm kiếm một thứ khác (chính sách của công ty, không có thời gian, vấn đề kiểm tra, bạn đặt tên cho nó).

Cuối cùng, nếu tôi có thể thực hiện điều này từ dòng lệnh, điều đó có nghĩa là tôi có thể tạo tệp lô để cập nhật nhiều tệp cụ thể mà không phải tạo cấu trúc thư mục.

Tôi quên nói rằng tôi cũng muốn tránh phải mở, cập nhật, mở lại toàn bộ thứ, vì JAR này có thể lên tới 2GB vì vậy phải mất một thời gian để thực hiện điều này, về cơ bản, thêm một chút tệp tài nguyên cho JAR khổng lồ của tôi.

Bất kỳ trợ giúp nào về điều này được đánh giá cao!

+0

Bạn đề cập rằng bạn đang trên Linux, bạn đã xem xét gói zip chưa? '' 'man zip''' cho hướng dẫn. Nó dường như chỉ là công cụ bạn đang tìm kiếm, và ghép nối nó với một kịch bản để tự động hóa. – TomJ

Trả lời

5

4129445 : An API to incrementally update ZIP files trong cơ sở dữ liệu lỗi Sun/Oracle yêu cầu tính năng này được triển khai trong api java.

Từ đánh giá:

"Nó rất dễ dàng để cảm thông với những người muốn lỗi này cố định Có lẽ dễ dàng hơn để cảm thông với những người có, vô tình, các tập tin JAR ghi đè đã có trong sử dụng bởi một. chạy JVM. "

"Nó sẽ được tốt đẹp nếu các API zip jar & đã cho phép cho các tập tin zip có thể thay đổi từ ngày đầu tiên. Nhưng vào thời điểm này thêm mutability để làm chao & file zip từ Java (hay đúng hơn, tăng dễ biến đổi chúng) dường như có khả năng đưa ra nhiều vấn đề khó gỡ lỗi hơn. "

+0

Eesh ... có vẻ như quá dài:/ – Acapulco

+5

Nhìn bên dưới để có câu trả lời đúng. Đây là một sự lãng phí thời gian. – Sorter

1

This previous discussion hiển thị một số mã nguồn Java để cập nhật tệp zip (hoặc jar).

Nó không hoàn toàn rõ ràng với tôi cho dù điều này thực sự sẽ nhanh hơn sử dụng jar -u, nhưng ít nhất bạn sẽ có thể điều chỉnh mã đó để bạn không phải tạo lại cấu trúc tệp trên đĩa.

Chỉnh sửa: Here is the documentation trên tiện ích 'jar' - bạn có thể thấy chính mình rằng hành vi cụ thể mà bạn đang tìm kiếm, trong khi nó sẽ hữu ích, không có ở đó.

Tôi nghĩ lý do là giao diện dòng lệnh cơ bản là bản sao của lệnh 'tar' Unix/Linux. Tất nhiên, nó tạo ra định dạng zip, chứ không phải là tar.

Chỉnh sửa # 2 - Đã xảy ra với tôi rằng để thêm tệp vào mã zip, bạn chỉ cần xóa khỏi thư mục trung tâm từ cuối tệp, thêm mục nhập mới và sau đó viết lại thư mục trung tâm. Bản cập nhật sẽ giống nhau, ngoại trừ thay vì thêm mục nhập vào thư mục, bạn sẽ cập nhật mục nhập thư mục hiện có để trỏ đến mục nhập zip mới.

Khi khám phá khả năng này, tôi thấy Java 7 bao gồm zip file system provider trông giống như vậy và có thể tạo cơ sở cho giải pháp cho những gì bạn muốn làm.

+0

Cảm ơn bạn đã tham khảo. Tôi đã thực sự đã đọc nó và đã suy nghĩ về việc thực hiện nó. Tuy nhiên, tôi vẫn đang tìm kiếm một câu trả lời dứt khoát bằng cách sử dụng lệnh jar, không phải là một giải pháp thay thế. Nó có vẻ thực sự vô lý rằng các nhà phát triển của công cụ này đã không cho phép hoạt động như vậy. Tôi chỉ muốn chắc chắn (tài liệu, nguồn có thẩm quyền, vv) mà nó thực sự KHÔNG THỂ được thực hiện, và có lẽ tại sao điều này như vậy (lý do lịch sử, vv). Tôi không thể tin rằng một hoạt động đơn giản và hữu ích như vậy chưa được thực hiện trong lệnh. Phải có rất nhiều lập trình viên muốn điều này. – Acapulco

+0

Tôi đoán tôi cần một đôi mắt khác để nhìn vào nó, vì tôi không thể tin được. Tôi đọc tài liệu trước khi đăng tất nhiên, nhưng một lần nữa, tôi nghĩ rằng tôi đã thiếu một cái gì đó. Vì vậy, cảm ơn vì đã xem xét khác. Nếu đến cuối thời gian bounty không có gì tốt hơn, tôi sẽ chấp nhận câu trả lời của bạn. Tuy nhiên, muốn tận dụng toàn bộ lợi thế của tiền thưởng ngay cả khi có chút khó chịu, muốn hỏi bạn: Tôi đang làm việc để thay đổi mã nguồn để hỗ trợ kịch bản này. Làm thế nào cứng bạn sẽ xem xét nó sẽ là để có được sự thay đổi được chấp nhận? Tôi có thể nghĩ nhiều hơn một cách này có thể hữu ích Cảm ơn bạn lần nữa! – Acapulco

+1

Thật đáng để thử, nhưng tôi nghĩ bạn sẽ gặp khó khăn trong việc chấp nhận nó. Nếu bạn không chấp nhận nó, hãy xem liệu mã nguồn có được mã nguồn mở hay không. Nếu có, hãy nĩa nó, thực hiện thay đổi và xuất bản các thay đổi của bạn. – GreyBeardedGeek

39

Như câu trả lời được chấp nhận đã chỉ ra, bạn không thể sử dụng cả các zip lẫn jar lệnh để chèn một tập tin cụ thể trên hệ thống tập tin vào một thư mục cụ thể bên trong các tập tin nén.

Nhưng có này workaround, mà trong một nutshell trích ra một tập tin cụ thể bên trong file nén đầu tiên, bạn có thể cập nhật nó và sau đó đặt nó trở lại vào tập tin nén:

1. Trích xuất một đơn file:
Xem xét một jar với các nội dung sau

$ jar tvf foo.jar 
0 Thu Jan 10 00:05:06 IST 2013 META-INF/ 
68 Thu Jan 10 00:05:06 IST 2013 META-INF/MANIFEST.MF 
0 Thu Jan 10 00:04:30 IST 2013 x/ 
0 Thu Jan 10 00:07:36 IST 2013 x/b/ 
9 Thu Jan 10 00:07:36 IST 2013 x/b/hello.txt 
0 Thu Jan 10 00:04:30 IST 2013 x/a/ 

để trích xuất chỉ hello.txt, bạn phải từ bỏ đường dẫn đầy đủ của tập tin-to-chiết xuất. Jar cũng tạo các thư mục thích hợp.

Ví dụ:

$ jar xvf foo.jar x/b/hello.txt 
inflated: x/b/hello.txt 

$ tree x/ 
x 
└── b 
    └── hello.txt 
1 directory, 1 file 

2. Cập nhật một Single File

  1. Sửa đổi các tập tin trích
  2. cập nhật jar bằng cách sử dụng 'u' cờ. Cung cấp thư mục gốc của thư mục và jar sẽ được cập nhật tất cả các phần tử đường dẫn bên dưới nó.

Ví dụ:

$ jar vfu foo.jar x/ 
adding: x/(in = 0) (out= 0)(stored 0%) 
adding: x/b/(in = 0) (out= 0)(stored 0%) 
adding: x/b/hello.txt(in = 23) (out= 11)(deflated 52%) 

3. Phiên bản nào của jar tôi đã cố gắng này ra với ai?

tôi đã sử dụng jar kèm với JDK 7 trên Fedora 17.


Tôi đã xác minh tất cả các bước được đề cập ở đây. Hi vọng điêu nay co ich.

+0

Vâng, đây chắc chắn là một câu trả lời hay, mặc dù tôi không tìm cách giải quyết như tôi đã nói ở trên. Nó có thể làm việc chắc chắn, ngay cả trong một kịch bản hàng loạt, tuy nhiên lý do tôi bắt đầu tiền thưởng là để có được một câu trả lời dứt khoát về việc liệu nó có thể hay không. Bây giờ tôi biết nó không phải, và sau đó cách giải quyết là sự lựa chọn duy nhất. Trong mọi trường hợp, tôi đánh giá cao giải pháp, vì đó là một trong những điều tốt nhất mà tôi có thể nói. – Acapulco

+0

bạn thật tuyệt vời, cảm ơn! – lorraine

+0

Điều này hữu ích. Lúc đầu, tôi nghĩ rằng nó không hoạt động, bởi vì các tập tin tôi đã cố gắng để cập nhật sẽ bị xóa thay vì (với đầu ra nói rằng tập tin đã bị bỏ qua). Nhưng điều này là do tệp tôi đang cập nhật là META-INF/MANIFEST.MF. Như đã giải thích trên trang người dùng, bạn phải sử dụng tùy chọn M để tránh xóa tệp kê khai. Hoạt động như mô tả trong câu trả lời này khi tôi làm điều đó. Ngoài ra, tôi đã sử dụng tùy chọn C để tạm thời thay đổi thư mục với thư mục đã cập nhật. Tôi đã thử nghiệm với OpenJDK Java 7 và Java 8. – MidnightJava

1

Tôi nghĩ điều này là do các lớp trong gói java.util.zip hoạt động như thế nào. Họ ngồi trên đầu luồng.

Lớp ZipFile được xây dựng trên đỉnh của ZipFileInputStream. Viết zipfiles được thực hiện bằng cách cho ZipEntries từng cái một vào một ZipOutputStream.

Tôi cho rằng tệp thực thi jar được xây dựng trên các lớp này.

0

Tôi cũng đang cố cập nhật một cái bình mà không cần tái tạo cấu trúc tệp của jar bên ngoài bình và vì lý do nào đó, jar uf jarFileName -C ... command không bao giờ cho phép tôi sao chép tệp vào thư mục con trong bình. Sau đó tôi đã thử cắt và dán tệp vào jar bằng trình quản lý lưu trữ được tích hợp sẵn của ubuntu 14.04 (tức là nhấp chuột phải vào tệp jar và chọn "mở bằng trình quản lý lưu trữ" rồi dán tệp đó vào bất kỳ cấu trúc tệp nào của jar). . Nó không phải là một giải pháp cli nhưng nó hoạt động. Hy vọng điều này sẽ giúp người khác tiết kiệm thời gian.

-2

Nó hoạt động, nhưng nó không phải là giải pháp mở rộng mà bạn đang xem.

Thay vì tạo cấu trúc thư mục, tôi đang hỏi đề cập đến toàn bộ con đường, vì vậy mkdir sẽ tạo thư mục và thư mục con too.hope này giúp ....

set /p Folder=where you want to move inside jar 
set /p File=Mention path of file to be moved 
set /p Jarfile=Where is your jar file 
mkdir %Folder% 
copy %File% %Folder% 
jar -uvf %Jarfile% %File% 
rd /s /q %Folder% 
rmdir %Folder% 
Các vấn đề liên quan