環境:hadoop-0.20.2
當透過 HDFS Thrift 用 PHP/Python 寫檔案再讀二進制檔案時,會無法順利開啟讀出的檔案。
似乎是因為 Thrift 有支援一種 Binrary 的型態但是 hdfs 的 read/write[1] 都是用 String 的型態所造成的,
而在 hdfs 的 issue 中[2]有看到類似的問題,內文回覆的 Stuart Smith 提到相關的問題,並提供對應修改過的檔案供下載,
我沒仔細看他附檔的內容與回應,但在最後兩篇回覆中他提到了,可以在 read/write 透過 base64 encode/decode 來避免這個問題,
且他附上修改過的函式原始碼,應該跟附檔內修改的地方一樣,並且要多 import base64 的 library ,
按照他的修改,並且重新編譯後,接著修改 client(php/python) 端,在 write 前先 base64_encode() ,read 時 base64_decode(),問題就解決了。
額外一提他附檔的 hdfs.Thrift 就是將 read/write api 參數改成 binary 格式,但在此透過base64 以後編碼解碼以後就可以不必自行編譯 thrift 的 client 檔案了…
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.EncoderException; /** * write to a file */ public boolean write(ThriftHandle tout, String encodedData) throws ThriftIOException { try { now = now(); HadoopThriftHandler.LOG.debug("write: " + tout.id); FSDataOutputStream out = (FSDataOutputStream)lookup(tout.id); Base64 base64 = new Base64(); byte[] tmp = null; tmp = (byte[])base64.decode( (byte[]) encodedData.getBytes("UTF-8") ); out.write(tmp, 0, tmp.length); HadoopThriftHandler.LOG.debug("wrote: " + tout.id); return true; } catch (IOException e) { throw new ThriftIOException(e.getMessage()); } } /** * read from a file */ public String read(ThriftHandle tout, long offset, int length) throws ThriftIOException { try { now = now(); HadoopThriftHandler.LOG.debug("read: " + tout.id + " offset: " + offset + " length: " + length); FSDataInputStream in = (FSDataInputStream)lookup(tout.id); if (in.getPos() != offset) { in.seek(offset); } byte[] tmp = new byte[length]; int numbytes = in.read(offset, tmp, 0, length); HadoopThriftHandler.LOG.debug("read done: " + tout.id); try { Base64 base64 = new Base64(); return new String( (byte[])base64.encode( (Object)tmp ), "UTF-8"); } catch( EncoderException e ) { e.printStackTrace(); System.exit(0); return ""; } } catch (IOException e) { throw new ThriftIOException(e.getMessage()); } }
參考資源:
- [1] hdfs ap source http://svn.apache.org/viewvc/hadoop/hdfs/trunk/src/contrib/thriftfs/if/hadoopfs.thrift?view=markup
- [2] hdfs-1169 https://issues.apache.org/jira/browse/HDFS-1169
😯 it is very helpful, but I am not sure what’s the use of hadoopfs.thrift, could u give me some clues? thanks.
你是想有些實際的參考程式嗎?
thrift api 還蠻好懂的,參考他定義的函式跟參數結構以後照著呼叫就好哩~
我有寫一個 php 的範例
http://mlwmlw.no-ip.org/2010/12/hadoop-0-21-0-ant-build-thrift-php/
你好,小弟我也想利用thrift透過php語法讀取HDFS上的東西
,可以麻煩你寄範例給我嗎?? 謝謝你。 🙂