关于输入格式:hadoop中自带了许多的输入格式,其中有一个抽象类是FileInputFormat,所有操作文件的InputFormat类都是从这里继承功能和属性,当开启一个hadoop作业时,FileInputFormat会得到一个路径参数,这个路径包含了所需要处理的文件,FileInputFormat会读取目录中的所有文件,然后通过把这些文件拆分成一个或多个切片。可以通过Job对象setInputFormatClass方法来设置文件的输入格式。
FileInputFormat下面的子类与继承关系:
为什么要对输入文件进行切片:因为每一个切片可以分配一个MapTask并行处理。
从切片和K,V上来这两点来总结他们输入格式的特点:
-
TextInputFormat:他是默认的FileInputFormat的输入格式读取文件的行,每个文件单独切,而且是按照默认的块大小进行切分,K为行的字节偏移量,V是每一行的内容。
-
KeyValueTextInputFormat: 切片的形式没有改变与TextInputFormat一样,但是它的K是每一行分隔符前面的所有内容(分隔符默认为tab键),V是分隔符后面的内容。
-
NlineInputFormat: 按照你设置的行进行切分,假如一个文件有15行,你设置的每5行进行切片,那么你的切片数就为3,他的KV类型没有改变和TextInputFormat一样。
-
CombineTextInputFormat: 用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个MapTask处理。他的KV类型时也没有改变,和TextInputFormat一样。
CombineTextInputFormat的切片机制:
生成切片过程包括:虚拟存储过程和切片过程二部分。
(1)虚拟存储过程: 将输入目录下所有文件大小,依次和设置的setMaxInputSplitSize值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块;如果输入文件大于设置的最大值且小于两倍,那么将此文件划分为等大小的两块;当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)。
例如setMaxInputSplitSize值为4M,输入文件大小为8.02M,则先逻辑上分成一个4M。剩余的大小为4.02M,如果按照4M逻辑划分,就会出现0.02M的小的虚拟存储文件,所以将剩余的4.02M文件切分成(2.01M和2.01M)两个文件。
(2)切片过程:
(a)判断虚拟存储的文件大小是否大于setMaxInputSplitSize值,大于等于则单独形成一个切片。
(b)如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。
(c)测试举例:有4个小文件大小分别为1.7M、5.1M、3.4M以及6.8M这四个小文件,则虚拟存储之后形成6个文件块,大小分别为:
1.7M,(2.55M、2.55M),3.4M以及(3.4M、3.4M)
最终会形成3个切片,大小分别为:
(1.7+2.55)M,(2.55+3.4)M,(3.4+3.4)M