Android: 解压缩串联的 gzip 压缩文件
Android: uncompress concatenated gzip-compressed files
gzip
是 documented 以支持压缩文件的串联:
$ echo hello >hhh
$ echo world >www
$ cat hhh www
hello
world
$ echo hello | gzip >hhhh
$ echo world | gzip >wwww
$ cat hhhh wwww | gunzip
hello
world
我可以用 GZIPOutputStream
创建一个串联文件,但不幸的是 GZIPInputStream
只读取数据的第一部分(gunzip
运行 从命令行读取所有数据。 )
我在 Android 4.1.2 和 4.4.2 上都看到了这个。
如何从 Java 读取整个文件?
更新:
演示错误的示例(主机版本):
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
class GZTest {
static void append(File f, String s) {
try {
FileOutputStream fos = new FileOutputStream(f, true);
//FileOutputStream gzos = fos;
GZIPOutputStream gzos = new GZIPOutputStream(fos);
gzos.write(s.getBytes("UTF-8"));
gzos.close(); // TODO: do it finally{}
fos.close(); // TODO: do it finally{}
} catch (IOException e) {
e.printStackTrace();
}
}
static String readAll(File f) {
try {
FileInputStream fis = new FileInputStream(f);
//FileInputStream gzis = fis;
GZIPInputStream gzis = new GZIPInputStream(fis);
byte[] buf = new byte[4096];
int len = gzis.read(buf);
gzis.close(); // TODO: do it finally{}
fis.close(); // TODO: do it finally{}
return new String(Arrays.copyOf(buf, len), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public class A {
public static void main(String[] args) {
System.out.println("~~~");
File f = new File("x.y");
f.delete();
GZTest.append(f, "Hello, ");
GZTest.append(f, "world!\n");
System.out.println(GZTest.readAll(f));
}
}
运行它:
$ javac A.java
$ java A
~~~
Hello,
$ gunzip <x.y
Hello, world!
更新2
看起来这是错误 JDK-2192186,据报道已于 2010-08-03 修复。尽管如此,现在还是有 bug。
关于宿主java,正确的读法是:
static String readAll(File f) {
try {
FileInputStream fis = new FileInputStream(f);
//FileInputStream gzis = fis;
GZIPInputStream gzis = new GZIPInputStream(fis);
final int SIZE=4096;
byte[] buf = new byte[SIZE];
int len=0, read=0;
do {
read = gzis.read(buf, len, SIZE-len);
if (read < 0) {
break;
}
len += read;
} while (len<SIZE);
gzis.close(); // TODO: do it finally{}
return new String(Arrays.copyOf(buf, len), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
(这个readAll()是用来代替问题中的readAll())
此代码不适用于 Android!!!
在 Android 上,这仍然给出
D/~~~ (30098): Hello,
而命令行 gunzip 说
# cat /data/data/com.example.gzctest2/files/x.y | gunzip
Hello, world!
刚刚尝试了 truncated output from GZIPInputStream on Android 的解决方案:有效。
要使用修复 https://github.com/ymnk/jzlib/tree/concatenated_gzip_streams 克隆分支,请使用:
git clone https://github.com/ymnk/jzlib.git
git checkout concatenated_gzip_streams
然后复制目录src/main/java(你不能只复制一个文件)到你的项目并替换导入:
//import java.util.zip.GZIPInputStream;
import com.jcraft.jzlib.GZIPInputStream;
适用于 Android!
如果您希望删除不需要的文件,您将需要:
Adler32.java Deflate.java GZIPInputStream.java Inflate.java InfTree.java Tree.java
Checksum.java GZIPException.java InfBlocks.java InflaterInputStream.java JZlib.java ZStream.java
CRC32.java GZIPHeader.java InfCodes.java Inflater.java 静态Tree.java
而且不会需要:
Deflater.java DeflaterOutputStream.java GZIPOutputStream.java ZInputStream.java ZOutputStream.java ZStreamException.java
看起来删除 6 个未使用的文件 (24K) 而保留 17 个文件 (198K) 是不值得的结果。
gzip
是 documented 以支持压缩文件的串联:
$ echo hello >hhh
$ echo world >www
$ cat hhh www
hello
world
$ echo hello | gzip >hhhh
$ echo world | gzip >wwww
$ cat hhhh wwww | gunzip
hello
world
我可以用 GZIPOutputStream
创建一个串联文件,但不幸的是 GZIPInputStream
只读取数据的第一部分(gunzip
运行 从命令行读取所有数据。 )
我在 Android 4.1.2 和 4.4.2 上都看到了这个。
如何从 Java 读取整个文件?
更新:
演示错误的示例(主机版本):
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
class GZTest {
static void append(File f, String s) {
try {
FileOutputStream fos = new FileOutputStream(f, true);
//FileOutputStream gzos = fos;
GZIPOutputStream gzos = new GZIPOutputStream(fos);
gzos.write(s.getBytes("UTF-8"));
gzos.close(); // TODO: do it finally{}
fos.close(); // TODO: do it finally{}
} catch (IOException e) {
e.printStackTrace();
}
}
static String readAll(File f) {
try {
FileInputStream fis = new FileInputStream(f);
//FileInputStream gzis = fis;
GZIPInputStream gzis = new GZIPInputStream(fis);
byte[] buf = new byte[4096];
int len = gzis.read(buf);
gzis.close(); // TODO: do it finally{}
fis.close(); // TODO: do it finally{}
return new String(Arrays.copyOf(buf, len), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public class A {
public static void main(String[] args) {
System.out.println("~~~");
File f = new File("x.y");
f.delete();
GZTest.append(f, "Hello, ");
GZTest.append(f, "world!\n");
System.out.println(GZTest.readAll(f));
}
}
运行它:
$ javac A.java
$ java A
~~~
Hello,
$ gunzip <x.y
Hello, world!
更新2
看起来这是错误 JDK-2192186,据报道已于 2010-08-03 修复。尽管如此,现在还是有 bug。
关于宿主java,正确的读法是:
static String readAll(File f) {
try {
FileInputStream fis = new FileInputStream(f);
//FileInputStream gzis = fis;
GZIPInputStream gzis = new GZIPInputStream(fis);
final int SIZE=4096;
byte[] buf = new byte[SIZE];
int len=0, read=0;
do {
read = gzis.read(buf, len, SIZE-len);
if (read < 0) {
break;
}
len += read;
} while (len<SIZE);
gzis.close(); // TODO: do it finally{}
return new String(Arrays.copyOf(buf, len), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
(这个readAll()是用来代替问题中的readAll())
此代码不适用于 Android!!!
在 Android 上,这仍然给出
D/~~~ (30098): Hello,
而命令行 gunzip 说
# cat /data/data/com.example.gzctest2/files/x.y | gunzip
Hello, world!
刚刚尝试了 truncated output from GZIPInputStream on Android 的解决方案:有效。 要使用修复 https://github.com/ymnk/jzlib/tree/concatenated_gzip_streams 克隆分支,请使用:
git clone https://github.com/ymnk/jzlib.git
git checkout concatenated_gzip_streams
然后复制目录src/main/java(你不能只复制一个文件)到你的项目并替换导入:
//import java.util.zip.GZIPInputStream;
import com.jcraft.jzlib.GZIPInputStream;
适用于 Android!
如果您希望删除不需要的文件,您将需要:
Adler32.java Deflate.java GZIPInputStream.java Inflate.java InfTree.java Tree.java
Checksum.java GZIPException.java InfBlocks.java InflaterInputStream.java JZlib.java ZStream.java
CRC32.java GZIPHeader.java InfCodes.java Inflater.java 静态Tree.java
而且不会需要:
Deflater.java DeflaterOutputStream.java GZIPOutputStream.java ZInputStream.java ZOutputStream.java ZStreamException.java
看起来删除 6 个未使用的文件 (24K) 而保留 17 个文件 (198K) 是不值得的结果。