Cách tốt nhất để tìm ra i java.io.InputStream
có chứa dữ liệu nén không?Cách tốt nhất để phát hiện xem luồng có được nén trong Java
Trả lời
magic bytes cho định dạng ZIP là 50 4B
. Bạn có thể kiểm tra luồng (sử dụng mark và reset - bạn có thể cần phải buffer) nhưng tôi không cho rằng đây là phương pháp đáng tin cậy 100%. Sẽ không có cách nào để phân biệt nó với một tệp văn bản được mã hóa US-ASCII bắt đầu bằng các chữ cái PK
.
Cách tốt nhất Cách tốt nhất là cung cấp siêu dữ liệu ở định dạng nội dung trước khi mở luồng và sau đó xử lý nó một cách thích hợp.
Không rất thanh lịch, nhưng đáng tin cậy:
Nếu Stream có thể được đọc qua ZipInputStream
, nó nên được nén.
Bạn có thể kiểm tra xem bốn byte đầu tiên của dòng là phần đầu tập tin địa phương chữ ký bắt đầu tiêu đề tập tin địa phương đó tiến hành tất cả các tập tin trong một file ZIP, as shown in the spec here là 50 4B 03 04
.
Một mã kiểm tra ít cho thấy để làm việc này:
byte[] buffer = new byte[4];
try {
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("so.zip"));
ZipEntry ze = new ZipEntry("HelloWorld.txt");
zos.putNextEntry(ze);
zos.write("Hello world".getBytes());
zos.close();
FileInputStream is = new FileInputStream("so.zip");
is.read(buffer);
is.close();
}
catch(IOException e) {
e.printStackTrace();
}
for (byte b : buffer) {
System.out.printf("%H ",b);
}
Đã cho tôi kết quả này:
50 4B 3 4
Tôi đã có ý tưởng tương tự (mặc dù Wikipedia đáng tin cậy về spec - vì xấu hổ!), Nhưng có vẻ như đây không phải là một cơ chế đáng tin cậy: _ "Người thực hiện cần lưu ý rằng các tệp ZIP có thể gặp phải hoặc không có chữ ký này và nên giải thích cho cả hai trường hợp khi đọc các tệp ZIP để đảm bảo khả năng tương thích. "_ – McDowell
Đó là sự thật cho quan điểm chung, nhưng tôi đoán là nếu bạn không có chữ ký ZipInputStream sẽ thất bại vì nó nhấn mạnh vào các đối tượng ZipEntry. –
Bạn có thể có rác ngẫu nhiên được thêm vào để nén các tệp (chẳng hạn như các tệp thi hành Microsoft Windows). Những công việc này chỉ hoạt động nếu bạn sử dụng thư mục trung tâm thay vì phát trực tiếp bằng các tiêu đề cục bộ. FWIW, Java PlugIn và WebStart sử dụng thư mục trung tâm nhưng bây giờ kiểm tra bốn byte đầu tiên (xem GIAR). –
Giới thiệu
Vì tất cả các câu trả lời là 5 tuổi, tôi cảm thấy một nhiệm vụ viết xuống, những gì đang xảy ra ngày hôm nay. Tôi nghiêm túc nghi ngờ người ta nên đọc byte ma thuật của dòng! Đó là một mã mức thấp, nó nên tránh nói chung.
câu trả lời đơn giản
miku viết:
Nếu Stream có thể được đọc qua ZipInputStream, nó nên được nén.
Có, nhưng trong trường hợp ZipInputStream
"có thể đọc" có nghĩa là lệnh gọi đầu tiên đến .getNextEntry()
trả về giá trị không null. Không có ngoại lệ bắt và cetera. Vì vậy, thay vì phân tích cú pháp byte ảo, bạn chỉ có thể làm:
boolean isZipped = new ZipInputStream(yourInputStream).getNextEntry() != null;
Và đó là nó!
suy nghĩ giải nén chung
Nhìn chung, dường như đó là thuận tiện hơn nhiều để làm việc với các tập tin trong khi [un] nén, so với suối. Có một số thư viện hữu ích, cộng với ZipFile có nhiều chức năng hơn ZipInputStream. Xử lý các tệp zip được thảo luận tại đây: What is a good Java library to zip/unzip files? Vì vậy, nếu bạn có thể làm việc với các tệp bạn làm tốt hơn!
mẫu Mã
Tôi cần thiết trong ứng dụng của tôi để làm việc với chỉ suối. Vì vậy, đó là phương pháp tôi đã viết để giải nén:
import org.apache.commons.io.IOUtils;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public boolean unzip(InputStream inputStream, File outputFolder) throws IOException {
ZipInputStream zis = new ZipInputStream(inputStream);
ZipEntry entry;
boolean isEmpty = true;
while ((entry = zis.getNextEntry()) != null) {
isEmpty = false;
File newFile = new File(outputFolder, entry.getName());
if (newFile.getParentFile().mkdirs() && !entry.isDirectory()) {
FileOutputStream fos = new FileOutputStream(newFile);
IOUtils.copy(zis, fos);
IOUtils.closeQuietly(fos);
}
}
IOUtils.closeQuietly(zis);
return !isEmpty;
}
Có những tình huống mà một 'ZipOutputStream' không được hoàn thành hoặc đóng đúng cách sẽ có nghĩa là tệp kết quả sẽ ném một' IOException' khi được phân tích cú pháp thành 'new ZipFile (f)' vì nó không hợp lệ. Ở trên sẽ không thất bại, ngay cả khi tệp zip không hợp lệ cho các mục đích khác. –
Kiểm tra số ma thuật có thể không phải là tùy chọn phù hợp.
Tệp Docx cũng có số ma thuật tương tự 50 4B 3 4
Thats vì các tệp docx là các tệp zip. – tak3shi
Đây có phải là một phần của yêu cầu/phản hồi HTTP không? –