摘要:于是开始了长时间的排错之旅。但是读取的时候,出现问题一直报异常,而路径并未出错而且文件存在。由于错误定位在的构造函数中上,便重新写了一个类测试类的类,发现完全没有问题,不是这出的错误。查看类构造函数,其功能就是接受参数,调用的构造函数。
在实现《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分开存储。看来,有时候报错,问题往往出现在细节上,仔细思考每一处细节,可以减少很多的排错时间。至少这次我花了不少时间。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/64160.html
阅读 1899·2021-09-07 10:24
阅读 2034·2019-08-30 15:55
阅读 1988·2019-08-30 15:43
阅读 640·2019-08-29 15:25
阅读 997·2019-08-29 12:19
阅读 1911·2019-08-23 18:32
阅读 1483·2019-08-23 17:59
阅读 931·2019-08-23 12:22