HDFS中合并大量小文件成大文件(尤其是日志文件)对于存储和后面的计算等都有很大的帮助。

之前记录了如何使用FileSystem API操作HDFS文件,根据之前的积累,实现对小文件的内容的合并并输出到一个文件中。

1、思路

一次读取目录中的小文件内容,并写入一个文件中即可, 主要是用到了API中的read和write两个操作。

2、代码及注释

package com.hdfstest;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;

import java.net.URI;

/**
 * Project   : hadooptest2
 * Package   : com.hdfstest
 * User      : Postbird @ http://www.ptbird.cn
 * TIME      : 2017-01-18 21:35
 */
public class HDFSTestCombineFile {
    //hdfs的active node
    public static String hdfsUrl = "hdfs://node2.hadoop.ptbird.cn:8020";

    //获得hafs的配置信息
    public static FileSystem getHdfs() throws Exception {
        //获取配置文件信息
        Configuration conf = new Configuration();
        //获取文件系统
        FileSystem hdfs = FileSystem.get(URI.create(hdfsUrl), conf);
        return hdfs;
    }

    /**
     *@param prePath 需要合并的文件目录
     * @param resPath 合并输出的文件名
     *                合并文件 读取文件的目录 然后依次读文件并合并输出到一个文件中
     *                不处理递归
     */
    public static void mergeFile(Path prePath, Path resPath) throws Exception {
        FileSystem hdfs = getHdfs();
        //获取文件目录
        FileStatus[] fileStatuses = hdfs.listStatus(prePath);
        //创建文件输出流
        FSDataOutputStream fsOutStream = hdfs.create(resPath, true);
        try {
            for (FileStatus fs : fileStatuses) {
                Path tmpPath = fs.getPath();
                Boolean isFile = fs.isDirectory() ? false : true;
                //只操作文件
                if (isFile) {
                    System.out.println(tmpPath.getName());
                    //打开文件流
                    FSDataInputStream inStream = hdfs.open(tmpPath);
                    //读取文件内容到输出文件流
                    IOUtils.copyBytes(inStream, fsOutStream, 4096, false);
                    //关闭临时的输入流
                    IOUtils.closeStream(inStream);
                }
            }
        } catch (Exception ex) {
            System.out.println(ex.toString());
        } finally {
            //关闭输出流
            IOUtils.closeStream(fsOutStream);
        }
    }

    public static void main(String args[]) throws Exception {
        Path prePath = new Path("/test/input");
        Path resPath = new Path("/test/output/res.txt");
        mergeFile(prePath, resPath);
    }
}

3、代码存放

git@osc地址:https://git.oschina.net/postbird/codes/4m1fbictx60qs5rj827ld88

postbird

4、其他补充


使用markdown编辑代码的时候,本身 `` 的语法没有问题,但是没办法做高亮。

我是用的是prism的高亮,因此实际上每次我都是使用 pre.language-java 这样的标签里面套代码,但是发现由于markdown的原因,很多时候我的代码加进去就会引起格式错误,从而导致代码显示有问题。

有时间需要解决这个问题。

查了一下 prism也只是markdown的 `java ` 这样的语法,直接就这样子写就好,之前自己写的简直是烧饼头顶。。。。。。