ZipInputStream은보고하지 않습니다 * 실제 * (예 : 압축) 바이트 읽기
-
05-07-2019 - |
문제
이 웹 사이트를 사랑하십시오! 내 문제는 다음과 같습니다.
HTTP "Put"요청에서 네트워크를 통해 나오는 ZIP 파일을 읽고 있습니다. 요청 헤더는 컨텐츠 길이가 (예 : 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와 같습니다 (파일의 압축에 따라 다르면 무엇이든 될 수 있습니다!). 내가 알고 싶은 것은 원본에서 얼마나 많은 실제 바이트를 읽었는지 알아낼 수있는 방법이 있는지 여부입니다. inputStream
? 둘 다 ze.getSize()
그리고 ze.getCompressedSize()
ZIPPER 입장마다 -1을 반환합니다 (즉, 모릅니다). 전송 된 ZIP 파일의 바이트가 네트워크에서 읽었는지 표시하려면 진행률 표시 줄 에이 정보가 필요합니다.
제안? ZipInputStream 서브 클래스가 아마도 랩핑 된 입력 스트림에서 읽고있는 바이트 수를 찾아야합니까?
미리 감사드립니다!
해결책
물론, 그것은 합리적으로 보입니다.
기본적으로 두 가지 옵션이 있습니다. 모든 바이트를 읽고, 저장 (메모리 또는 파일에)을 저장 한 다음 계산 한 다음 압축을 억제하십시오. 또는 그들이 들어올 때 계산하십시오. 전자는 비효율적 인 것처럼 보이고 후자는 서브 클래스가 필요합니다. InputStream
읽는 바이트를 계산할 수있는 능력이 있습니다. 표준 라이브러리에서 하나를 생각할 수는 없지만 구현은 아마도 존재할 것입니다. 다시는 자신의 글을 쓰기가 매우 쉽습니다.
다른 팁
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));
둘 다 감사합니다! 나는 Clint가 제안한 것을 거의 정확히 만들었습니다!
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;
}
}
이제 나는 누가 작은 "체크 마크"를 주어야하는지 궁금합니다 ...?
다시 한 번 감사드립니다!
이것이 제가하는 일입니다 ... 아무것도 무시할 필요가 없습니다.
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();