2013-07-23 7 views
1

Je souhaite obtenir le chemin relatif à partir d'un chemin absolu, étant donné le chemin de base absolu. Y a-t-il une API Hadoop Java qui le fait?Hadoop obtient le chemin relatif du chemin absolu et du chemin de base

Par exemple, si mon chemin HDFS absolu est abs_path = hdfs://name-node/level1/level2/level3 et mon chemin de base absolue est abs_base_path = hdfs://name-node/level1, je voudrais extraire le chemin relatif de abs_path, qui serait rel_path = level2/level3. Je suis familier avec l'utilisation du constructeur de chemin pour combiner deux chemins.

Par exemple, si je le rel_path et abs_base_path, je peux utiliser un des constructeurs surchargées dans la classe Path http://hadoop.apache.org/docs/current/api/org/apache/hadoop/fs/Path pour construire abs_path mais je ne peux pas trouver une API pour faire l'inverse.

+0

La façon dont j'ai trouvé est de convertir abs_base_path et abs_path en String do abs_path_str.replace (abs_base_path_str, StringUtils.EMPTY). Je ne peux pas penser à une meilleure façon de le faire. –

Répondre

0

Que diriez-vous de construire une chaîne tout en récurant avec getParent() jusqu'à ce que le chemin actuel soit égal au chemin de base? Voici une fonction d'aide qui pourrait faire ce que vous voulez. (Je ne l'ai pas encore testé, mais l'idée pourrait aider)

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

Ceci est réellement fait dans le code source de FileOutputCommitter. La fonction correspondante est

/** 
    * 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; 
    } 
    } 

L'idée est de créer un URI pour le répertoire de base, puis créer un nouveau chemin d'accès pour cette nouvelle URI relativisée.

Espérons que ça aide.

Questions connexes