项目背景:系统数据对接,删量对方返回一个Base64的字符串,转文件后为zip,而且zip里面还会含有zip文件,最终才会存在xml文件记录有删量标识。
解决方法:
1.先将Base64转为文件。
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import static com.xzl.common.util.ReadXMLFromZIP.readZipFile;
/**
* 文件与base64的互相转换操作
*/
public class Base64ToZIPFile {
/**
* 测试main
*
* @param args args
*/
public static void main(String[] args) {
Base64ToZIPFile t = new Base64ToZIPFile();
try {
// 拿到的Base64文件
String ret = "UEsDBBQACAAIAAAAAA==";
Long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
t.decoderBase64File(ret, "C://" + milliSecond + ".zip", "C://");
String zipfile_dir = "C://" + milliSecond + ".zip";
try {
// 读取xml
readZipFile(zipfile_dir);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将文件转成base64 字符串
*
* @param path 文件路径
* @return *
* @throws Exception
*/
public static String encodeBase64File(String path) throws Exception {
File file = new File(path);
FileInputStream inputFile = new FileInputStream(file);
byte[] buffer = new byte[(int) file.length()];
inputFile.read(buffer);
inputFile.close();
return new BASE64Encoder().encode(buffer);
}
/**
* 将base64字符解码保存文件
*
* @param base64Code 文件base64
* @param targetPath 文件地址
* @param catalogue 存放文件夹
*/
public static void decoderBase64File(String base64Code, String targetPath, String catalogue)
throws Exception {
File file = new File(catalogue);
if (file.exists() == false) {
file.mkdirs();
}
byte[] buffer = new BASE64Decoder().decodeBuffer(base64Code);
FileOutputStream out = new FileOutputStream(targetPath);
out.write(buffer);
out.close();
}
2.实现文件循环读取
import java.io.*;
import java.nio.charset.Charset;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
/**
* 阅读zip里的xml
*/
public class ReadXMLFromZIP {
/**
* 读取zip文件
*
* @param file 文件地址
* @throws Exception 异常
*/
public static void readZipFile(String file) throws Exception {
readZipFile(new File(file));
}
/**
* 循环解压读取xml文件信息
*
* @param file 文件
* @throws Exception 异常
*/
public static void readZipFile(File file) throws Exception {
ZipFile zf = new ZipFile(file, Charset.forName("GBK"));
InputStream in = new BufferedInputStream(new FileInputStream(file));
ZipInputStream zis = new ZipInputStream(in);
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
if (ze.isDirectory()) {
System.err.println("true if this is a directory entry. A directory entry is!");
} else {
if (ze.getName().endsWith(".xml")) {
System.err.println("file - " + ze.getName() + " : " + ze.getSize() + " bytes");
// 不解压直接读取size为-1
if (ze.getSize() == -1) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while (true) {
int bytes = zis.read();
if (bytes == -1) {
break;
}
baos.write(bytes);
}
baos.close();
System.out.println(String.format("Name:%s,Content:%s", ze.getName(), new String(baos.toByteArray())));
} else {
// ZipEntry的size正常
byte[] bytes = new byte[(int) ze.getSize()];
zis.read(bytes, 0, (int) ze.getSize());
System.out.println(String.format("Name:%s,Content:%s", ze.getName(), new String(bytes)));
}
} else if (ze.getName().endsWith("zip")) {
//判断是否为压缩包,若是则将其解压出再读取
String fileName = file.getName().substring(0, file.getName().lastIndexOf("."));
File temp = new File(file.getParent() + File.separator + fileName + File.separator + ze.getName());
if (!temp.getParentFile().exists()) {
temp.getParentFile().mkdirs();
}
OutputStream os = new FileOutputStream(temp);
通过ZipFile的getInputStream方法拿到具体的ZipEntry的输入流
InputStream is = zf.getInputStream(ze);
int len;
while ((len = is.read()) != -1) {
os.write(len);
}
os.close();
is.close();
// 递归调取解压
readZipFile(temp.getPath());
}
}
}
zis.closeEntry();
zis.close();
zf.close();
}
}