四):揭祕HDFSgithub
五):揭祕MapReduceapache
=====================================================服務器
一、分佈式存儲系統HDFS(Hadoop Distributed File System)分佈式存儲層網絡
二、資源管理系統YARN(Yet Another Resource Negotiator)集羣資源管理層數據結構
三、分佈式計算框架MapReduce分佈式計算層
單機模式是Hadoop的默認模式。當首次解壓Hadoop的源碼包時,Hadoop沒法瞭解硬件安裝環境,便保守地選擇了最小配置。
在這種默認模式下全部3個XML文件均爲空。當配置文件爲空時,Hadoop會徹底運行在本地。
由於不須要與其餘節點交互,單機模式就不使用HDFS,也不加載任何Hadoop的守護進程。該模式主要用於開發調試MapReduce程序的應用邏輯。
僞分佈模式在「單節點集羣」上運行Hadoop,其中全部的守護進程都運行在同一臺機器上。
該模式在單機模式之上增長了代碼調試功能,容許你檢查內存使用狀況,HDFS輸入輸出,以及其餘的守護進程交互。
5個進程的介紹http://www.aboutyun.com/thread-7088-1-1.html
Hadoop守護進程運行在一個集羣上。
評論:意思是說 master 上看到 namenode,jobtracer,secondarynamenode 能夠安裝在master節點,也能夠單獨安裝。
slave節點能看到 datanode 和 nodeManage
源於Google的GFS論文 發表於2003年10月 HDFS是GFS的克隆版!
什麼是GFS? 詳細參考地址
GFS是一個可擴展的分佈式文件系統,用於大型的、分佈式的、對大量數據進行訪問的應用。
它運行於廉價的普通硬件上,並提供容錯功能。
它能夠給大量的用戶提供整體性能較高的服務。
GFS 也就是 google File System,Google公司爲了存儲海量搜索數據而設計的專用文件系統。
HDFS(Hadoop Distributed File System,Hadoop 分佈式文件系統)是一個高度容錯性的系統,適合部署在廉價的機器上。
HDFS 能提供高吞吐量的數據訪問,適合那些有着超大數據集(largedata set)的應用程序。
核心:
NameNode:主機器上
DataNode:子機器上
SecondaryNameNode:(NameNode的快照)
能夠在master機器上也能夠是單獨一臺機器
HDFS是一個主從結構(master/slave),一個HDFS集羣由一個名字節點(NameNode)和多個數據節點(DataNode)組成。
這兩個文件和 VERSION 存在安裝目錄下的 hdfs/name/current 文件夾下:
#Mon Feb 06 23:54:55 CST 2017
namespaceID=457699475 #命名空間,hdfs格式化會改變命名空間id,當首次格式化的時候datanode和namenode會產生一個相同的namespaceID,
而後讀取數據就能夠,若是你從新執行格式化的時候,namenode的namespaceID改變了,
可是datanode的namespaceID沒有改變,兩邊就不一致了,若是從新啓動或進行讀寫hadoop就會掛掉。
解決方案:
一、推薦方式
hdfs namenode -format -force 進行強制的格式化會同時格式化 namenode 和 datanode
二、不推薦可是也能夠實現
進入每一個子機器,以後刪除HDFS和tmp文件! 刪除以前舊版本!
HDFS 認爲全部計算機均可能會出問題,爲了防止某個主機失效讀取不到該主機的塊文件,它將同一個文件塊副本分配到其它某幾個主機上,若是其中一臺主機失效,能夠迅速找另外一塊副本取文件。
副本存放策略:
數據自動保存多個節點;
備份丟失後,自動恢復。
很是適合上T B級別的大文件或者一堆大數據文件的存儲
HDFS 將一個完整的大文件平均分塊(一般每塊(block)128M)存儲到不一樣計算機上,這樣讀取文件能夠同時從多個主機取不一樣區塊的文件,多主機讀取比單主機讀取效率要高得多得多。
block的大小,咱們實際能夠本身控制!
在數據存儲的地方進行計算,而不是把數據拉取到計算的地方,下降了成本,提升了性能!
一次寫入,並行讀取。不支持動態改變文件內容,而是要求讓文件一次寫入就不作變化,要變化也只能在文件末添加內容。
水庫中全部的水能夠理解成一個批式數據!
水龍頭的水,是一股一股留下來的,咱們能夠理解成流式數據!
若是咱們要統計某個文件的數據,會有兩種方式:
一、把文件中全部的數據 讀取到內存中,以後再進行計算,這樣就有個延遲,由於咱們須要等待全部數據讀取完畢!
二、文件中的數據讀取一點,計算一點!這樣就沒有了延遲,並且還提高了數據的吞吐量!
客戶端在寫入時,爲保證最大吞吐量,客戶端會將數據先緩存到本地文件,當客戶端緩存的數據超過一個block大小時,會向NN申請建立block,將數據寫到block裏。
在往block的多個副本寫入數據時,HDFS採用流水線複製的方式,好比block的三個副本在A、B、C上,客戶端將數據推送給最近的A;
A收到數據後當即推送給B、B推送給C,等全部副本寫入成功後,向客戶端返回寫入成功,當文件全部的block都寫入成功後,客戶端向NS請求更新文件的元信息。
經過多副本提升可靠性,提供了容錯和恢復機制。
HDFS 能夠應用在普通PC 機上,這種機制可以讓一些公司用幾十臺廉價的計算機就能夠撐起一個大數據集羣。
小例子:
好比有一個100G的文件 須要存在HDFS中,那麼不可能存在一個節點上,由於存儲數據的這個節點一旦宕機,數據就會丟失!
那麼是否是能夠把這個100G的文件分幾份進行存儲!
好比:A節點存一份 B節點存一份 C節點存一份???
這樣每一個節點的壓力都比較大,由於100G的文件仍是比較大的,須要佔用很大的帶寬!(網絡IO)
這時候,HDFS就是採用了分塊存儲的方法!
把100G的這個文件分紅了不少塊,每一個塊是128M,以後把每一個塊存放在不一樣的節點上!
在咱們的主機上會有兩份記錄:
0一、一個存儲文件被分紅了幾塊
0二、這幾塊都在那些節點上
文件的真正存儲是在DataNode!子機器中!Master是管理者!
做用:
0一、它是一個管理文件的命名空間
0二、協調客戶端對文件的訪問
0三、記錄每一個文件數據在各個DataNode上的位置和副本信息
文件解析:
version :是一個properties文件,保存了HDFS的版本號。
editlog :任何對文件系統數據產生的操做,都會被保存!
fsimage /.md5:文件系統元數據的一個永久性的檢查點,包括數據塊到文件的映射、文件的屬性等。
seen_txid :很是重要,是存放事務相關信息的文件
HDFS是一個分佈式文件存儲系統,文件分佈式存儲在多個DataNode節點上。
問題?
0一、一個文件存儲在哪些DataNode節點?
0二、又存在DataNode節點的哪些位置?
這些描述了文件存儲的節點,以及具體位置的信息(元數據信息(metadata))由NameNode節點來處理。隨着存儲文件的增多,NameNode上存儲的信息也會愈來愈多。
0三、HDFS是如何及時更新這些metadata的呢?
FsImage 和 Editlog是HDFS 的核心數據結構。
這些文件的損壞會致使整個集羣的失效。
所以,名字節點能夠配置成支持多個 FsImage 和 EditLog 的副本。任何 FsImage 和 EditLog 的更新都會同步到每一份副本中。
0一、FsImage文件包含文件系統中全部的目錄和文件inode的序列化形式,每一個Inode是一個文件或目錄的元數據的內部表示,
幷包含此類信息:文件的複製等級、修改和訪問時間、訪問權限、塊大小以及組成文件的塊,對於目錄、則存儲修改時間、權限和配額元數據
0二、FsImage文件沒有記錄塊存儲在哪一個數據節點,而是由名稱節點把這些映射保留在內存中,當數據節點加入HDFS集羣中,數據節點會把本身所包含的塊列表告知名稱節點,此後會按期執行這種告知操做,以確保名稱節點的映射是最新的。
0一、在名稱節點運行期間,HDFS的全部更新操做都是直接到EditLog,一段時間以後,EditLog文件會變得很大
0二、雖然這對名稱節點運行時候沒有什麼明顯影響,可是,當名稱節點重啓時候,名稱節點須要先將FsImage裏面的全部內容映射到內存,而後一條一條地執行EditLog中的記錄,當EditLog文件很是大的時候,
會致使名稱節點啓動操做會很是的慢
節點進程存在於集羣的master上,也能夠是單獨一臺機器
做用:
一、NameNode的一個快照
二、週期性備份NameNode
三、記錄NameNode中的MateData以及其餘數據
四、能夠用來恢復NameNode,可是不能替換NameNode
工做原理:
執行流程:
0一、SecondaryNameNode節點會按期和NameNode通訊,請求其中止使用EditLog,暫時將新的寫操做到一個新的文件edit.new上來,這個操做是瞬間完成的。
0二、SecondaryNameNode 經過HTTP Get方式從NameNode上獲取到FsImage和EditLog文件並下載到本地目錄
0三、將下載下來的FsImage 和EditLog加載到內存中這個過程就是FsImage和EditLog的合併(checkpoint)
0四、合併成功以後,會經過post方式將新的FsImage文件發送NameNode上。
0五、Namenode 會將新接收到的FsImage替換掉舊的,同時將edit.new替換EditLog,這樣EditLog就會變小。
何時進行checkpoint由兩個參數dfs.namenode.checkpoint.preiod(默認值是3600,即1小時)和dfs.namenode.checkpoint.txns(默認值是1000000)來決定。
period參數表示,通過1小時就進行一次checkpoint,txns參數表示,hdfs通過100萬次操做後就要進行checkpoint了。
這兩個參數任意一個獲得知足,都會觸發checkpoint過程。進行checkpoint的節點每隔dfs.namenode.checkpoint.check.period(默認值是60)秒就會去統計一次hdfs的操做次數。
也能夠去core-site.xml文件中進行配置:
<property>
<name>fs.checkpoint.period</name>
<value>3600</value>
<description>The number of seconds between two periodic checkpoints. </description>
</property>
<property>
<name>fs.checkpoint.size</name>
<value>67108864</value>
<description>The size of the current edit log (in bytes) that triggers a periodic checkpoint even if the fs.checkpoint.period hasn't expired.
</description>
</property>
做用:
0一、真實數據的存儲管理
0二、一次寫入,並行讀取(不修改,僅支持append)
0三、文件由數據塊組成,Hadoop2.x的塊大小默認是128MB,能夠自由設置
0四、將數據塊儘可能散佈到各個節點
文件解析:
blk_<id>:HDFS的數據塊,保存具體的二進制數據
blk_<id>.meta:數據塊的屬性信息:版本信息、類型信息
能夠經過修改 hdfs-site.xml 的 dfs.replication 屬性設置產生副本的個數!默認是3!
寫入文件的流程:
例如:客戶端發送一個請求給NameNode,說它要將「zhou.log」文件寫入到HDFS。那麼,其執行流程如圖1所示。具體爲: HDFS寫 圖1 HDFS寫過程示意圖
第一步:
客戶端發消息給NameNode,說要將「zhou.log」文件寫入。(如圖1中的①)
第二步:
NameNode發消息給客戶端,叫客戶端寫到DataNode A、B和D,並直接聯繫DataNode B。(如圖1中的②)
第三步:
客戶端發消息給DataNode B,叫它保存一份「zhou.log」文件,而且發送一份副本給DataNode A和DataNode D。(如圖1中的③)
第四步:
DataNode B發消息給DataNode A,叫它保存一份「zhou.log」文件,而且發送一份副本給DataNode D。(如圖1中的④)
第五步:
DataNode A發消息給DataNode D,叫它保存一份「zhou.log」文件。(如圖1中的⑤)
第六步:
DataNode D發確認消息給DataNode A。(如圖1中的⑤)
第七步:
DataNode A發確認消息給DataNode B。(如圖1中的④)
第八步:
DataNode B發確認消息給客戶端,表示寫入完成。(如圖1中的⑥)
在分佈式文件系統的設計中,挑戰之一是如何確保數據的一致性。對於HDFS來講,直到全部要保存數據的DataNodes確認它們都有文件的副本時,數據才被認爲寫入完成。
所以,數據一致性是在寫的階段完成的。一個客戶端不管選擇從哪一個DataNode讀取,都將獲得相同的數據。
爲了理解讀的過程,能夠認爲一個文件是由存儲在DataNode上的數據塊組成的。
客戶端查看以前寫入的內容的執行流程如圖2所示,具體步驟爲:HDFS讀寫圖2 HDFS讀過程
示意圖:
第一步:
客戶端詢問NameNode它應該從哪裏讀取文件。(如圖2中的①)
第二步:
NameNode發送數據塊的信息給客戶端。(數據塊信息包含了保存着文件副本的DataNode的IP地址,以及DataNode在本地硬盤查找數據塊所須要的數據塊ID。) (如圖2中的②)
第三步:
客戶端檢查數據塊信息,聯繫相關的DataNode,請求數據塊。(如圖2中的③)
第四步:
DataNode返回文件內容給客戶端,而後關閉鏈接,完成讀操做。(如圖2中的④)
客戶端並行從不一樣的DataNode中獲取一個文件的數據塊,而後聯結這些數據塊,拼成完整的文件。
副本技術即分佈式數據複製技術,是分佈式計算的一個重要組成部分。該技術容許數據在多個服務器端共享,一個本地服務器能夠存取不一樣物理地點的遠程服務器上的數據,也可使全部的服務器均持有數據的拷貝。
一、提升系統可靠性:系統不可避免的會產生故障和錯誤,擁有多個副本的文件系統不會致使沒法訪問的狀況,從而提升了系統的可用性。另外,系統能夠經過其餘無缺的副本對發生錯誤的副本進行修復,從而提升了系統的容錯性。
二、負載均衡:副本能夠對系統的負載量進行擴展。多個副本存放在不一樣的服務器上,可有效的分擔工做量,從而將較大的工做量有效的分佈在不一樣的站點上。
三、提升訪問效率:將副本建立在訪問頻度較大的區域,即副本在訪問節點的附近,相應減少了其通訊開銷,從而提升了總體的訪問效率。
HDFS 的副本放置策略是:
第一個副本放在本地節點,
第二個副本放到不一樣機架上的一個節點,
第三個副本放到第二個副本同機架上的另一個節點。
若是還有其餘的副本,隨機分佈在集羣中的其餘節點!
=====
HDFS 運行在跨越大量機架的集羣之上。兩個不一樣機架上的節點是經過交換機實現通訊的,在大多數狀況下,相同機架上機器間的網絡帶寬優於在不一樣機架上的機器。
在開始的時候,每個數據節點自檢它所屬的機架 id,而後在向名字節點註冊的時候告知它的機架 id。
HDFS 提供接口以便很容易地掛載檢測機架標示的模塊。
一個簡單但不是最優的方式就是將副本放置在不一樣的機架上,這就防止了機架故障時數據的丟失,而且在讀數據的時候能夠充分利用不一樣機架的帶寬。
這個方式均勻地將複製分散在集羣中,這就簡單地實現了組建故障時的負載均衡。然而這種方式增長了寫的成本,由於寫的時候須要跨越多個機架傳輸文件塊。
通常狀況下複製因子(文件的副本數)爲 3。
HDFS 的副本放置策略是:
第一個副本放在本地節點,
第二個副本放到不一樣機架上的一個節點,
第三個副本放到第二個副本同機架上的另一個節點。
這種方式減小了機架間的寫流量,從而提升了寫的性能。機架故障的概率遠小於節點故障。這種方式並不影響數據可靠性和可用性的限制,而且它確實減小了讀操做的網絡聚合帶寬,由於文件塊僅存在兩個不一樣的機架,而不是三個。
文件的副本不是均勻地分佈在機架當中,1/3 副本在同一個節點上,1/3 副本在另外一個機架上,另外 1/3 副本均勻地分佈在其餘機架上。
這種方式提升了寫的性能,而且不影響數據的可靠性和讀性能。
Hadoop配置文件的管理類! 咱們以前在配置Hadoop集羣環境時,能夠看到全部xml文件的根節點都是configuration!
針對於hdfs中文件的一系列操做!好比:建立新文件,刪除文件,判斷文件是否存在,將本地文件copy到hdfs中等!
獲取文件或者文件夾的元信息!好比:文件路徑,文件大小,文件全部者,所在的塊大小,文件修改時間,備份數量,權限等!
輸入流對象! 能夠將hdfs中的文件或者文件夾讀取到本地!
輸出流對象! 能夠將本地的文件或者文件夾上傳到hdfs中!
一、建立項目,引入須要的jar或者pom文件
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.8.0</version>
</dependency>
二、獲取Configuration==》Hadoop配置文件的管理類!
三、獲取FileSystem ==》針對於hdfs中文件的一系列操做!
四、進行文件操做(讀寫、刪除、修改)
五、查詢HDFS指定目錄下文件
public static void main(String[] args) throws IOException { selectFromPath("/"); //查詢HDFS跟目錄下 全部文件
} /** * @param path 用戶須要查詢的HDFS中的目錄 * @throws IOException */
public static void selectFromPath(String path) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //實例化配置文件對象
Configuration config=new Configuration(); //建立文件系統對象 實現對文件的操做
FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //查詢 hdfs中根目錄下全部的文件
FileStatus[] status = fileSystem.listStatus(new Path(path)); for (FileStatus s:status){ System.out.println("====>"+s); } /* 獲取單個文件的信息 FileStatus status = fileSystem.getFileStatus(new Path(path)); System.out.println(status);*/ }
輸出內容對應的含義:
path=hdfs://master:9000/demo/demo.txt;文件位置
isDirectory=false; 是不是文件夾 length=111; 文件的大小 replication=2; 副本數量 blocksize=134217728; 所在塊大小 modification_time=1513047780762; 修改時間1970年到如今的毫秒數 access_time=1513047788225;最後一次訪問時間1970年到如今的毫秒數
owner=root; 文件擁有者 group=supergroup; 文件所屬組 permission=rw-r--r--; 文件的權限 isSymlink=false是不是鏈接
public static void main(String[] args) throws IOException { ceateFile("/demo.txt"); //用戶須要建立的文件名稱以及路徑
} /** * @param fileName 用戶須要建立的文件名稱 * @throws IOException */
public static void ceateFile(String fileName) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //實例化配置文件對象
Configuration config=new Configuration(); //建立文件系統對象 實現對文件的操做
FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //建立文件
boolean flag = fileSystem.createNewFile(new Path(fileName)); if (flag){ System.out.println("文件建立成功"); }else { System.out.println("文件建立失敗"); } }
可能出現的問題:
若是建立文件失敗且是權限問題:
Permission denied: user=root, access=WRITE, inode="/":hdfs:supergroup:drwxr-xr-x
解決方案:
01.hadoop fs -chmod 777 /
02.修改hdfs-site.xml 文件中的增長節點 <property>
<name>dfs.permissions</name>
<value>false</value>
</property>
public static void main(String[] args) throws IOException { mkdirFile("/demo"); //用戶須要建立的文件夾名稱以及路徑
} /** * @param fileName 用戶須要建立的文件夾名稱 * @throws IOException */
public static void mkdirFile(String fileName) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //實例化配置文件對象
Configuration config=new Configuration(); //建立文件系統對象 實現對文件的操做
FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //建立文件夾
boolean flag = fileSystem.mkdirs(new Path(fileName)); if (flag){ System.out.println("文件夾建立成功"); }else { System.out.println("文件夾建立失敗"); } }
public static void main(String[] args) throws IOException { renameFile("/demo","/demo2"); //重命名文件夾
renameFile("/demo.txt","/demo2.txt"); //重命名文件
} /** * @param oldName 用戶須要重命名的文件夾/文件名稱 * @param newName 用戶須要重命名的文件夾/文件名稱 * @throws IOException */
public static void renameFile(String oldName,String newName) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //實例化配置文件對象
Configuration config=new Configuration(); //建立文件系統對象 實現對文件的操做
FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //重命名文件夾
boolean flag = fileSystem.rename(new Path(oldName),new Path(newName)); if (flag){ System.out.println("重命名成功"); }else { System.out.println("重命名失敗"); } }
public static void main(String[] args) throws IOException { deleteFile("/demo2"); //刪除文件夾
deleteFile("/demo2.txt"); //刪除名文件
} /** * @param fileName 用戶須要刪除的文件夾/文件名稱 * @throws IOException */
public static void deleteFile(String fileName) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //實例化配置文件對象
Configuration config=new Configuration(); //建立文件系統對象 實現對文件的操做
FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //刪除文件夾/文件
boolean flag = fileSystem.deleteOnExit(new Path(fileName)); if (flag){ System.out.println("刪除成功"); }else { System.out.println("刪除失敗"); } }
public static void main(String[] args) throws IOException { uploadFile("D:/hadoop.txt","/hadoop.txt"); //上傳本地文件,也能夠更名
uploadFile("D:/hadoop","/hadoop"); //上傳本地文件夾,也能夠更名
} /** * @param localFile 用戶須要上傳的文件夾/文件名稱 * @param desFile 用戶須要上傳到HDFS中的文件夾/文件名稱 * @throws IOException */
public static void uploadFile(String localFile,String desFile) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //實例化配置文件對象
Configuration config=new Configuration(); //建立文件系統對象 實現對文件的操做
FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //上傳文件夾/文件
fileSystem.copyFromLocalFile(new Path(localFile),new Path(desFile)); //關閉流
fileSystem.close(); }
public static void main(String[] args) throws IOException { downloadFile("/hadoop.txt","D:/hadoop.txt"); //下載到本地,也能夠更名
downloadFile("/hadoop","D:/hadoop"); //下載到本地,也能夠更名
} /** * @param localFile 用戶須要下載到本地的文件夾/文件名稱 * @param hdfsFile 用戶須要下載的HDFS中的文件夾/文件名稱 * @throws IOException */
public static void downloadFile(String hdfsFile,String localFile) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //實例化配置文件對象
Configuration config=new Configuration(); //建立文件系統對象 實現對文件的操做
FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //下載文件夾/文件
fileSystem.copyToLocalFile(new Path(hdfsFile),new Path(localFile)); //關閉流
fileSystem.close(); }
下面的這種方式只能下載文件!不能下載文件夾!
public static void main(String[] args) throws IOException { downloadFile("/hadoop.txt","D:/hadoop.txt"); //下載到本地,也能夠更名
} /** * @param localFile 用戶須要下載到本地的文件名稱 * @param hdfsFile 用戶須要下載的HDFS中的文件名稱 * @throws IOException */
public static void downloadFile(String hdfsFile,String localFile) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //實例化配置文件對象
Configuration config=new Configuration(); //建立文件系統對象 實現對文件的操做
FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //建立輸入流對象
FSDataInputStream inputStream = fileSystem.open(new Path(hdfsFile)); //建立輸出流對象
OutputStream outputStream=new FileOutputStream(localFile); //下載文件 而且關閉流
IOUtils.copyBytes(inputStream,outputStream,1024,true);
public static void main(String[] args) throws IOException { readFile("/eclipsePut/file1.txt"); //須要讀取的文件路徑以及名稱
} /** * @param readFile 須要讀取的文件名稱 * @throws IOException */
public static void readFile(String readFile) throws IOException { String uri="hdfs://192.168.27.2:9000/"; //實例化配置文件對象
Configuration config=new Configuration(); //建立文件系統對象 實現對文件的操做
FileSystem fileSystem = FileSystem.get(URI.create(uri), config); //建立輸入流對象
FSDataInputStream inputStream = fileSystem.open(new Path(readFile)); //解決中文亂碼問題
BufferedReader br=new BufferedReader(new InputStreamReader(inputStream)); String line=""; while ((line=br.readLine())!=null){ System.out.println(line); } //關閉流
br.close(); inputStream.close(); fileSystem.close(); }