我知道hadoop
版本2.7
的{{1}}具有FileUtil
功能,可将多个文件合并为一个新文件。
但copyMerge
版本中的API不再支持copyMerge
函数。
关于如何将目录中的所有文件合并到3.0
版本的hadoop中的新单个文件中的任何想法?
答案 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,错误时返回非零。
答案 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;
}