假设一个客户端应用程序使用一个FileSplit
对象来从相应的文件中读取实际字节。
为此,必须通过以下代码InputStream
从 中创建一个对象:FileSplit
FileSplit split = ... // The FileSplit reference
FileSystem fs = ... // The HDFS reference
FSDataInputStream fsin = fs.open(split.getPath());
long start = split.getStart()-1; // Byte before the first
if (start >= 0)
{
fsin.seek(start);
}
在某些场景中,例如类,会出现将流调整为 -1 的情况Hadoop
MapReduce
LineRecordReader
。但是,该FSDataInputStream
seek()
方法的文档明确指出,在寻找到一个位置之后,下一次读取将来自该位置,这意味着(?)上面的代码将是 1 个字节(?)。
所以,问题是,对于所有 InputSplit 阅读案例是否需要“-1”调整?
顺便说一句,如果想要FileSplit
正确读取一个文件,仅寻找它的开头是不够的,因为每个拆分也有一个结尾,可能与实际 HDFS 文件的结尾不同。因此,对应的InputStream
应该是“有界的”,即具有最大长度,如下所示:
InputStream is = new BoundedInputStream(fsin, split.getLength());
fsin
在这种情况下,在上面创建了“本机”流之后,使用org.apache.commons.io.input.BoundedInputStream
该类来实现“边界”。
更新
显然,仅当用例排在该类中时才需要进行调整LineRecordReader
,这超出了拆分的边界,以确保它读取完整的最后一行。
可以在较早的问题和MAPREDUCE-772的评论中找到有关此问题的详细讨论。