2009-05-05 7 views
4

このウェブサイトを愛してください!私の問題は以下の通りです:ZipInputStreamは* actual *(すなわち圧縮された)バイトを報告しません

HTTP "PUT"リクエストからネットワークを経由してくるzipファイルを読んでいます。要求ヘッダーは、Content-Lengthが1Mbであることを伝えます。次のコードはZipInputStreamを作成し、現在のディレクトリ内のファイルへのzipの内容を保存します。

ZipInputStream zis = new ZipInputStream(inputStream); 
ZipEntry ze; 
long totalBytesRead = 0; 
while ((ze = zis.getNextEntry()) != null) { 
    BufferedOutputStream outStream = new BufferedOutputStream(new FileOutputStream(ze.getName())); 
    byte[] buffer = new byte[4096]; 
    int i; 
    while ((i = zis.read(buffer)) != -1) { 
     totalBytesRead+=i; 
     outStream.write(buffer,0,i); 
    } 
    outStream.close(); 
} 
inputStream.close(); 

全てが言ったと行って、totalBytesRead約1.5Mbのに等しいです(ファイルの圧縮に応じて、可能性がされている場合何でも!)。私が知りたいのは、実際のバイト数が元のバイト数からどれくらい読み取られたかを調べる方法がある場合です。inputStreamze.getSize()ze.getCompressedSize()は、すべての圧縮されたエントリについて-1を返します(つまり、それはわかりません)。私は、送信されたzipファイルの何バイトがネットワークから読み込まれたかを示すプログレスバーにこの情報が必要です。

提案?私はおそらく、ZipInputStreamをサブクラス化して、それが何回読み込み中のInputStreamから読み込んでいるかを調べるべきでしょうか?

ありがとうございます!

答えて

1

確かに、それは妥当と思われます。

基本的に2つのオプションがあります:すべてのバイトを読み込み、メモリまたはファイルに保存し、カウントしてから圧縮解除します。前者は効率が悪いと思われ、後者はサブクラスがInputStreamで、それは読み込んだバイト数を数えます。私は標準ライブラリのものを考えることはできませんが、おそらく実装がそこに存在するかもしれません - そして、あなた自身で書くことはかなり簡単でしょう。

2
import java.io.FilterInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

/** 
* 
*/ 

/** 
* @author clint 
* 
*/ 
public class ByteCountingInputStream extends FilterInputStream { 

    public int totalRead = 0; 

    /** 
    * @param in 
    */ 
    protected ByteCountingInputStream(InputStream in) { 
    super(in); 
    // TODO Auto-generated constructor stub 
    } 

    /* (non-Javadoc) 
    * @see java.io.FilterInputStream#read() 
    */ 
    @Override 
    public int read() throws IOException { 
    int ret = super.read(); 
    totalRead++; 
    return ret; 
    } 

    /* (non-Javadoc) 
    * @see java.io.FilterInputStream#read(byte[], int, int) 
    */ 
    @Override 
    public int read(byte[] b, int off, int len) throws IOException { 
    int ret = super.read(b, off, len); 
    totalRead += ret; 
    return ret; 
    } 

    /* (non-Javadoc) 
    * @see java.io.FilterInputStream#read(byte[]) 
    */ 
    @Override 
    public int read(byte[] b) throws IOException { 
    int ret = super.read(b); 
    totalRead += ret; 
    return ret; 
    } 

    /* (non-Javadoc) 
    * @see java.io.FilterInputStream#skip(long) 
    */ 
    @Override 
    public long skip(long n) throws IOException { 
    //What to do? 
    return super.skip(n); 
    } 

    /** 
    * @return the totalRead 
    */ 
    protected int getTotalRead() { 
    return this.totalRead; 
    } 

} 

これは

等との
ZipInputStream zis = new ZipInputStream(new ByteCountingInputStream(inputStream)); 
+0

なぜコンストラクタは保護されていますか? –

2

に行くあなたの両方をありがとう!私はちょうどクリントが提案したものをかなり完成させました!

import java.io.FilterInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

public class CountingInputStream extends FilterInputStream { 

    private long totalBytes = 0; 

    protected CountingInputStream(InputStream in) { 
     super(in); 
    } 

    public int getTotalBytesRead() { 
     return totalBytes; 
    } 

    @Override 
    public int read() throws IOException { 
     int byteValue = super.read(); 
     if (byteValue != -1) totalBytes++; 
     return byteValue; 
    } 

    @Override 
    public int read(byte[] b) throws IOException { 
     int bytesRead = super.read(b); 
     if (bytesRead != -1) totalBytes+=bytesRead; 
     return bytesRead; 
    } 

    @Override 
    public int read(byte[] b, int off, int len) throws IOException { 
     int bytesRead = super.read(b,off,len); 
     if (bytesRead != -1) totalBytes+=bytesRead; 
     return bytesRead; 
    } 
} 

私は小さな "チェックマーク"を誰に与えるべきなのでしょうか?

もう一度おねがいします!

+0

はい、-1チェックは良い適応です。 – Clint

-1

これは私が行うことです...何も上書きする必要はありません。

ZipInputStream zis = new ZipInputStream(inputStream); 
ZipEntry ze; 
int totalBytes = inputStream.available(); 
int totalBytesRead = 0; 
while ((ze = zis.getNextEntry()) != null) { 
    totalBytesRead = totalBytes - inputStream.available(); 
    BufferedOutputStream outStream = new BufferedOutputStream(new FileOutputStream(ze.getName())); 
    byte[] buffer = new byte[4096]; 
    int i; 
    while ((i = zis.read(buffer)) != -1) { 
     outStream.write(buffer,0,i); 
    } 
    outStream.close(); 
} 
inputStream.close(); 
+0

http://docs.oracle.com/javase/7/docs/api/java/util/zip/ZipInputStream.html#available()現在の入力データに対してEOFに達した後に0を返します。それ以外の場合は常に1を返します。 プログラムはブロックせずに読み込める実際のバイト数を返すためにこのメソッドを使うべきではありません。 –

関連する問題