使用java读取jar包,hdfs,本地文件
使用java读取各种类型的文件需求 : 在程序执行的过程中,很多地方需要读取并解析一些配置文件这些配置文件,有的存储在hdfs文件系统,有的保存在linux或windows环境下有的被打包在了jar包里面.....那么该如何读取并解析这些文件呢?---------------------------------------1. 读取本地文件或者文件夹a. 读取并解析本地文...
·
使用java读取各种类型的文件
需求 : 在程序执行的过程中,很多地方需要读取并解析一些配置文件
这些配置文件,有的存储在hdfs文件系统,有的保存在linux或windows环境下
有的被打包在了jar包里面.....
那么该如何读取并解析这些文件呢?
1. 读取本地文件或者文件夹
a. 读取并解析本地文件
首先给出一个本地文件的示例 : D:\mastercom\data\userhot_log_1.1(windows下)
读取:
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8")); //path是文件的路径,设置为UTF-8,中文不会乱码
解析:
String strData = null;
while ((strData = reader.readLine()) != null)
{
if (strData.trim().length() == 0)
{
continue;
}
System.out.println(strData);
}
不管是本地文件,jar包文件,还是hdfs上面的文件,获取到输入流之后的解析方法都是一样的! 后续只介绍读取方法
b. 读取本地文件夹
File file = new File(path); // path是文件夹的路径
File [] fileList = file.listFile(); // 获取该文件夹下面的文件
for (File f : fileList)
{
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(path), "UTF-8")); // 对每一个文件,获取输入流
}
之后就按照上述步骤进行解析即可!
2. 读取jar包里面的文件或者文件夹! 个人认为这个是稍微复杂一点的
给出一个jar包文件路径的示例 :
jar:file:\E:\ruanjian\lib_package\xmr.jar!/cn/mastercom/bigdata/conf/cellconfig
a. 读取jar包文件
对于jar包里的文件,直接使用上述方法是找不到的,需要做一些转换-->才能够找到相应的路径
1) 第一种方式,利用类加载器
ConfigReader.class.getResourceAsStream("/xmr.txt"));
// 这里指的是读取ConfigReader所在jar包的SRC目录下的xmr.txt文件
这种方式是有局限性的 : 只可以读取到src目录下的文件:
如果配置文件很不巧放在jar包下的其它文件夹下,就要使用下面的方式:
2) 第二种方式,使用url
String jarPath = ConfigReader.class.getProtectionDomain().getCodeSource().getLocation().getFile(); //获得jar包的绝对路径
String path = cn/mastercom/bigdata/conf/cellconfig/xmr.txt //jar包里面文件的路径
URL url = new URL("jar:file:" + jarPath + "!/" + path);
InputStream is = url.openStream(); //使用url的方式获取输入流
reader = new BufferedReader(new InputStreamReader(is));
// 获取到流之后,我们就可以用上述的方式来对文件进行解析!
b. 读取jar包文件夹
对于这种方式的支持应该不是很友好,我在网上搜了好多也没找到原生的api或者是博客对此也很少涉猎,我就根据我们的业务需要,写了一个对指定文件夹下的文件进行读取的方法
List<String> fileNameList = null;
String jarPath = ConfigReader.class.getProtectionDomain().getCodeSource().getLocation().getFile(); //获取到jar包的绝对路径
JarFile jarFile = new JarFile(jarPath); // 获取到JarFile对象的实例
Enumeration<JarEntry> entrys = jarFile.entries(); // 其中包括jarFile下面的所有文件和文件夹
// 遍历jar下面的所有实例,如果其为文件夹并且包含我们指定的过滤关键字,就添加到list集合里面, 这样,我们就通过list集合拿到了所有需要我们解析的文件夹
while (entrys.hasMoreElements())
{
JarEntry jar = entrys.nextElement();
if (jar.getName().contains(filterPath) && jar.isDirectory())
{
fileNameList.add(jar.getName());
}
}
if (fileNameList == null)
{
return false;
}
// list集合不为空的话, 遍历该list集合, 解析文件
for (String fileName : fileNameList)
{
URL url = new URL("jar:file:" + jarPath + "!/" + fileName);
InputStream is = url.openStream();
reader = new BufferedReader(new InputStreamReader(is));
}
3. 读取hdfs文件或者文件夹
a.读取文件
Configuration conf = new Configuration(); // 创建hadoop配置
FileSystem fs = FileSystem.get(conf); //根据该配置获得hdfs文件系统对象
String filePath = "xmr/xmr.txt"
Path file = new Path(filePath);
BufferedReader reader = new BufferedReader(new InputStreamReader(fs.open(file), "UTF-8"))
// 之后按行进行解析即可!
b. 读取文件夹
Configuration conf = new Configuration(); // 创建hadoop配置
FileSystem fs = FileSystem.get(conf); //根据该配置获得hdfs文件系统对象
FileStatus[] fileStatusArr = fs.listFileStatus();
for (FileStatus fileStatus : fileStatusArr)
{
// 解析文件或者文件夹
}
需要注意的地方 :
1. 读取jar包里面文件的方法,不能直接使用这种方法 :
File file = new File("jar:file:\" + urlPath + \"!/cn/mastercom/bigdata/conf/cellconfig/xmr.txt");
// 一定找不到!!!
2. 在不是文件夹的情况下 :
调用 方法
File [] fileList = file.listFiles();
是不被允许的!
但方法 :
FileStatus[] fileStatusArr = fs.listFileStatus(); //其中fs是一个FileSystem对象
就是没问题的!
3. 类名.class.getResourceAsStream("/文件名"));
这种方法只能读取 : src目录下的文件名, 而且文件名前面必须加/
-----------
之前公司的 代码里,基本上每读一次配置都要写一遍上述的代码.
导致高度重复的代码出现 多次,
为了避免这种情况的发生,影响代码可读性
就把读取各种文件夹,文件的方法抽离出来整理出两个工具类 一个针对于hdfs,另一个类针对于本地,jar包文件.
实际读取配置的时候,只需要写对配置文件按行进行处理的逻辑代码即可!
下面附上其中一个工具类的源码及调用方式,希望能对各位产生一些帮助!
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.PathFilter;
import org.apache.hadoop.io.compress.CompressionCodec;
import org.apache.hadoop.io.compress.CompressionCodecFactory;
/**
* 从文件系统中读取文本,支持文本格式和压缩文件
* @author Kwong
*/
public final class FileReader {
private static final Log LOG = LogFactory.getLog(FileReader.class);
private FileReader(){}
public interface LineHandler
{
void handle(String line);
}
private static FileStatus[] listFileStatus(FileSystem fs, String dirpath) throws Exception
{
Path directory = new Path(dirpath);
if(!fs.exists(directory)){
throw new FileNotFoundException(dirpath);
}
FileStatus[] fileStatusArr = fs.listStatus(directory, new PathFilter()
{
@Override
public boolean accept(Path path)
{
if(path.getName().endsWith(".crc"))
return false;
else return true;
}
});
return fileStatusArr;
}
/**
* 读取文件文本(支持压缩),并回调处理每行
* @param conf 配置
* @param dirpath 目录
* @param linehandler 回调处理
* @return
* @throws Exception
*/
public static boolean readFiles(Configuration conf, String dirpath, LineHandler linehandler) throws Exception
{
FileSystem fs = FileSystem.get(conf);
FileStatus[] fileStatusArr = listFileStatus(fs, dirpath);
for (FileStatus fileStatus : fileStatusArr)
{
readFile(fs, fileStatus.getPath(), linehandler);
}
return true;
}
public static boolean readFiles(String dirpath, LineHandler linehandler) throws Exception{
return readFiles(new Configuration(),dirpath, linehandler);
}
/**
* 读取文件文本(支持压缩),并回调处理每行
* @param conf 配置
* @param filePath 文件路径
* @param linehandler 每行回调处理
* @return
* @throws Exception
*/
public static boolean readFile(Configuration conf, String filePath, LineHandler linehandler) throws Exception
{
FileSystem fs = FileSystem.get(conf);
Path file = new Path(filePath);
if(!fs.exists(file)){
throw new FileNotFoundException(filePath);
}
return readFile(fs, file, linehandler);
}
/**
* 读取文件文本(支持压缩),并回调处理每行
* @param filePath 文件路径
* @param linehandler 每行回调处理
* @return
* @throws Exception
*/
public static boolean readFile(String filePath, LineHandler linehandler) throws Exception
{
return readFile(new Configuration(), filePath, linehandler);
}
/**
* 读取文件文本(支持压缩),并回调处理每行
* @param fs 文件系统
* @param file 文件路径
* @param linehandler 每行回调处理
* @return
* @throws Exception
*/
public static boolean readFile(FileSystem fs, Path file, LineHandler linehandler) throws Exception{
//从文件名判断是否压缩
boolean isCompressedFile;
final CompressionCodec codec = new CompressionCodecFactory(fs.getConf()).getCodec(file);
if (null == codec) {
isCompressedFile = false;
}else{
isCompressedFile = true;
}
String strData = null;
try(BufferedReader reader = new BufferedReader(new InputStreamReader(isCompressedFile ? codec.createInputStream(fs.open(file)) : fs.open(file), "UTF-8")))
{
while ((strData = reader.readLine()) != null)
{
if (strData.trim().length() == 0)
{
continue;
}
linehandler.handle(strData);
}
}
catch (Exception e)
{
throw e;
}
return true;
}
}
调用方式 :
FileReader.readFile(job.getConfiguration(), path, new LineHandler()
{
@Override
public void handle(String line)
{
// 对读取到的每行内容进行处理的逻辑代码
}
});
这样,无论是读取jar包,hdfs,或者是本地文件,我们只要传入相应的参数,调用接口,写我们的业务逻辑就好了,再也不用担心该怎么读取这些文件了!
更多推荐
已为社区贡献1条内容
所有评论(0)