博主上一篇博客分享了namenode和datanode的工做原理,本章節將繼前面的HDFS的java客戶端簡單API後深度講述HDFS流處理API。java
場景:博主前面的文章介紹過HDFS上存的大文件會成不一樣的塊存儲在不一樣的datanode節點上,對外提供統一的訪問視圖。可是,若是這個須要處理的文件總體特別大,咱們在mapreduce程序中若是每次都所有下載到本地在執行那會很是耗時耗空間;那麼,有沒有一種好的方式,能夠實現當前這個mapreduce任務處理的那個分片數據,就下載分片這一段的數據到本地進行處理。答案:HDFS流客戶端APInode
package com.empire.hadoop.hadoop_demo; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.URI; import org.apache.commons.io.IOUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.junit.Before; import org.junit.Test; /** * 用流的方式來操做hdfs上的文件 * 能夠實現讀取指定偏移量範圍的數據 * @author * */ public class HdfsStreamAccess { FileSystem fs = null; Configuration conf = null; @Before public void init() throws Exception{ conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://master:9000"); //客戶端去操做hdfs時,是有一個用戶身份的 //默認狀況下,hdfs客戶端api會從jvm中獲取一個參數來做爲本身的用戶身份:-DHADOOP_USER_NAME=hadoop //拿到一個文件系統操做的客戶端實例對象 /*fs = FileSystem.get(conf);*/ System.setProperty("hadoop.home.dir", "E:\\\\hadoop-2.9.1"); //能夠直接傳入 uri和用戶身份 //centos-aaron-h1爲namenode的主機名或者域名 fs = FileSystem.get(new URI("hdfs://centos-aaron-h1:9000"),conf,"hadoop"); //最後一個參數爲用戶名 } /** * 經過流的方式上傳文件到hdfs * @throws Exception */ @Test public void testUpload() throws Exception { FSDataOutputStream outputStream = fs.create(new Path("/angelababy.love"), true); FileInputStream inputStream = new FileInputStream("c:/angelababy.love"); IOUtils.copy(inputStream, outputStream); } /** * 經過流的方式獲取hdfs上數據 * @throws Exception */ @Test public void testDownLoad() throws Exception { FSDataInputStream inputStream = fs.open(new Path("/angelababy.love")); FileOutputStream outputStream = new FileOutputStream("d:/angelababy.love"); IOUtils.copy(inputStream, outputStream); } @Test public void testRandomAccess() throws Exception{ FSDataInputStream inputStream = fs.open(new Path("/angelababy.love")); inputStream.seek(12); FileOutputStream outputStream = new FileOutputStream("d:/angelababy.love.part2"); IOUtils.copy(inputStream, outputStream); } /** * 顯示hdfs上文件的內容 * @throws IOException * @throws IllegalArgumentException */ @Test public void testCat() throws IllegalArgumentException, IOException{ FSDataInputStream in = fs.open(new Path("/angelababy.love")); IOUtils.copy(in, System.out); //hadoop的IOUtils更容易實現文件偏移分片處理 // IOUtils.copyBytes(in, System.out, 1024); } }
前面的一些疑問總結:apache
hdfs dfsadmin -report 打印集羣的狀態,看到的內容至關準確 start-dfs.sh 若是namenode沒關,也不要緊
HDFS listFiles()爲什麼不直接反回List而是返回一個迭代器?由於若是listFiles參數傳遞的目錄中包含幾十億個文件,那List直接放客戶端內存,可能會讓客戶端吃不消;迭代器爲什麼就行呢,迭代器其實不是個集合,它只是取數據的一種方式,它並不存數據,只是提供給一個方法,讓你能夠經過next(),nexthas()方法獲取數據。centos
mapreduce相對於HDFS來講,實際上是一個HDFS客戶端的角色。api
最後寄語,以上是博主本次文章的所有內容,若是你們以爲博主的文章還不錯,請點贊;若是您對博主其它服務器大數據技術或者博主本人感興趣,請關注博主博客,而且歡迎隨時跟博主溝通交流。服務器