今天在編寫hadoop程序的時候,用到了流的處理。關閉流的時候出現了問題:
代碼:
1 FSDataInputStream fsin = fs.open(new Path(filein)); 2 FSDataOutputStream fsout = fs.append(new Path(fileout)); 3 BufferedReader br = new BufferedReader(new InputStreamReader(fsin)); 4 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fsout)); 5 ... 6 br.close(); 7 fsin.close(); 8 bw.close(); 9 fsout.close();
異常:
1 [root@bigdata004 bigdata]# ./bigdataTimer.sh 2 INFO [main] com.sinosoft.bigdata.BigDataTimer.main(227) | -----Timer begin----- 3 INFO [main] com.sinosoft.bigdata.BigDataInit.<clinit>(70) | bigdata init ... 4 WARN [main] org.apache.hadoop.util.NativeCodeLoader.<clinit>(62) | Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 5 INFO [main] com.sinosoft.bigdata.BigDataTimer.mergeFile(66) | Finished appending file. 6 INFO [main] com.sinosoft.bigdata.BigDataTimer.mergeFile(68) | deleted the input data path. 7 INFO [main] com.sinosoft.bigdata.BigDataTimer.mergeFile(70) | create the input data path. 8 ERROR [main] org.apache.hadoop.hdfs.DFSClient.closeAllFilesBeingWritten(776) | Failed to close file /user/root/dayfileInput/dayfileIn 9 org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.hdfs.server.namenode.LeaseExpiredException): No lease on /user/root/dayfileInput/dayfileIn: File does not exist. Holder DFSClient_NONMAPREDUCE_-221972347_1 does not have any open files.
原因:關閉處理流br.close();之后,緊接着關閉了與之相關的fsin.close();的節點流。事實上,br.close();會調用fsin.close(); 因此重復關閉了2次fsin.close();最后拋出了異常。
回顧了一下流的知識:
按照流是否直接與特定的地方(如磁盤、內存、設備等)相連,分為節點流和處理流兩類。
- 節點流:可以從或向一個特定的地方(節點)讀寫數據。如FileReader.
- 處理流:是對一個已存在的流的連接和封裝,通過所封裝的流的功能調用實現數據讀寫。如BufferedReader.處理流的構造方法總是要帶一個其他的流對象做參數。一個流對象經過其他流的多次包裝,稱為流的鏈接。
JAVA常用的節點流:
- 文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件進行處理的節點流。
- 字符串 StringReader StringWriter 對字符串進行處理的節點流。
- 數 組 ByteArrayInputStream ByteArrayOutputStreamCharArrayReader CharArrayWriter 對數組進行處理的節點流(對應的不再是文件,而是內存中的一個數組)。
- 管 道 PipedInputStream PipedOutputStream PipedReaderPipedWriter對管道進行處理的節點流。
常用處理流(關閉處理流使用關閉里面的節點流)
- 緩沖流:BufferedInputStrean BufferedOutputStream BufferedReader BufferedWriter
---增加緩沖功能,避免頻繁讀寫硬盤。
- 轉換流:InputStreamReader OutputStreamReader實現字節流和字符流之間的轉換。
- 數據流 DataInputStream DataOutputStream 等-提供將基礎數據類型寫入到文件中,或者讀取出來.
流的關閉順序
- 一般情況下是:先打開的后關閉,后打開的先關閉
- 另一種情況:看依賴關系,如果流a依賴流b,應該先關閉流a,再關閉流b。例如,處理流a依賴節點流b,應該先關閉處理流a,再關閉節點流b
- 可以只關閉處理流,不用關閉節點流。處理流關閉的時候,會調用其處理的節點流的關閉方法。
注意:
- 如果將節點流關閉以后再關閉處理流,會拋出IO異常。
- 如果關閉了處理流,在關閉與之相關的節點流,也可能出現IO異常。(hadoop編程文件流操作中遇到了。)