hadoop中的filesystem和localfilesystem
在這一節我們要深入了解Hadoop的FileSystem類——這是與與hadoop的文件系統交互的重要接口。雖然我們只是著重于HDFS的實現,但我們在編碼時一般也要注意代碼在FileSystem不同子類文件系統之間的可移植性。這是非常有用的,比如說你可以非常方便的直接用同樣的代碼在你的本地文件系統上進行測試。
使用hadoop URL讀數據
從hadoop文件系統中讀取文件的最簡單的方法之一便是使用java.net.URL對象來打開一個欲從中讀取數據的流(stream)。通常情況下的編程風格如下:
1 InputStream in = null; 2 try { 3 in = new URL("hdfs://host/path").openStream(); 4 // process in 5 } finally { 6 IOUtils.closeStream(in); 7 }想要使java識別出hdfs開頭的URL標示還需要一點其他的工作要做:通過URL的setURLStreamHandlerFactory()方法為java設置一個FSUrlStreamHandlerFactory。這個方法在每個JVM中只能調用一次,所以它通常會被放在一個static block中執行(如下所示),但如果你的某部分程序——例如一個你無法修改源代碼的第三方組件——已經調用了這個方法,那你就不能通過URL來這樣讀取數據了(下一節我們會介紹另一種方法)。
1 public class URLCat { 2 static { 3 URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()); 4 } 5 6 public static void main(String[] args) throws Exception{ 7 InputStream in = null; 8 try { 9 in = new URL(args[0]).openStream(); 10 IOUtils.copyBytes(in, System.out, 4096, false); 11 } finally { 12 // TODO: handle exception 13 IOUtils.closeStream(in); 14 } 15 } 16 }上例中我們使用了Hadoop中的IOUtils類的兩個靜態方法:?
1)IOUtils.copyBytes(),其中in表示拷貝源,System.out表示拷貝目的地(也就是要拷貝到標準輸出中去),4096表示用來拷貝的buffer大小,false表明拷貝完成后我們并不關閉拷貝源可拷貝目的地(因為System.out并不需要關閉,in可以在finally語句中被關閉)。?
2)IOUtils.closeStream(),用來關閉一個流。?
下面是我們的測試例子:
| % hadoop URLCat hdfs://localhost/user/tom/quangle.txt? On the top of the Crumpetty Tree? The Quangle Wangle sat,? But his face you could not see,? On account of his Beaver Hat. |
使用FileSystem讀取數據
就像上節所說的,有時候我們無法通過設置URLStreamHandlerFactory方法的方式來通過URL讀取數據,這時FIleSystem API就派上用場了。?
Hadoop文件系統中的文件是用Hadoop的Path對象來表示的(而不是java中的java.io.File對象,因為它的語義太接近于本地文件系統了)。你可以把一個Path對象看做Hadoop文件系統中的某一個URL,如上例中的“hdfs://localhost/user/tom/quangle.txt”。?
Filesystem是一個通用的文件系統API,所以使用它的第一步就是先抽取出它的一個實例出來——在這個例子中是HDFS。下面列出了幾個Filesystem的用于抽取Filesystem實例的幾個靜態方法:
| public static FileSystem get(Configuration conf) throws IOException? public static FileSystem get(URI uri, Configuration conf) throws IOException? public static FileSystem get(URI uri, Configuration conf, String user) throws IOException |
一個Configuration對象封裝了客戶端或服務器端的配置信息,這些配置信息是通過從conf/core-size.xml之類的配置文件中讀取出來的名值對來設置的。下面我們一一說明上面的三個方法:?
1)第一個方法返回一個默認的文件系統(在conf/core-site.xml中通過fs.default.name來指定的,如果在conf/core-site.xml中沒有設置則返回本地文件系統)。?
2)第二個方法通過uri來指定要返回的文件系統(例如,如果uri是上個測試例子中的hdfs://localhost/user/tom/quangle.txt,也即以hdfs標識開頭,那么就返回一個hdfs文件系統,如果uri中沒有相應的標識則返回本地文件系統)。?
3)第三個方法返回文件系統的機理同(2)是相同的,但它同時又限定了該文件系統的用戶,這在安全方面是很重要的。
有時候你可能想要使用一個本地文件系統,你可以使用另一個很方便的方法:?
public static LocalFileSystem getLocal(Configuration conf) throws IOException
得到一個文件系統的實例后,我們可以調用該實例的open()方法來打開某個給定文件的輸入流(第一個方法使用一個默認的4KB的輸入緩沖):
| public FSDataInputStream open(Path f) throws IOException? public abstract FSDataInputStream open(Path f, int bufferSize) throws IOException |
把上面介紹的組合起來我們就得到了下面的代碼:
1 public class FileSystemCat { 2 public static void main(String[] args) throws Exception { 3 String uri = args[0]; 4 Configuration configuration = new Configuration(); 5 FileSystem fs = FileSystem.get(URI.create(uri), configuration); 6 InputStream in = null; 7 try{ 8 in = fs.open(new Path(uri)); 9 IOUtils.copyBytes(in, System.out, 4096, false); 10 } finally { 11 IOUtils.closeStream(in); 12 } 13 } 14 }
?Hadoop LocalFileSystem是客戶端校驗的類。在使用LocalFileSystem寫文件時,會透明的創建一個.filename.crc的文件。校驗文件大小的字節數由io.bytes.per.checksum屬性設置,默認是512bytes,即每512字節就生成一個CRC-32校驗和。
? ? ? .filename.crc文件會存 io.bytes.per.checksum的信息。在讀取的時候,會根據此文件進行校驗。
? ? ? 事實上LocalFileSystem是通過繼承ChecksumFileSystem實現校驗的工作。
?
寫例子:
Java代碼 ?
總結
以上是生活随笔為你收集整理的hadoop中的filesystem和localfilesystem的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 地理数据库 (geodatabase)
- 下一篇: 自然语言处理-nltk学习(一)