HDFS集群内文件移动的Java实现

版权声明:虽然坑有点多,不过转载请声明原作者 https://blog.csdn.net/jyj1100/article/details/83627553

写在前面:

这是关于HDFS的api org.apache.hadoop.fs 小科普和吐槽,不过这个问题没有看过类似的,有一点提的价值。这个问题是实现需求:移动一个文件从一个目录到另一个目录。


实现方案

实现了后确实很简单,先创建对象,然后调用api就行。

 /**
     * 获取hdfs的文件系统对象
     *
     * @return FileSystem
     * @throws IOException 打开HDFS文件系统异常
     */
    public static FileSystem createFileSystemInstance() throws IOException {
        Configuration conf = new Configuration();
        return FileSystem.get(conf);
    }  


  /**
     * 移动hdfs上目录或文件到
     * @param path 当前路径
     * @param newPath 目标路径
     * @return 是否移动成功
     */
    public static boolean mv(String path,String newPath) {
        boolean result = false;
        FileSystem fs = null;
        try {
            fs =  HDFSUtil.createFileSystemInstance();
            if (!fs.exists(new Path(newPath))){
                result=fs.rename(new Path(path),new Path(newPath)); 
            }else {
                LOGGER.warn("HDFS上目录: {} 被占用!",newPath);
            }
        } catch (Exception e) {
            LOGGER.error("移动HDFS上目录:{} 失败!", path, e);
        } finally {
            //close(fs);
        }

       return result;
    }

但调用的api十分有趣:rename,没错 就是重命名,尤其是linux的移动命令都是 hadoop fs -mv的时候。但最后就是这个重命名的api实现了需求(真的迷)

最开始在org.apache.hadoop.fs 找到两个与移动相关的api moveToLocalFile和 moveFromLocalFile 会在运行中显示找不到源文件,我觉得这两个api的作用是用在本机和集群之间的文件传输(待验证),但显然无法作用于hdfs系统的文件之间。


11.9补充

实际上有更好的实现,可以完成模糊查询数据追加等操作

 /**
     *@param prePath 需要合并的文件目录
     * @param resPath 合并输出的文件名
     *                合并文件 读取文件的目录 然后依次读文件并合并输出到一个文件中,并删除原文件
     *                不处理递归
     */
    public static void mergeFile(String prePath, String resPath) throws Exception {
        FileSystem hdfs = HDFSUtil.createFileSystemInstance();
        //获取文件目录(采用模糊查询的方法)
        FileStatus[] fileStatuses = hdfs.globStatus(new Path(prePath));
        //创建文件输出流
        FSDataOutputStream fsOutStream = hdfs.create(new Path(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);
                    //删除原文件,去掉后就是不删除原文件
                    hdfs.delete(tmpPath, true);
                }

            }

        } catch (Exception ex) {
            System.out.println(ex.toString());
        } finally {
            //关闭输出流
         //   IOUtils.closeStream(fsOutStream);
        }
    }

猜你喜欢

转载自blog.csdn.net/jyj1100/article/details/83627553