使用java读取jar包,hdfs,本地文件

使用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,或者是本地文件,我们只要传入相应的参数,调用接口,写我们的业务逻辑就好了,再也不用担心该怎么读取这些文件了!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值