Java 如何在Hadoop 3.0中进行CopyMerge?
我知道hadoop的Java 如何在Hadoop 3.0中进行CopyMerge?,java,hadoop,Java,Hadoop,我知道hadoop的version2.7的FileUtil具有copyMerge功能,可以将多个文件合并到一个新文件中 但是3.0版本中的API不再支持copyMerge功能 关于如何在hadoop的3.0版本中将目录中的所有文件合并到新的单个文件中的任何想法都已删除。有关主要更改的详细信息,请参见: 您可以使用getmerge 用法:hadoop fs-getmerge[-nl] 将源目录和目标文件作为输入,并将src中的文件连接到目标本地文件中。(可选)可以将-nl设置为允许在每个文件的
version2.7
的FileUtil
具有copyMerge
功能,可以将多个文件合并到一个新文件中
但是3.0
版本中的API不再支持copyMerge
功能
关于如何在hadoop的3.0
版本中将目录中的所有文件合并到新的单个文件中的任何想法都已删除。有关主要更改的详细信息,请参见:
您可以使用getmerge
用法:hadoop fs-getmerge[-nl]
将源目录和目标文件作为输入,并将src中的文件连接到目标本地文件中。(可选)可以将-nl设置为允许在每个文件的末尾添加换行符(LF)-“跳过空文件”可用于在出现空文件时避免不需要的换行符
示例:
hadoop fs -getmerge -nl /src /opt/output.txt
hadoop fs -getmerge -nl /src/file1.txt /src/file2.txt /output.txt
退出代码:
成功时返回0,错误时返回非零
我也有同样的问题,不得不重新实施copyMerge
(虽然在PySpark中,但使用与原始copyMerge相同的API调用)
我不知道为什么Hadoop 3中没有等效的功能。
我们必须经常将HDFS目录中的文件合并到HDFS文件中
下面是我在上面提到的pySpark中的实现
由于已被弃用并从API开始的第3版中删除,一个简单的解决方案是自己重新实现它
是以前版本的Java原始实现
下面是一个Scala重写:
导入scala.util.Try
导入org.apache.hadoop.conf.Configuration
导入org.apache.hadoop.fs.{文件系统,路径}
导入org.apache.hadoop.io.IOUtils
导入java.io.IOException
def copyMerge(
srcFS:FileSystem,srcDir:Path,
dstFS:FileSystem,dstFile:Path,
deleteSource:Boolean,conf:Configuration
):布尔={
如果(dstFS.exists(dstFile))
抛出新IOException(目标$dstFile已存在)
//源路径应为目录:
if(srcFS.getFileStatus(srcDir.isDirectory()){
val outputFile=dstFS.create(dstFile)
试一试{
srcFS
.listStatus(srcDir)
.sortBy(u.getPath.getName)
.收集{
如果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
}
否则错误
}
这应该行得通
/** 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;
}
/**将目录中的所有文件复制到一个输出文件(合并)*/
公共静态布尔copyMerge(文件系统srcFS,路径srcDir,
文件系统dstFS,路径dstFile,
布尔删除源,
配置配置,字符串addString)引发IOException{
dstFile=checkDest(srcDir.getName(),dstFS,dstFile,false);
如果(!srcFS.getFileStatus(srcDir.isDirectory())
返回false;
OutputStream out=dstFS.create(dstFile);
试一试{
FileStatus contents[]=srcFS.listStatus(srcDir);
数组。排序(内容);
for(int i=0;i
这种方法有效,但不适用于有效的庄园。这会将文件合并到我的本地目录,第一个目录有延迟,第二个目录要求我通过再次从本地计算机复制文件,将文件放回HDFS服务器。是否无法在HDFS服务器上进行合并并生成新文件?似乎没有直接的方法将多个文件合并为一个文件,而不必将新文件从LFS复制到HDFS。看看这个问题:那是我的恐惧。我想知道为什么在最新版本中删除了copyMerge。我想知道同样的原因。我认为这是一个非常有效的方法。同时,您可以编写java代码来实现同样的功能。“FileUtil#copyMerge目前在Hadoop源代码树中未使用。在branch-1中,它是Hadoop fs-getmerge shell命令实现的一部分。在branch-2中,该shell命令的代码已以不再需要此方法的方式重写。”感谢您提供答案!请包含一些文本来解释您的答案是如何工作的。如果您想使用finally-use-finally,您正在try monad中吞咽异常,但原始代码没有使异常静音