fs.rename(新路径(rawFileName),新路径(processFileName))无法正常工作

时间:2017-08-02 11:04:55

标签: hadoop apache-spark spark-dataframe hadoop2 hadoop-partitioning

我正在开发基于Scala的Apache Spark实现,用于从远程位置到HDFS的数据入门,然后从HDFS到Hive表的数据摄取。

使用我的第一个火花作业,我已经将数据/文件加入到位于HDFS的位置 -

  

hdfs://sandbox.hortonworks.com:8020 / data / analytics / raw / folder

让我们考虑一下,在登录CT_Click_Basic.csv和CT_Click_Basic1.csv.gz文件后,我在HDFS中有以下文件[共享位置的文件名将是这里的文件夹名称,其内容将出现在part-xxxxx文件中]:< / p>

  

[root @ sandbox~] #hdfs dfs -ls / data / analytics / raw / * /   找到3项

     

-rw-r - r-- 3 chauhan.bhupesh hdfs 0 2017-07-27 15:02 /data/analytics/raw/CT_Click_Basic.csv/_SUCCESS

     

-rw-r - r-- 3 chauhan.bhupesh hdfs 8383 2017-07-27 15:02 /data/analytics/raw/CT_Click_Basic.csv/part-00000

     

-rw-r - r-- 3 chauhan.bhupesh hdfs 8395 2017-07-27 15:02 /data/analytics/raw/CT_Click_Basic.csv/part-00001

     

找到2项

     

-rw-r - r-- 3 chauhan.bhupesh hdfs 0 2017-07-27 15:02 /data/analytics/raw/CT_Click_Basic1.csv.gz/_SUCCESS

     

-rw-r - r-- 3 chauhan.bhupesh hdfs 16588 2017-07-27 15:02 /data/analytics/raw/CT_Click_Basic1.csv.gz/part-00000

现在使用我的另一个Spark Job,我想将这些文件从 / raw 文件夹移动到 / process ,最后移到 / archive < / strong> HDFS中的文件夹,基于每个阶段执行的任务。

为此,我首先使用以下代码获取 / raw 文件夹下的所有文件列表:

    def listAllFilesFolderInDir(filePath:String,recursiveTraverse:Boolean,filePaths: ListBuffer[Path]) : ListBuffer[Path] = {
val files = GlobalContext.hdfs.listStatus(new Path(filePath))
files.foreach { fileStatus => {
           if(!fileStatus.isDirectory()) {
                filePaths+=fileStatus.getPath()      
            }
            else {
                listAllFilesFolderInDir(fileStatus.getPath().toString(), recursiveTraverse, filePaths)
            }
        }
  }   
  filePaths
}

然后使用以下代码行,我试图将/ raw文件夹中的文件重命名/移动到/ process文件夹:

var inputDir = "/data/analytics/raw"
var outputDir = "/data/analytics/process"
var filePaths = new ListBuffer[Path]()
var pathArray = listAllFilesFolderInDir(inputDir, true, filePaths)
val fs= <Getting hdfs FileSystem Instance Here>
for(path<-pathArray){
   var pathSplit = path.toString().split("/")
   var pathSplitSize = pathSplit.size
   val rawFileName = inputDir + "/" + pathSplit(pathSplitSize-2) + "/" + pathSplit(pathSplitSize-1)
   val processFileName = outputDir + "/" + pathSplit(pathSplitSize-2) + "/" + pathSplit(pathSplitSize-1)
   fs.rename(new Path(rawFileName), new Path(processFileName))
 }

但是我无法使用上面编写的代码移动/重命名这些文件。我尝试调试代码,发现fs.rename()正在返回“false”。

  

请注意:当我在/ data / analytics / raw文件夹ex CT.csv [或任何其他文件]中手动复制任何文件时,我能够实现文件重命名/移动   然后运行fs.rename()但它不适用于Part-xxxxx文件。

我有什么遗漏吗?

任何快速帮助将不胜感激。

此致 布佩希

2 个答案:

答案 0 :(得分:2)

最后,我遇到了这个问题。实际上我试图将文件从/data/analytics/raw/folder.csv/part-xxxxx重命名为/data/analytics/process/folder.csv/part-xxxxx,其中/ data / analytics / process存在于HDFS中,但是“ folder.csv“不存在;因此在重命名时它会让我失意。我在我的代码中添加了以下行,并为我工作正常

var inputDir = "/data/analytics/raw"
var outputDir = "/data/analytics/process"
var filePaths = new ListBuffer[Path]()
var pathArray = listAllFilesFolderInDir(inputDir, true, filePaths)
val fs= <Getting hdfs FileSystem Instance Here>
for(path<-pathArray){
   var pathSplit = path.toString().split("/")
   var pathSplitSize = pathSplit.size

   val rawFileName = inputDir + "/" + pathSplit(pathSplitSize-2) + "/" + pathSplit(pathSplitSize-1)

   var processFolderName = outputDir + "/" + pathSplit(pathSplitSize-2)
   var processFolderPath = new Path(processFolderName)
   if(!(fs.exists(processFolderPath)))
         fs.mkdirs(processFolderPath)
   val processFileName = processFolderName + "/" + pathSplit(pathSplitSize-1)
   fs.rename(new Path(rawFileName), new Path(processFileName))
 }

答案 1 :(得分:0)

如果新的Path(rawFileName)不存在,则重命名可以返回false 在fs.rename之前检查文件是否存在:

if (fs.exists(somePath)) {
 fs.rename...
}

另一个原因可能是您尝试重命名的文件被某人使用。或者,如果您尝试重命名目录,则某人可以使用其中的某些文件 要确保这是根本原因,请尝试重命名代码中的其他文件:

var inputDir = "/data/analytics/raw"
var outputDir = "/data/analytics/process"
var filePaths = new ListBuffer[Path]()
var pathArray = listAllFilesFolderInDir(inputDir, true, filePaths)
val fs= <Getting hdfs FileSystem Instance Here>
for(path<-pathArray){
   var pathSplit = path.toString().split("/")
   var pathSplitSize = pathSplit.size
   val rawFileName = inputDir + "/" + pathSplit(pathSplitSize-2) + "/" + pathSplit(pathSplitSize-1)
   val processFileName = outputDir + "/" + pathSplit(pathSplitSize-2) + "/" + pathSplit(pathSplitSize-1)
   fs.rename(new Path("**/TESTDIR1**"), new Path("**/TESTDIR2**"))
 }

如果这个重命名成功,根本原因确实处于竞争状态。