如何在Hadoop 3.0中进行CopyMerge?

时间:2017-02-04 02:08:48

标签: java hadoop

我知道hadoop版本2.7的{​​{1}}具有FileUtil功能,可将多个文件合并为一个新文件。

copyMerge版本中的API不再支持copyMerge函数。

关于如何将目录中的所有文件合并到3.0版本的hadoop中的新单个文件中的任何想法?

4 个答案:

答案 0 :(得分:7)

FileUtil#copyMerge方法已被删除。查看主要变更的详细信息:

https://issues.apache.org/jira/browse/HADOOP-12967

https://issues.apache.org/jira/browse/HADOOP-11392

您可以使用getmerge

用法:hadoop fs -getmerge [-nl]

将源目录和目标文件作为输入,并将src中的文件连接到目标本地文件。可选地,-nl可以设置为允许在每个文件的末尾添加换行符(LF)。 -skip-empty-file可用于在空文件的情况下避免不需要的换行符。

示例:

hadoop fs -getmerge -nl /src /opt/output.txt
hadoop fs -getmerge -nl /src/file1.txt /src/file2.txt /output.txt

退出代码: 成功时返回0,错误时返回非零。

https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/FileSystemShell.html#getmerge

答案 1 :(得分:3)

我有同样的问题,不得不重新实现copyMerge (虽然在PySpark中,但使用与原始copyMerge相同的API调用)。

不知道为什么Hadoop 3中没有相同的功能。 我们必须经常将HDFS目录中的文件合并到HDFS文件中。

以上引用的pySpark中的实现 https://github.com/Tagar/stuff/blob/master/copyMerge.py

答案 2 :(得分:3)

由于FileUtil.copyMerge()已被弃用并从API开始版本3中删除,因此一个简单的解决方案就是自己重新实现它。

Here是以前版本的 Java 原始实现。

这是 Scala 重写:

import scala.util.Try
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.hadoop.io.IOUtils
import java.io.IOException

def copyMerge(
    srcFS: FileSystem, srcDir: Path,
    dstFS: FileSystem, dstFile: Path,
    deleteSource: Boolean, conf: Configuration
): Boolean = {

  if (dstFS.exists(dstFile))
    throw new IOException(s"Target $dstFile already exists")

  // Source path is expected to be a directory:
  if (srcFS.getFileStatus(srcDir).isDirectory()) {

    val outputFile = dstFS.create(dstFile)
    Try {
      srcFS
        .listStatus(srcDir)
        .sortBy(_.getPath.getName)
        .collect {
          case status if status.isFile() =>
            val inputFile = srcFS.open(status.getPath())
            Try(IOUtils.copyBytes(inputFile, outputFile, conf, false))
            inputFile.close()
        }
    }
    outputFile.close()

    if (deleteSource) srcFS.delete(srcDir, true) else true
  }
  else false
}

答案 3 :(得分:0)

这应该有效

/** Copy all files in a directory to one output file (merge). */
    public static boolean copyMerge(FileSystem srcFS, Path srcDir,
                                    FileSystem dstFS, Path dstFile,
                                    boolean deleteSource,
                                    Configuration conf, String addString) throws IOException {
        dstFile = checkDest(srcDir.getName(), dstFS, dstFile, false);

        if (!srcFS.getFileStatus(srcDir).isDirectory())
            return false;

        OutputStream out = dstFS.create(dstFile);

        try {
            FileStatus contents[] = srcFS.listStatus(srcDir);
            Arrays.sort(contents);
            for (int i = 0; i < contents.length; i++) {
                if (contents[i].isFile()) {
                    InputStream in = srcFS.open(contents[i].getPath());
                    try {
                        IOUtils.copyBytes(in, out, conf, false);
                        if (addString!=null)
                            out.write(addString.getBytes("UTF-8"));

                    } finally {
                        in.close();
                    }
                }
            }
        } finally {
            out.close();
        }


        if (deleteSource) {
            return srcFS.delete(srcDir, true);
        } else {
            return true;
        }
    }

    private static Path checkDest(String srcName, FileSystem dstFS, Path dst,
                                  boolean overwrite) throws IOException {
        if (dstFS.exists(dst)) {
            FileStatus sdst = dstFS.getFileStatus(dst);
            if (sdst.isDirectory()) {
                if (null == srcName) {
                    throw new IOException("Target " + dst + " is a directory");
                }
                return checkDest(null, dstFS, new Path(dst, srcName), overwrite);
            } else if (!overwrite) {
                throw new IOException("Target " + dst + " already exists");
            }
        }
        return dst;
    }