讀取 HDFS 文件的正確方式

jopen 9年前發布 | 28K 次閱讀 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的大小,導致這些狀況的原因可能有以下幾點:

  1. 硬件上的buffersize比較小
  2. 網絡的IO比較慢
  3. 文件是分布式的,組合在一起時需要花費一些時間

最后關于解決方法,除了使用Reader一行一行讀以外,DataInputStream.readFully()方法也能避免這種問題。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!