如何利⽤java解析压缩⽂件中xml⽂件
应⽤场景
在⼤数据的⼯作中,每天必不可少的就是和数据打交道,我们需要从我们的业务⽅将数据采集过来,然后根据我们的业务逻辑将数据解析并转换成我们所需要的格式!⼤数据分析往往数据量都是⾮常⼤的,⼀天⼏⼗T都是很正常,如果按正常的来采集的话,估计就是采集都要花费不少时间,最常⽤的⽅式就是将数据进⾏压缩之后再进⾏传输,这样的效率是⽐较⾼的,也节省了带宽资源!举⼀个简单的例⼦,我们的逻辑是xml原始⽂件先压缩成⼀个gz⽂件,再将上百个gz⽂件再⼆次压缩成⼀个⽂件!⼀个压缩⽂件的⼤⼩⼤概是200M,但是解压出来就差不多20G此篇⽂章就记录⼀下实现功能需求的过程!
依赖
<dependency>
<groupId>org.apachemons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.5</version>
</dependency>
实现代码
slf4j.Slf4j;
import org.apachemonspress.archivers.tar.TarArchiveEntry;
import org.apachemonspress.archivers.tar.TarArchiveInputStream;
import org.apachemonspress.utils.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.zip.GZIPInputStream;
@Slf4j
public class FileUtils {
private static final Logger LOGGER = Logger(FileUtils.class);
public static void main(String[] args) {
deCompressGZipFile("path1", "dir1");
}
/**
* Tar⽂件解压⽅法
*
* @param tarGzFile 要解压的压缩⽂件名称(绝对路径名称)
* @param destDir 解压后⽂件放置的路径名(绝对路径名称)当路径不存在,会⾃动创建
* @return 解压出的⽂件列表
*/
public static void deCompressGZipFile(String tarGzFile, String destDir) {
// 建⽴输出流,⽤于将从压缩⽂件中读出的⽂件流写⼊到磁盘
TarArchiveEntry entry = null;
TarArchiveEntry[] subEntries = null;
File subEntryFile = null;
try (FileInputStream fis = new FileInputStream(tarGzFile);
GZIPInputStream gis = new GZIPInputStream(fis);
TarArchiveInputStream taris = new TarArchiveInputStream(gis);) {
while ((entry = NextTarEntry()) != null) {
StringBuilder entryFileName = new StringBuilder();
entryFileName.append(destDir).append(File.separator).Name());
File entryFile = new String());
if (entry.isDirectory()) {
if (!ists()) {
entryFile.mkdir();
}
subEntries = DirectoryEntries();
for (int i = 0; i < subEntries.length; i++) {
try (OutputStream out = new FileOutputStream(subEntryFile)) {
subEntryFile = new File(entryFileName + File.separator + subEntries[i].getName());
} catch (Exception e) {
<("deCompressing file failed:" + subEntries[i].getName() + "in" + tarGzFile);
}
}
} else {
checkFileExists(entryFile);
OutputStream out = new FileOutputStream(entryFile);
out.close();
//如果是gz⽂件进⾏递归解压
if (Name().endsWith(".gz")) {
String namepath = AbsolutePath();
compressGZ(namepath);
}
}
}
//如果需要刪除之前解压的gz⽂件,在这⾥进⾏
File dir = new File("dir1");
File[] files = dir.listFiles();
if (f.getName().split("\\.").length==3){
f.delete();
}
}
} catch (Exception e) {
LOGGER.warn("decompress failed", e);
}
}
/**
* 解压GZ⽂件
* @param pwd
*/
public static void compressGZ(String pwd){
if (!getExtension(pwd).equalsIgnoreCase("gz")) {
}
GZIPInputStream in = null;
try {
in = new GZIPInputStream(new FileInputStream(pwd));
} catch(FileNotFoundException e) {
} catch (IOException e) {
e.printStackTrace();
}
String outFileName = getFileName(pwd);
FileOutputStream out = null;
try {
out = new FileOutputStream(outFileName);
} catch (FileNotFoundException e) {
}
try {
byte[] buf = new byte[1024];
int len;
while((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Used to extract and return the extension of a given file.
* @param f Incoming file to get the extension of
* @return <code>String</code> representing the extension of the incoming * file.
*/
public static String getExtension(String f) {
String ext = "";
int i = f.lastIndexOf('.');
if (i > 0 && i < f.length() - 1) {
ext = f.substring(i+1);
}
return ext;
}
/**
* Used to extract the filename without its extension.
* @param f Incoming file to get the filename
* @return <code>String</code> representing the filename without its
* extension.
*/
public static String getFileName(String f) {
String fname = "";
int i = f.lastIndexOf('.');
if (i > 0 && i < f.length() - 1) {
fname = f.substring(0,i);
}
return fname;
}
public static void checkFileExists(File file) {
//判断是否是⽬录
if (!ists()) {
file.mkdir();
}
} else {
//判断⽗⽬录是否存在,如果不存在,则创建
if (ParentFile() != null && !ParentFile().exists()) {
}
try {
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这样就实现了将⽂件中的xml原始⽂件全部解压出来!之后就可以将xml⽂件中的数据拿出来做解析和分析了!java解析xml⽂件的⽅式有多种,这⾥使⽤dom4j!!依赖
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
实现代码
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
/**
* java DOM4j xml解析
*/
public class JavaXMLTest {
public static void main(String[] args) throws IOException, DocumentException {
SAXReader reader = new SAXReader();
Document xmlDocument = ad(new FileInputStream(new File("2.xml")));
/
/System.out.println(doc==null?"未读取到xml⽂件":"已读取到xml⽂件");
//获取根节点
Element rootElement = RootElement();
//获取根节点下的直接⼦节点的个数和名字
List<Element> list = rootElement.elements("fileHeader");
//System.out.println("根节点下有"+list.size()+"直接⼦节点");
//获取根节点下 fileHeader节点得value值
for (Element elemet:list) {
String reportTime = elemet.attributeValue("reportTime");
String startTime = elemet.attributeValue("startTime");
String endTime = elemet.attributeValue("endTime");
}
//获取根节点下所有得⼦节点
List<Element> list1 = rootElement.elements("header");
//System.out.println("根节点下header有"+list1.size()+"直接⼦节点");
//由于只有⼀个节点所以取get(0)
Element header = (0);
//获取header节点得value值
String id = header.attributeValue("id");
//System.out.println("id是"+id);
//获取header节点下所有 measure 节点
Element measure = header.elements("measure").get(0);
/
/获取measurement节点下 smr节点
Element sm = measure.elements("sm").get(0);
//获取smr节点的value值
String stringValue = sm.getStringValue();
//按照空格进⾏拆分
String[] objj = stringValue.split(" ");
dom4j读取xml//System.out.println("stringvalue===="+stringValue);
//List<Element> smlist = smr.elements("obj");
//获取measure节点下所有的 obj 节点
List<Element> objlist = measurement.elements("obj");
//Map<String,String> map = new HashMap();
/
/遍历所有 obj节点
for (Element ob:objectlist) {
//System.out.println(objj.length);
//获取所有 obj节点下的 v 节点
List<Element> vlist = ob.elements("v");
//遍历 v 节点
for (Element v:vlist) {
//System.out.println("v得value值是"+v.getStringValue());
//获取v节点的value值
String[] vv = v.getStringValue().split(" ");
//System.out.println(vv.length);
StringBuilder sb = new StringBuilder();
for (int i=0;i<objj.length;i++){
sb.append(objj[i]+"="+vv[i]);
}
System.out.String());
sb=null;
}
}
}
}
⾄此,利⽤java就完成了对⽂件的解压,并对xml原始⽂件进⾏数据解析这个⽅法对于⼩数据量
是可以实现的!但是⼤数据都是基于分布式⽂件系统Hadoop构建的!我们的数据都是存储在hdfs上的,⽽且数据也⾮常⼤,这样解压⽂件写到本地⽂件系统中,再解析其中的数据上传⾄hdfs!同时也是要消耗带宽的!最终在测试的时候是不⾏的!这个⽅案就被否定了!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论