一、代碼實現
package com.xtd.hdfs
import java.io.File
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.{FileSystem, FileUtil, Path}
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
object HDFSUtils {
def main(args: Array[String]): Unit = {
val status = uploadFile("C:\\Users\\com\\Desktop\\測試數據\\","/test/file/","報銷單.docx")
if(status) println("上傳成功!") else println("上傳失敗")
}
/**
* 本地文件上傳到 hdfs
* @param localDirectory 本地目錄
* @param hdfsDirectory hdfs目錄
* @param fileName 文件名稱
* @return true:上傳成功 flase:上傳失敗
*/
def uploadFile(localDirectory:String,hdfsDirectory:String,fileName:String): Boolean = {
val configuration:Configuration = new Configuration()
val fileSystem:FileSystem = FileSystem.get(configuration)
val localFullPath = localDirectory+"/"+fileName
val hdfsFullPath = hdfsDirectory+"/"+fileName
val localPath = new Path(localFullPath)
val hdfspath = new Path(hdfsDirectory)
val hdfsfilepath = new Path(hdfsFullPath)
val status1 = new File(localFullPath).isFile
val status2 = fileSystem.isDirectory(hdfspath)
val status3 = fileSystem.exists(hdfsfilepath)
println(status1,status2,!status3)
// 本地文件存在,hdfs目錄存在,hdfs文件不存在(防止文件覆蓋)
if(status1 && status2 && !status3) {
fileSystem.copyFromLocalFile(false,false,localPath,hdfsfilepath)
return true
}
false
}
}
二、代碼說明
這裏做了三個判斷
status1:本地文件存在
status2:hdfs目錄存在
status3:hdfs文件不存在
查看源碼,刪除代碼就一個 copyFromLocalFile方法,爲啥寫這麼複雜呢??
public void copyFromLocalFile(boolean delSrc, boolean overwrite, Path src, Path dst) throws IOException {
Configuration conf = this.getConf();
FileUtil.copy(getLocal(conf), src, this, dst, delSrc, overwrite, conf);
}
原因一:FileSystem類 的 copyFromLocalFile方法沒有返回值,但是業務需要知道上傳狀態
原因二:copyFromLocalFile方法的 hdfs Path 可以寫上傳的目錄也可以寫成 目錄+文件名
但是,如果本來輸入的 hdfs是目錄,但是由於這個路徑不存在,copyFromLocalFile方法會把
最後一個目錄的當成文件的名稱當成文件名上傳至hdfs,文件名後綴沒了,而且容易造成混亂
三、運行效果
四、寫入文件
hadoop不推薦追加文件到hdfs,如果需要追加文件有兩個思路
1、先把內容追加到本地文件,再從本地上傳到 hdfs(大數據場景下推薦使用)
2、用集合或者String數組先把追加的緩存,最後再一次性追加到hdfs (小數據或系統內存大的場景下)
hadoop 默認關閉hdfs文件追加功能,開啓需要配置 hdfs-site.xml 文件
<property>
<name>dfs.support.append</name>
<value>true</value>
</property>
實現代碼
val configuration:Configuration = new Configuration()
val fileSystem:FileSystem = FileSystem.get(configuration)
val path:Path = new Path("xxx")
fileSystem.append(path)