由於hadoop擅長存儲大文件,因為大文件的元數據信息比較少,如果hadoop集群當中有大量的小文件,那么每個小文件都需要維護一份元數據信息,會大大的增加集群管理元數據的內存壓力,所以在實際工作當中,如果有必要一定要將小文件合並成大文件進行一起處理。
在我們的hdfs 的shell命令模式下,可以通過命令行將很多的hdfs文件合並成一個大文件下載到本地,命令如下:
例如合並文件存放到/export/servers下
cd /export/servers
hdfs dfs -getmerge /config/*.xml ./bigfile.xml
既然可以在下載的時候將這些小文件合並成一個大文件一起下載,那么肯定就可以在上傳的時候將小文件合並到一個大文件里面去,一般采用兩種策略
1.在文件上傳到hdfs之前進行小文件的合並(適用於同一類數據的情況)
2.在hdfs上通過mpareduce進行小文件的合並
代碼如下:
/**
* 將多個本地系統文件,上傳到hdfs,並合並成一個大的文件
* @throws Exception
*/
@Test
public void mergeFile() throws Exception{
//獲取分布式文件系統
FileSystem fileSystem = FileSystem.get(new URI("hdfs://192.168.52.100:8020"), new Configuration(),"root");
FSDataOutputStream outputStream = fileSystem.create(new Path("/bigfile.xml"));
//獲取本地文件系統
LocalFileSystem local = FileSystem.getLocal(new Configuration());
//通過本地文件系統獲取文件列表,為一個集合
FileStatus[] fileStatuses = local.listStatus(new Path("file:///F:\\上傳小文件合並"));
for (FileStatus fileStatus : fileStatuses) {
FSDataInputStream inputStream = local.open(fileStatus.getPath());
IOUtils.copy(inputStream,outputStream);
IOUtils.closeQuietly(inputStream);
}
IOUtils.closeQuietly(outputStream);
local.close();
fileSystem.close();
}