我正在开发基于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文件。
我有什么遗漏吗?
任何快速帮助将不胜感激。
此致 布佩希
答案 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**"))
}
如果这个重命名成功,根本原因确实处于竞争状态。