Domanda

Adoro questo sito! Il mio problema è il seguente:

Sto leggendo un file zip che proviene da una rete da un HTTP " PUT " richiesta. L'intestazione della richiesta mi dice che la lunghezza del contenuto è (diciamo) 1Mb. Il codice seguente crea ZipInputStream e salva i contenuti zip nei file nella directory corrente:

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();

Quando tutto è detto e fatto, totalBytesRead è pari a circa 1,5 Mb (a seconda della compressione dei file, potrebbe essere qualsiasi cosa!). Quello che vorrei sapere è se c'è un modo per scoprire quanti byte effettivi sono stati letti dall'originale inputStream ? Sia ze.getSize () che ze.getCompressedSize () restituiscono -1 per ogni voce zippata (cioè non lo sa). Ho bisogno di queste informazioni per una barra di avanzamento per mostrare quanti byte del file zip trasmesso sono stati letti dalla rete.

Suggerimenti? Dovrei forse sottoclassare ZipInputStream e provare a scoprire quanti byte sta leggendo da InputStream racchiuso?

Grazie in anticipo!

È stato utile?

Soluzione

Certo, sembra ragionevole.

Esistono sostanzialmente due opzioni: leggere tutti i byte, memorizzarli (in memoria o in un file), contarli, quindi decomprimerli; o contarli quando entrano. Il primo sembra inefficiente e il secondo richiederà una sottoclasse di InputStream che ha la capacità di contare i byte che legge. Non riesco a pensarne uno nella libreria standard, ma probabilmente esistono delle implementazioni là fuori - quindi sarebbe di nuovo abbastanza facile scrivere il tuo.

Altri suggerimenti

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;
  }

}

Questo va in mezzo come

ZipInputStream zis = new ZipInputStream(new ByteCountingInputStream(inputStream));

Grazie ad entrambi! Ho appena finito di fare esattamente ciò che Clint ha suggerito!

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;
    }
}

Ora mi chiedo chi dovrei dare il piccolo segno di spunta " a ...?

Grazie ancora!

Questo è quello che faccio ... non è necessario ignorare nulla.

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();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top