1、需求
北京市,按照村为单位,生成文件结构(包含市、区、镇,村/小区),最底层结构(村/小区)下面生成excel文件。
Excel生成参考:https://blog.csdn.net/u010286334/article/details/117107595
2、压缩
2.1、生成树状结构的
public class Tree {
private String code;
private String name;
private List<String> urlList;
private List<Tree> childs;
public Tree() {
childs = new ArrayList();
childs.clear();
}
}
public static Tree createTree(String[] areaCodes){
Tree tree = new Tree();
tree.setCode("中国");
tree.setName("中国");
Tree delegate = null;
for (String areaCode : areaCodes) {
int areaCount = areaCode.length();
delegate = tree;
int codeLength = 0;
for (int i=0;i<areaCodeLevel;i++){
codeLength += areaCodeLevelLength[i];
String subCode = areaCode.substring(0, codeLength);
//00或者000该层为空
//90 省直辖县级行政规划
if(shouldSkip(i, subCode)){
continue;
}
String subName = findAreaName(subCode, codeLength);
Tree existNode = findExistNode(delegate, subCode, subName);
if(existNode!=null){
delegate = existNode;
} else if(!"00".equals(subCode)){
Tree subTree = new Tree();
subTree.setCode(subCode);
subTree.setName(subName);
delegate.addNode(subTree);
delegate = subTree;
}
}
}
return tree;
}
private static String findAreaName(String subCode, int codeLength) {
String code = subCode+StringUtils.repeat("0", CODE_LENGTH-codeLength);
String name = codeNameMap.get(code);
System.out.println(code+":"+name);
return name;
}
private static Tree findExistNode(Tree delegate, String subCode, String subName) {
for (Tree child : delegate.getChilds()) {
if(subCode.equals(child.getCode())
&& subName.equals(child.getName())){
return child;
}
}
return null;
}
2.2、根据2.1中生成的数据结构构建zip文件
public static String generateFileFromTree( Tree tree, String format, boolean hasHead) throws Exception {
// 压缩文件的路径不存在
if (null == tree) {
throw new Exception("文件树为空,无法进行压缩...");
}
// 用于存放压缩文件的文件夹
String generateFile = "D:" + File.separator +"CompressFile";
File compress = new File(generateFile);
// 如果文件夹不存在,进行创建
if( !compress.exists() ){
compress.mkdirs();
}
// 目的压缩文件
String generateFileName = compress.getAbsolutePath() + File.separator + "文件名称"+DateUtil.getDate()+"." + format;
// 输出流
FileOutputStream outputStream = new FileOutputStream(generateFileName);
// 压缩输出流
ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(outputStream));
generateFileFromTree(zipOutputStream, tree.getChilds(), "");
System.out.println("目的压缩文件生成位置:" + generateFileName);
// 关闭 输出流
zipOutputStream.close();
return generateFileName;
}
/**
* @param out 输出流
* @param treeList 目标树
* @throws Exception
*/
private static void generateFileFromTree(ZipOutputStream out, List<Tree> treeList, String dir) throws Exception {
// 当前的是文件夹,则进行一步处理
if (CollectionUtils.isNotEmpty(treeList)) {
//循环将文件夹中的文件打包
for (Tree tree : treeList) {
String name = tree.getName();
String subDir = dir + "/" + name;
//得到文件列表信息
//将文件夹添加到下一级打包目录
out.putNextEntry(new ZipEntry(subDir + "/"));
subDir = subDir.length() == 0 ? "" : subDir + "/";
//递归调用,生成各级文件夹
generateFileFromTree(out, tree.getChilds(), subDir);
}
} else { // 当前是底层文件
// 标记要打包的条目
out.putNextEntry(new ZipEntry(dir+"明细"+FORMAT_INNER_EXCEL));
// 输入流
//TODO 查询业务数据
List<ExportDto> list = new ArrayList<>(1);
ExportDto exportDto = new ExportDto();
exportDto.setBatchNo("123456788");
list.add(exportDto);
ByteArrayInputStream inputStream = ExcelUtil.write(list, ExportDto.class, "明细", 0);
// 进行写操作
int len = 0;
byte[] bytes = new byte[1024];
while ((len = inputStream.read(bytes)) > 0) {
out.write(bytes, 0, len);
}
// 关闭输入流
inputStream.close();
}
}
3、解压
public static void decompressionFile(InputStream inputStream, Function<InputStream, Boolean> function) throws IOException {
//zip读取压缩文件
ZipInputStream in ;
try {
in = new ZipInputStream(inputStream, Charset.forName("gbk"));
}catch (Exception e){
in = new ZipInputStream(inputStream, Charset.forName("utf-8"));
}
ZipEntry zipEntry;
while ((zipEntry=in.getNextEntry())!=null) {
//如果是目录,不处理
if (zipEntry.isDirectory()){
System.err.println("当前路径为目录:"+zipEntry.getName());
}else {
//getNextEntry() 读取下一个ZIP文件条目,并将流定位在条目数据的开头。
//这里in里面的文件流都是当前条目的文件数据, in.read读完就可以了
File tmpFile = FileUtils.createTmpFile("tmp.xlsx");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tmpFile));
int len;
byte[] buff = new byte[1024];
while ((len = in.read(buff)) != -1) {
bos.write(buff, 0, len);
}
bos.close();
//读取当前文件的数据流,
//function单独处理当前文件的数据
boolean result = function.apply(new FileInputStream(tmpFile));
tmpFile.delete();
}
}
//关闭流
in.close();
}