因为项目业务需要,实现调用第三方接口获取zip文件(byte数组形式接收),并解析文件的数据内容,将数据转化为自定义的对象保存于数据库中。整个过程不需要将文件存于磁盘。
以下为笔者所实现功能的代码,首次分享,大牛勿喷,多多指教~
public void resolveZipFile() {
//自定义对象接收数据
Class<Item> clazz = Item.class;
//调用第三方接口获取文件(byte[]形式接收,为utf-8的编码格式)
byte[] byt = new byte[0];
try {
byt = ThirdService.downloadZipFile();
System.out.println(new String(byt,"UTF-8"));
} catch (NullPointerException e) {
loger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>文件为空<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
//输出文件到磁盘,检查文件数据内容及结构,方便测试。
OutputStream os = null;
InputStream in = null;
try {
os = new FileOutputStream("e://2019-01-31.zip");
in = new ByteArrayInputStream(byt);
byte[] bs = new byte[1024];
int len = 0;
while((len = in.read(bs)) != -1){
os.write(bs,0,len);
os.flush();
}
in.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
/*File file = new File("d://test.zip");
InputStream input = null;
byte[] byt = new byte[0];*/
//自定义ZipInputStream对象解析zip文件(参数为字节数组读入流读入上面的字节数组)
ZipInputStream zip = null;
//自定义字符缓冲流
BufferedReader br = null;
try {
/*input = new FileInputStream(file);
byt = new byte[input.available()];
input.read(byt);*/
zip = new ZipInputStream(new ByteArrayInputStream(byt));
ZipEntry zipEntry = null;
//记录文件数据行数(最终转为的对象数目)
int number = 0;
//当zip压缩文件内有文件时候进入解析
while ((zipEntry = zip.getNextEntry()) != null){
//读入文件,编码格式utf-8
br = new BufferedReader(new InputStreamReader(zip,"UTF-8"));
//读取文件第一行
String line = br.readLine();
//定义分隔符(这边文件分隔符为‘char27’)
String seperator = Character.toString((char) 27);
//获取第一行第一个字段(总记录数)
String num = line.split(seperator)[0];
//Field[] fields = clazz.getDeclaredFields();
while (line != null && !"0".equals(num)) {
//Object object = clazz.newInstance();
line = br.readLine(); // 一次读入一行数据
if (line == null || "".equals(line.trim())){
break;
}
//将每行数据转对象item
Item item = (Item) DataUtils.Str2Obj(line, seperator, clazz, 2);
System.out.println(item);
number++;
//保存到MongDB
mongoTemplate.save(item,"item");
}
}
System.out.println("文件数据行数:"+number);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//input.close();
zip.close();
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结:通过将 byteArrayInputStream对象读入字节数组,作为ZipInputStream的读入对象,再由字符缓冲流BufferInputStream读入ZipInputStream(作为new InputStreamReader的参数),编码格式utf-8。利用字符缓冲流的readLine()方法读入文件每一行数据,转化为item对象保存数据库。
流转化过程: byte[] --> new ByteArrayInputStream(byt) --> new ZipInputStream(bais) --> new InputStreamReader(zis,“UTF-8”) --> new BufferReader(ins)
如果初始以文件流形式接收而非byte[],可通过byteOutPutStream写入文件,再转字节数组,代码如下:
//自定义数组对象
byte[] byt= null;
//读入zip文件
File file = new File("d://test.zip");
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(fis.available());
byte[] bytes = new byte[fis.available()];
int temp;
while ((temp = fis.read(bytes)) != -1) {
bos.write(bytes, 0, temp);
}
fis.close();
bos.close();
//转化成字节数组
byt = bos.toByteArray();
嘿嘿,细心的小伙伴已经发现了,这里是其中一种实现方案,另一种已经写在前面的代码块里,不通过字节数组输出流便完成了转化
在前面的代码块中,本人自定义了工具类 DataUtils.Str2Obj方法实现字符串到对象的转化,至于工具类的实现细节,想了解的请点击另外一篇文章:https://blog.csdn.net/qq_41981107/article/details/85053446