摘要:于是開始了長時間的排錯之旅。但是讀取的時候,出現問題一直報異常,而路徑并未出錯而且文件存在。由于錯誤定位在的構造函數中上,便重新寫了一個類測試類的類,發現完全沒有問題,不是這出的錯誤。查看類構造函數,其功能就是接受參數,調用的構造函數。
在實現《Hadoop高級編程》一書中第9章的一個例子:將HBase用于圖片管理系統中,遇到了一個很讓人頭疼的問題:FileNotFoundException。雖然異常很簡單,但是文件確實存在那了。于是開始了長時間的排錯之旅。
該例子是將一堆小圖片文件合成一個大文件,并將各個小文件的位置索引存入HBase中。有一個DatedPhoto類,用于存放時間(long)以及圖片(byte[]);還有一個PhotoLocation類,用于存放位置(long)、時間(long)和文件名(String)。位置是小文件在大文件中的字節位置,文件名是合成的大文件名,按序號命名。PhotoLocation類還提供了toBytes和fromBytes函數,用于將三種信息字節化后寫入HBase以及從HBase中讀出索引信息后還原成位置, 時間 和 文件名 信息。其余為寫入類,讀出類。整體非常簡單。
寫的時候完全沒有問題,文件成功生成,HBase中保存了索引。但是讀取的時候,出現問題:一直報FileNotFoundException異常,而路徑并未出錯而且文件存在。
這到底是怎么一回事呢?因為用的是SequenceFile中的內部類Reader和Writer,而Hadoop 2.2.0的API中并沒有找到這兩個東西,便從源碼入手看看是不是這個類的問題。按照執行流程過了一遍,任何問題都沒發現。由于錯誤定位在SequenceFile.Reader的構造函數中getFileStatus上,便重新寫了一個類測試FileSystem類的getFileStatus類,發現完全沒有問題,不是這出的錯誤。
PhotoDataReader類是輔助讀出數據的類,被PhotoReader類調用。錯誤就定位在了該類的構造上。查看PhotoDataReader類構造函數,其功能就是接受參數,調用SequenceFile.Reader的構造函數。輸出PhotoDataReader接收到的參數:file(String)、user(UUID)、conf(Configuration),三者都沒問題,但是出現了一個很奇怪的現象:
執行
System.out.println("file:"+ _file + "sadasdsasdssssss");
時,后面的那一串字符串居然不顯示!
看來問題就出現在_file參數上面。但是不管怎么輸出_file的值,的確就是我要的那個文件名的字符串。似乎這是個根本就不應該出現的問題。然后輸出_file的字符串長度,明明只有1個字符的文件名,顯示的長度為112!看來問題就在這!
問題究竟出現在哪呢?繼續向上找,發現參數是PhotoReader傳給它的;PhotoReader又通過讀取HBase中的索引記錄得到后用PhotoLocation的fromBytes函數得到…… fromBytes函數?其實現的是將一個包含索引位置 、時間 與 文件名的128位字符數組分開然后生成三個值。索引位置與時間均為long型,字符數組均為8位,沒有問題。但是文件名為字符串,合成字符數組時用的length函數,但是還原時就把除索引位置與時間的16位排除后剩下的112位全部用來生成字符串了!生成字符串用Bytes.bytes()和 new String均無法生成原長度的字符串。
既然知道了原因,解決也好辦了。要么設個長度位,要么用定長字符串,要么干脆在HBase分開存儲。看來,有時候報錯,問題往往出現在細節上,仔細思考每一處細節,可以減少很多的排錯時間。至少這次我花了不少時間。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64160.html
閱讀 1951·2021-09-07 10:24
閱讀 2087·2019-08-30 15:55
閱讀 2037·2019-08-30 15:43
閱讀 669·2019-08-29 15:25
閱讀 1044·2019-08-29 12:19
閱讀 1927·2019-08-23 18:32
閱讀 1515·2019-08-23 17:59
閱讀 947·2019-08-23 12:22