天天看點

Hadoop URL中讀取資料出錯:unknown protocol: hdfs

今天在學習如何從hadoop中讀取資料時,寫了一個簡單的方法,測試時,卻報以下錯誤:

Hadoop URL中讀取資料出錯:unknown protocol: hdfs

以下是讀取hadoop中檔案并寫入本地磁盤的代碼:

<a href="http://my.oschina.net/itblog/blog/337235#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

<code>package</code> <code>hdfs;</code>

<code>import</code> <code>java.io.bufferedreader;</code>

<code>import</code> <code>java.io.filewriter;</code>

<code>import</code> <code>java.io.inputstream;</code>

<code>import</code> <code>java.io.inputstreamreader;</code>

<code>import</code> <code>java.net.url;</code>

<code>import</code> <code>org.apache.hadoop.io.ioutils;</code>

<code>public</code> <code>class</code> <code>hdfs {</code>

<code>        </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) </code><code>throws</code> <code>exception {</code>

<code>        </code><code>inputstream inputstream = </code><code>null</code><code>;</code>

<code>        </code><code>filewriter writer = </code><code>null</code><code>;</code>

<code>        </code><code>try</code> <code>{</code>

<code>            </code><code>url url = </code><code>new</code> <code>url(</code><code>"hdfs://localhost:9000/input.txt"</code><code>);</code>

<code>            </code><code>inputstream = url.openstream();</code>

<code>            </code><code>writer = </code><code>new</code> <code>filewriter(</code><code>"/home/wxl/桌面/tmp.txt"</code><code>);</code>

<code>            </code><code>inputstreamreader reader = </code><code>new</code> <code>inputstreamreader(inputstream);</code>

<code>            </code><code>bufferedreader bufferedreader = </code><code>new</code> <code>bufferedreader(reader);</code>

<code>            </code><code>string line = </code><code>null</code><code>;</code>

<code>            </code><code>while</code><code>((line = bufferedreader.readline()) != </code><code>null</code><code>) {</code>

<code>                </code><code>writer.write(line);</code>

<code>            </code><code>}</code>

<code>        </code><code>} </code><code>finally</code> <code>{</code>

<code>            </code><code>ioutils.closestream(inputstream);</code>

<code>            </code><code>if</code><code>(writer != </code><code>null</code><code>) {</code>

<code>                </code><code>writer.close();</code>

<code>        </code><code>}</code>

<code>    </code><code>}</code>

<code>}</code>

幾經周折,在《hadoop權威指南》中找到這樣的結果:

    "there’s a little bit more work required to make java recognize hadoop’s hdfs url scheme. this is achieved by calling the seturlstreamhandlerfactory method on url with an instance of fsurlstreamhandlerfactory . this method can be called only once per jvm, so it is typically executed in a static block."

    意即:“讓java程式能夠識别hadoop的hdfs url方案還需要一些額外的工作,這裡采用的方法是通過fsurlstreamhandlerfactory執行個體調用url中的seturlstreamhandlerfactory方法。由于java虛拟機隻能調用一次上述方法,是以通常在靜态方法中調用上述方法。”

    于是,在類中加入靜态執行塊:

<code>static</code> <code>{</code>

<code>    </code><code>// this method can be called at most once in a given jvm.</code>

<code>    </code><code>url.seturlstreamhandlerfactory(</code><code>new</code> <code>fsurlstreamhandlerfactory());</code>

    是以代碼變成了下面這樣:

32

33

34

35

36

37

38

39

<code>import</code> <code>org.apache.hadoop.fs.fsurlstreamhandlerfactory;</code>

<code>    </code> 

<code>    </code><code>static</code> <code>{</code>

<code>        </code><code>// this method can be called at most once in a given jvm.</code>

<code>        </code><code>url.seturlstreamhandlerfactory(</code><code>new</code> <code>fsurlstreamhandlerfactory(););</code>

<code>    </code><code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) </code><code>throws</code> <code>exception {</code>

    ok,不再報錯,成功運作。