讀取 HDFS 文件的正確方式
緣由
最近在寫一個MapReduce程序的時候,出現了讀取HDFS文件截斷的情況,代碼如下:
//fs : FileSystem InputStream in = null; byte[] b = new byte[1024 * 1024 * 64]; int len = 0; try { in = fs.open(new Path(fileName)); len = in.read(b); } catch (Exception e) { e.printStackTrace(); } finally { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } return new String(b, 0, len);
理論上,bytes數組大小已經設置為了64MB, 遠遠大于要讀取的文件,那為什么會出現這種情況呢?
一開始懷疑InputStream.read()方法導致截斷,果然,改成用BufferedReader讀取的方式就好用了。
BufferedReader reader = null; StringBuilder sb = new StringBuilder(); try { reader = new BufferedReader(new InputStreamReader(fs.open(new Path(fileName)))); String line = null; while((line = reader.readLine()) != null) { sb.append(line); } } catch (Exception ioe) { System.out.println(fileName + " does't exist!"); } finally { try { reader.close(); } catch (IOException e) { System.out.println("Reader close failed"); } } return sb.toString(); }
但真實的原因真的是這樣么?
分析
由上段代碼可知,InputStream.read()讀取的byte長度和期望值不同,我在 API Docs 中發現了這么一個定義
An attempt is made to read as many as len bytes, but a smaller number may be read.
也就是說,read()方法只是盡量的去讀stream,不保證讀取stream中全部的字節。類似的還有availabe()方法,這個方法 并不一定返回stream的大小,導致這些狀況的原因可能有以下幾點:
- 硬件上的buffersize比較小
- 網絡的IO比較慢
- 文件是分布式的,組合在一起時需要花費一些時間
最后關于解決方法,除了使用Reader一行一行讀以外,DataInputStream.readFully()方法也能避免這種問題。
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!