假设客户端应用程序使用 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);
}
在一些场景中,比如 Hadoop
MapReduce LineRecordReader
班级。但是
FSDataInputStream seek()
方法显式地表示,在查找到某个位置之后,下一次读取将来自该位置,这意味着(?)上面的代码将有1个字节的偏移(?)。
所以,问题是,对于所有的inputspilt读取案例,“-1”调整是必要的吗?
顺便说一下,如果你想读一本 FileSplit
正确地说,仅仅寻找它的开始是不够的,因为每个分割也有一个可能与实际hdfs文件的结束不相同的结束。所以,相应的 InputStream
应为“有界”,即具有最大长度,如下所示:
InputStream is = new BoundedInputStream(fsin, split.getLength());
在这种情况下,在“本地人”之后 fsin
上面产生了蒸汽 org.apache.commons.io.input.BoundedInputStream
类来实现“边界”。
更新
显然,调整只对用例行中的一个用例是必要的 LineRecordReader
类,它超出了拆分的边界,以确保它读取完整的最后一行。
在前面的问题和mapreduce-772的评论中可以找到关于这一点的详细讨论。
1条答案
按热度按时间mbskvtky1#
查找位置0意味着下一次调用inputstream.read()将读取字节0。寻求位置-1很可能会引发异常。
在示例和源代码中讨论标准模式时,您具体指的是什么?
拆分不一定如您所注意的那样有边界-以textinputformat和可以拆分的文件为例。处理拆分的记录读取器将:
查找开始索引,然后查找下一个换行符
找到下一个换行符(或eof)并将该“行”作为下一条记录返回
重复此操作,直到找到的下一个换行符超过拆分的结尾,或者找到eof为止。在这种情况下,分裂的实际界限可能会从输入分裂的界限右移
更新
从linerecordreader引用此代码块:
这个
--start
语句最有可能处理的是避免从换行符开始拆分并返回一个空行作为第一条记录。您可以看到,如果发生查找,将跳过第一行,以确保文件拆分不会返回重叠的记录