Java ZipoutStream在Android上生成损坏的zip文件
我已经使用zip存档实现了应用程序中用户数据的备份,我正在将数据库和共享首选项文件复制到zip存档,并计算输入文件的MD5校验和,以防止用户修改备份数据 要从archive I将备份文件解压缩到临时目录,请检查校验和,然后将preferences\database文件复制到相应的文件夹中 我的一些用户抱怨该应用程序生成的备份文件已损坏(zip文件确实已损坏) 下面是将所有文件压缩为zip文件的代码:Java ZipoutStream在Android上生成损坏的zip文件,java,android,zipfile,Java,Android,Zipfile,我已经使用zip存档实现了应用程序中用户数据的备份,我正在将数据库和共享首选项文件复制到zip存档,并计算输入文件的MD5校验和,以防止用户修改备份数据 要从archive I将备份文件解压缩到临时目录,请检查校验和,然后将preferences\database文件复制到相应的文件夹中 我的一些用户抱怨该应用程序生成的备份文件已损坏(zip文件确实已损坏) 下面是将所有文件压缩为zip文件的代码: public void backup(String filename) { File f
public void backup(String filename) {
File file = new File(getBackupDirectory(), filename);
FileOutputStream fileOutputStream = null;
ZipOutputStream stream = null;
try {
String settingsMD5 = null;
String databaseMD5 = null;
if (file.exists())
file.delete();
fileOutputStream = new FileOutputStream(file);
stream = new ZipOutputStream(new BufferedOutputStream(fileOutputStream));
File database = getDatabasePath(databaseFileName);
File dataDirectory = getFilesDir();
if (dataDirectory != null) {
File settings = new File(dataDirectory.getParentFile(), "/shared_prefs/" + PREFERENCES_FILENAME);
settingsMD5 = zipFile("preferences", stream, settings);
}
databaseMD5 = zipFile("database.db", stream, database);
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put(META_DATE, new SimpleDateFormat(DATE_FORMAT, Locale.US).format(new Date()));
jsonObject.put(META_DATABASE, databaseMD5);
jsonObject.put(META_SHARED_PREFS, settingsMD5);
} catch (Exception e) {
e.printStackTrace();
}
InputStream metadata = new ByteArrayInputStream(jsonObject.toString().getBytes("UTF-8"));
zipInputStream(stream, metadata, new ZipEntry("metadata"));
stream.finish();
stream.close();
stream = null;
return file;
} catch (FileNotFoundException e) {
//handling errrors
} catch (IOException e) {
//handling errrors
}
}
private String zipFile(String name, ZipOutputStream zipStream, File file) throws FileNotFoundException, IOException {
ZipEntry zipEntry = new ZipEntry(name);
return zipInputStream(zipStream, new FileInputStream(file), zipEntry);
}
private String zipInputStream(ZipOutputStream zipStream, InputStream fileInputStream, ZipEntry zipEntry) throws IOException {
InputStream inputStream = new BufferedInputStream(fileInputStream);
MessageDigest messageDigest = null;
try {
messageDigest = MessageDigest.getInstance("MD5");
if (messageDigest != null)
inputStream = new DigestInputStream(inputStream, messageDigest);
} catch (NoSuchAlgorithmException e) {
}
zipStream.putNextEntry(zipEntry);
inputToOutput(inputStream, zipStream);
zipStream.closeEntry();
inputStream.close();
if (messageDigest != null) {
return getDigestString(messageDigest.digest());
}
return null;
}
private String getDigestString(byte[] digest) {
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < digest.length; i++) {
String hex = Integer.toHexString(0xFF & digest[i]);
if (hex.length() == 1) {
hex = new StringBuilder("0").append(hex).toString();
}
hexString.append(hex);
}
return hexString.toString();
}
private void inputToOutput(InputStream inputStream, OutputStream outputStream) throws IOException {
byte[] buffer = new byte[BUFFER];
int count = 0;
while ((count = inputStream.read(buffer, 0, BUFFER)) != -1) {
outputStream.write(buffer, 0, count);
}
}
公共无效备份(字符串文件名){
File File=新文件(getBackupDirectory(),文件名);
FileOutputStream FileOutputStream=null;
ZipOutputStream=null;
试一试{
字符串设置MD5=null;
字符串databaseMD5=null;
if(file.exists())
delete();
fileOutputStream=新的fileOutputStream(文件);
stream=新的ZipoutStream(新的BufferedOutputStream(fileOutputStream));
文件数据库=getDatabasePath(databaseFileName);
File dataDirectory=getFilesDir();
if(dataDirectory!=null){
文件设置=新文件(dataDirectory.getParentFile(),“/shared\u prefs/”+首选项\u FILENAME);
settingsMD5=zipFile(“首选项”、流、设置);
}
databaseMD5=zipFile(“database.db”、流、数据库);
JSONObject JSONObject=新的JSONObject();
试一试{
put(META_DATE,新的SimpleDateFormat(DATE_格式,Locale.US).FORMAT(new DATE());
jsonObject.put(META_数据库,databaseMD5);
jsonObject.put(元共享优先权,设置MD5);
}捕获(例外e){
e、 printStackTrace();
}
InputStream元数据=新的ByteArrayInputStream(jsonObject.toString().getBytes(“UTF-8”);
zipInputStream(流、元数据、新ZipEntry(“元数据”));
stream.finish();
stream.close();
流=空;
返回文件;
}catch(filenotfounde异常){
//处理错误
}捕获(IOE异常){
//处理错误
}
}
私有字符串zipFile(字符串名称、ZipOutStream zipStream、文件文件)抛出FileNotFoundException、IOException{
ZipEntry ZipEntry=新ZipEntry(名称);
返回zipInputStream(zipStream,新文件输入流(文件),zipEntry);
}
私有字符串zipInputStream(ZipOutStream zipStream、InputStream文件InputStream、ZipEntry ZipEntry)引发IOException{
InputStream InputStream=新的BufferedInputStream(fileInputStream);
MessageDigest=null;
试一试{
messageDigest=messageDigest.getInstance(“MD5”);
if(messageDigest!=null)
inputStream=新摘要inputStream(inputStream,messageDigest);
}捕获(无算法异常){
}
zipStream.putNextEntry(Zippentry);
输入输出(输入流、zipStream);
zipStream.closeEntry();
inputStream.close();
if(messageDigest!=null){
返回getDigestString(messageDigest.digest());
}
返回null;
}
私有字符串getDigestString(字节[]摘要){
StringBuffer hexString=新的StringBuffer();
for(int i=0;i <代码> > p>您可以考虑使用ZIP4J库。我用这个库解决了我遇到的问题(相同的问题-不同的方向)。有些zip文件无法使用本机android实现解码,但可以使用zip4j。您还可以通过使用zip4j进行压缩来解决问题。这里有一些代码,可以仅使用java标准类将目录压缩到文件中。有了这个,您可以直接呼叫:
ZipUtils.zip(sourceDirectory, targetFile);
ZipUtils.unzip(sourceFile, targetDirectory);
代码:
package com.my.project.utils.zip;
导入java.io.IOException;
导入java.nio.file.FileVisitResult;
导入java.nio.file.Files;
导入java.nio.file.Path;
导入java.nio.file.SimpleFileVisitor;
导入java.nio.file.attribute.BasicFileAttributes;
导入java.util.zip.ZipEntry;
导入java.util.zip.ZipoutStream;
公共类ZipUtils{
公共静态void解压(路径sourceFile,路径targetPath)引发IOException{
try(ZipInputStream zipInStream=newzipinputstream(Files.newInputStream(sourceFile))){
字节[]缓冲区=新字节[1024];
创建目录(targetPath);
ZipEntry条目=null;
而((entry=zipInStream.getNextEntry())!=null){
Path entryPath=targetPath.resolve(entry.getName());
Files.createDirectories(entryPath.getParent());
复制(zipInStream,entryPath);
zipInStream.closeEntry();
}
}
}
公共静态void zip(路径sourcePath,路径targetFile)引发IOException{
try(zipoutptstream zipOutStream=new zipoutptstream(Files.newOutputStream(targetFile))){
if(Files.isDirectory(sourcePath)){
zipDirectory(zipOutStream,sourcePath);
}否则{
createZipEntry(zipOutStream、sourcePath、sourcePath);
}
}
}
私有静态void zipDirectory(ZipOutStream zip,路径源)引发IOException{
walkFileTree(源代码,新的SimpleFileVisitor(){
@凌驾
公共文件VisitResult preVisitDirectory(路径目录,基本文件属性属性属性)引发IOException{
返回FileVisitResult.CONTINUE;
package com.my.project.utils.zip;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipUtils {
public static void unzip(Path sourceFile, Path targetPath) throws IOException {
try (ZipInputStream zipInStream = new ZipInputStream(Files.newInputStream(sourceFile))){
byte[] buffer = new byte[1024];
Files.createDirectories(targetPath);
ZipEntry entry = null;
while ((entry = zipInStream.getNextEntry()) != null){
Path entryPath = targetPath.resolve(entry.getName());
Files.createDirectories(entryPath.getParent());
Files.copy(zipInStream, entryPath);
zipInStream.closeEntry();
}
}
}
public static void zip(Path sourcePath, Path targetFile) throws IOException {
try (ZipOutputStream zipOutStream = new ZipOutputStream(Files.newOutputStream(targetFile))){
if (Files.isDirectory(sourcePath)){
zipDirectory(zipOutStream, sourcePath);
} else {
createZipEntry(zipOutStream, sourcePath, sourcePath);
}
}
}
private static void zipDirectory(ZipOutputStream zip, Path source) throws IOException {
Files.walkFileTree(source, new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
createZipEntry(zip, source, path);
return FileVisitResult.CONTINUE;
}
});
}
private static void createZipEntry(ZipOutputStream zip, Path sourcePath, Path path) throws IOException {
ZipEntry entry = new ZipEntry(sourcePath.relativize(path).toString());
zip.putNextEntry(entry);
Files.copy(path,zip);
zip.closeEntry();
}
}