2013-04-01 15 views
8

Bazı verileri sıkıştırmak istiyorum, bu nedenle DeflatorInputStream & DeflatorOutputStream sınıflarına rastladım. Ancak, aşağıdaki örnek, bu sınıfları kullanırken orijinal verilerimi yeniden oluşturamayacağımı gösterir.DeflatorInputStream ve DeflatorOutputStream, orijinal verileri yeniden oluşturmuyor

ZipInputStream ve ZipOutputStream'e geçtiğimde işe yaramıyor, ancak zip dosyalarına gerek duymadığımdan, genel bir sıkıştırmanın daha iyi olacağını düşündüm. Temel olarak bu örneğin neden çalışmadığını anlamak istiyorum.

//Create some "random" data 
int bytesLength = 1024; 
byte[] bytes = new byte[bytesLength]; 
for(int i = 0; i < bytesLength; i++) { 
    bytes[i] = (byte) (i % 10); 
} 

//Compress the data, and write it to somewhere (a byte array for this example) 
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); 
DeflaterOutputStream outputStream = new DeflaterOutputStream(arrayOutputStream); 
outputStream.write(bytes); 

//Read and decompress the data 
byte[] readBuffer = new byte[5000]; 
ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(arrayOutputStream.toByteArray()); 
DeflaterInputStream inputStream = new DeflaterInputStream(arrayInputStream); 
int read = inputStream.read(readBuffer); 

//Should hold the original (reconstructed) data 
byte[] actuallyRead = Arrays.copyOf(readBuffer, read); 

//Results differ - will print false 
System.out.println(Arrays.equals(bytes, actuallyRead)); 

cevap

13

Suçlama tarihi emsal. Unix'te, deflate'u tersine çevirmek için kullanılan işlev inflate olarak adlandırılır. Bu nedenle, diğer Java IO sınıflarının birçoğundan farklı olarak, giriş ve çıkış akışı çifti, eşleşen adlara sahip değildir (açıkça).

DeflaterOutputStream aslında bir deflasyonu tersine çevirmenize izin vermez, bunun yerine baytları bir lavabondan kaynağa geçirir. DeflateterInputStream ayrıca'u tanımlar, ancak veri kaynağından lavaboya veri akışı olarak eylemini gerçekleştirir. onun olası bir read çağrıda akışından tüm sıkıştırılmış veri almak değil, çünkü Ayrıca

InflaterInputStream inputStream = new InflaterInputStream(arrayInputStream); 

: sıkıştırılmamış (şişirilmiş) formatında veri okumak amacıyla

, bir InflaterInputStream kullanmak gerekir bir döngü kullanmalısın. Böyle bir şey:

int read; 
byte[] finalBuf = new byte[0], swapBuf; 
byte[] readBuffer = new byte[5012]; 

ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(
     compressed); 
InflaterInputStream inputStream = new InflaterInputStream(
     arrayInputStream); 
while ((read = inputStream.read(readBuffer)) != -1) { 
    System.out.println("Intermediate read: " + read); 
    swapBuf = finalBuf; 
    finalBuf = new byte[swapBuf.length + read]; 
    System.arraycopy(swapBuf, 0, finalBuf, 0, swapBuf.length); 
    System.arraycopy(readBuffer, 0, finalBuf, swapBuf.length, read); 
} 

Son olarak, önceki sıkıştırılmış bayt alma için deflater çıkış akışı temizlemek ya emin olun (veya alternatif akım kapatın).

1

Kodunuzu çalıştıran yalnızca 2 küçük değişiklik var. İlk

//Compress the data, and write it to somewhere (a byte array for this example) 
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); 
DeflaterOutputStream outputStream = new DeflaterOutputStream(arrayOutputStream); 
outputStream.write(bytes); 
outputStream.close(); 

, sen yakın() çıkış akımı var. Deflatörün işini tamamlamak için bazı son adımlar atması gerekiyor. Bir Deflatörlü InputStream kullanırsanız

InflaterInputStream inputStream = new InflaterInputStream(arrayInputStream); 

, tekrar sıkıştırılmış veriyi sıkıştırmak. Bir Inflator InputStream ile değiştirin ve kodunuz iyi çalışacaktır.

İlgili konular