如何从列举的HDFS文件中获取相对于源目录的相对路径?
你可以直接使用 Hadoop Path 内置的 relativize 方法计算相对路径,无需手动处理字符串切割、协议前缀等问题,实现方式如下:
完整可运行代码示例
FileSystem fs = ...; // 待复制文件所在的远程目录 org.apache.hadoop.fs.Path sourceRoot = new Path("/path/to/the/directory"); // 转换为带HDFS协议、NameNode地址的全路径,避免相对路径导致的计算偏差 sourceRoot = fs.makeQualified(sourceRoot); // 复制到的目标本地目录 java.nio.file.Path targetRoot = ...; for (LocatedFileStatus status : fs.listFiles(sourceRoot, true)) { org.apache.hadoop.fs.Path fullFilePath = status.getPath(); // 直接计算相对于源目录的相对路径 org.apache.hadoop.fs.Path relativeHadoopPath = sourceRoot.relativize(fullFilePath); // 转换为Java NIO Path格式,用于本地目录操作 java.nio.file.Path relativeLocalPath = java.nio.file.Paths.get(relativeHadoopPath.toUri().getPath()); // 拼接本地目标路径 java.nio.file.Path targetFilePath = targetRoot.resolve(relativeLocalPath); // 自动创建父级目录 Files.createDirectories(targetFilePath.getParent()); // 后续执行文件流复制逻辑即可 try (InputStream in = fs.open(fullFilePath); OutputStream out = Files.newOutputStream(targetFilePath)) { byte[] buf = new byte[4096]; int readLen; while ((readLen = in.read(buf)) != -1) { out.write(buf, 0, readLen); } } }
低版本Hadoop兼容方案
如果你使用的Hadoop版本低于2.1.0,没有内置relativize方法,可以使用字符串切割的方式实现:
// 提前计算源目录的字符串长度 int sourcePathLen = sourceRoot.toString().length(); for (LocatedFileStatus status : fs.listFiles(sourceRoot, true)) { String fullPathStr = status.getPath().toString(); // 切割出相对路径,+1是为了跳过源路径末尾的斜杠 String relativePathStr = fullPathStr.substring(sourcePathLen + 1); java.nio.file.Path relativeLocalPath = Paths.get(relativePathStr); // 后续目录创建、复制逻辑和上面一致 }
内容的提问来源于stack exchange,提问作者Jin Kwon
相关产品推荐
相关产品推荐

