2013-07-23 8 views
1

Я хочу получить относительный путь от абсолютного пути, учитывая абсолютный путь базы. Существует ли какой-либо Hadoop Java API, который это делает?Hadoop получить относительный путь от абсолютного пути и базового пути

Например, если мой абсолютный путь HDFS является abs_path = hdfs://name-node/level1/level2/level3 и мой абсолютный базовый путь abs_base_path = hdfs://name-node/level1, я хотел бы, чтобы извлечь относительный путь от abs_path, который будет rel_path = level2/level3. Я знаком с использованием конструктора путей для объединения двух путей.

Например, если у меня есть rel_path и abs_base_path, я могу использовать один из перегруженных конструкторов в классе Path http://hadoop.apache.org/docs/current/api/org/apache/hadoop/fs/Path построить abs_path, но я не могу найти API, чтобы сделать обратное.

+0

Способ, которым я пришел, состоит в том, чтобы преобразовать как abs_base_path, так и abs_path в String do abs_path_str.replace (abs_base_path_str, StringUtils.EMPTY). Не могу придумать лучшего способа сделать это. –

ответ

0

Как насчет создания строки при рекурсии с getParent(), пока текущий путь не будет равен базовому пути? Вот вспомогательная функция, которая может делать то, что вы хотите. (Я не проверял еще, но идея может помочь)

private static String absolutePathToRelativeString(final Path path, final Path base) { 
    final StringBuilder builder = new StringBuilder(path.toString().length()); 
    Path curPath = new Path(path); 
    while (curPath != null && curPath.depth() != 0 && !curPath.equals(base)) { 
     if (!curPath.equals(path)) { 
      builder.append('/'); 
     } 
     builder.insert(0, curPath.getName()); 
     curPath = curPath.getParent(); 
    } 
    return builder.toString(); 
} 
2

На самом деле это сделано в исходном коде FileOutputCommitter «s. Соответствующая функция

/** 
    * Find the final name of a given output file, given the job output directory 
    * and the work directory. 
    * @param jobOutputDir the job's output directory 
    * @param taskOutput the specific task output file 
    * @param taskOutputPath the job's work directory 
    * @return the final path for the specific output file 
    * @throws IOException 
    */ 
    private Path getFinalPath(Path jobOutputDir, Path taskOutput, 
          Path taskOutputPath) throws IOException { 
    URI taskOutputUri = taskOutput.toUri(); 
    URI relativePath = taskOutputPath.toUri().relativize(taskOutputUri); 
    if (taskOutputUri == relativePath) { 
     throw new IOException("Can not get the relative path: base = " + 
      taskOutputPath + " child = " + taskOutput); 
    } 
    if (relativePath.getPath().length() > 0) { 
     return new Path(jobOutputDir, relativePath.getPath()); 
    } else { 
     return jobOutputDir; 
    } 
    } 

Идея заключается в том, чтобы создать URI для базового каталога, а затем создать новый путь для этого нового, релятивизованной URI.

Надеюсь, что это поможет.

Смежные вопросы