1. import java.io.IOException;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4.  
  5. import org.apache.hadoop.fs.BlockLocation;
  6. import org.apache.hadoop.fs.FileStatus;
  7. import org.apache.hadoop.fs.FileSystem;
  8. import org.apache.hadoop.fs.Path;
  9. import org.apache.hadoop.fs.PathFilter;
  10. import org.apache.hadoop.io.LongWritable;
  11. import org.apache.hadoop.io.Text;
  12. import org.apache.hadoop.mapreduce.InputFormat;
  13. import org.apache.hadoop.mapreduce.InputSplit;
  14. import org.apache.hadoop.mapreduce.JobContext;
  15. import org.apache.hadoop.mapreduce.RecordReader;
  16. import org.apache.hadoop.mapreduce.TaskAttemptContext;
  17. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  18. import org.apache.hadoop.mapreduce.lib.input.InvalidInputException;
  19. import org.apache.hadoop.mapreduce.lib.input.KeyValueTextInputFormat;
  20. import org.apache.hadoop.mapreduce.lib.input.LineRecordReader;
  21. //import org.apache.hadoop.mapreduce.lib.input.FileInputFormat.MultiPathFilter;
  22. import org.apache.hadoop.mapreduce.security.TokenCache;
  23.  
  24. import com.google.common.base.Charsets;
  25.  
  26. public class MyFileinput extends FileInputFormat<LongWritable, Text> {
  27.  
  28. private static final PathFilter hiddenFileFilter = new PathFilter() {
  29. public boolean accept(Path p) {
  30. String name = p.getName();
  31. return ((!(name.startsWith("_"))) && (!(name.startsWith("."))));
  32. }
  33. };
  34.  
  35. // 遍历文件列表, 过滤掉_ .开头的文件(可以自定义过滤)
  36. protected List<FileStatus> listStatus(JobContext job) throws IOException {
  37. System.out.println("*********************");
  38. List result = new ArrayList();
  39. Path[] dirs = getInputPaths(job);
  40. System.out.println("dirs" + dirs);
  41. System.out.println("dirs length = " + dirs.length);
  42. for(Path p: dirs){
  43. System.out.println("Path loop " + p);
  44. }
  45.  
  46. if (dirs.length == 0) {
  47. throw new IOException("No input paths specified in job");
  48. }
  49.  
  50. TokenCache.obtainTokensForNamenodes(job.getCredentials(), dirs,
  51. job.getConfiguration());
  52.  
  53. List errors = new ArrayList();
  54.  
  55. List filters = new ArrayList();
  56. filters.add(hiddenFileFilter);
  57. PathFilter jobFilter = getInputPathFilter(job);
  58. if (jobFilter != null) {
  59. filters.add(jobFilter);
  60. }
  61.  
  62. // 过滤函数,可以拓展
  63. PathFilter inputFilter = new MultiPathFilter(filters);
  64.  
  65. for (int i = 0; i < dirs.length; ++i) {
  66. Path p = dirs[i];
  67. FileSystem fs = p.getFileSystem(job.getConfiguration());
  68. FileStatus[] matches = fs.globStatus(p, inputFilter);
  69. System.out.println("matches=" + matches);
  70. for(FileStatus match: matches){
  71. System.out.println("loop matches" + match.getPath());
  72. }
  73.  
  74. if (matches == null)
  75. errors.add(new IOException("Input path does not exist: " + p));
  76. else if (matches.length == 0)
  77. errors.add(new IOException("Input Pattern " + p
  78. + " matches 0 files"));
  79. else {
  80. for (FileStatus globStat : matches) {
  81. System.out.println("globStat " + globStat);
  82. if (globStat.isDirectory())
  83. for (FileStatus stat : fs.listStatus(
  84. globStat.getPath(), inputFilter)) {
  85. result.add(stat);
  86. }
  87. else {
  88. result.add(globStat);
  89. }
  90. }
  91. }
  92. }
  93.  
  94. if (!(errors.isEmpty())) {
  95. throw new InvalidInputException(errors);
  96. }
  97. // LOG.info("Total input paths to process : " + result.size());
  98. return result;
  99. }
  100.  
  101. // 计算分片大小,返回一个分片列表
  102. public List<InputSplit> getSplits(JobContext job) throws IOException {
  103. long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));
  104. long maxSize = getMaxSplitSize(job);
  105.  
  106. System.out.print("minSize " + minSize);
  107. System.out.print("maxSize " + maxSize);
  108.  
  109. List splits = new ArrayList();
  110. // 获取输入目录下的文件列表(过滤文件)
  111. List<FileStatus> files = listStatus(job);
  112. for (FileStatus file : files) {
  113. Path path = file.getPath();
  114. long length = file.getLen();
  115. System.out.println("path: " + path+ " file len = " + length);
  116. if (length != 0L) {
  117. // 通过路径找到块列表
  118. FileSystem fs = path.getFileSystem(job.getConfiguration());
  119. BlockLocation[] blkLocations = fs.getFileBlockLocations(file,
  120. 0L, length);
  121.  
  122. if (isSplitable(job, path)) {
  123. long blockSize = file.getBlockSize();
  124. System.out.println("blockSize:" + blockSize);
  125. long splitSize = computeSplitSize(blockSize, minSize,
  126. maxSize);
  127. System.out.println("splitSize :" + splitSize);
  128.  
  129. long bytesRemaining = length;
  130. System.out.println("bytesRemaining :" + bytesRemaining);
  131.  
  132. System.out.println(bytesRemaining / splitSize);
  133. // 定义为1.1D, 为避免一个分片过小, 也需要启动一个MAP来运行
  134. // 最后剩余的文件大小只要不超过分片大小的1.1倍都会放入一个分片
  135. while (bytesRemaining / splitSize > 1.1D) {
  136. int blkIndex = getBlockIndex(blkLocations, length
  137. - bytesRemaining);
  138. System.out.println("blkIndex :" + blkIndex);
  139.  
  140. // 添加到分片分片列表
  141. splits.add(makeSplit(path, length - bytesRemaining,
  142. splitSize, blkLocations[blkIndex].getHosts()));
  143.  
  144. bytesRemaining -= splitSize;
  145. }
  146.  
  147. // 文件尾
  148. if (bytesRemaining != 0L) {
  149. Long remain = length - bytesRemaining;
  150. System.out.println("文件尾大小" + bytesRemaining);
  151. int blkIndex = getBlockIndex(blkLocations, length
  152. - bytesRemaining);
  153. splits.add(makeSplit(path, length - bytesRemaining,
  154. bytesRemaining,
  155. blkLocations[blkIndex].getHosts()));
  156. }
  157. } else {
  158. splits.add(makeSplit(path, 0L, length,
  159. blkLocations[0].getHosts()));
  160. }
  161. } else {
  162. // 测试文件大小为0, 也会启动一个map
  163. splits.add(makeSplit(path, 0L, length, new String[0]));
  164. }
  165. }
  166.  
  167. job.getConfiguration().setLong(
  168. "mapreduce.input.fileinputformat.numinputfiles", files.size());
  169. // LOG.debug("Total # of splits: " + splits.size());
  170. return splits;
  171. }
  172.  
  173. private static class MultiPathFilter implements PathFilter {
  174. private List<PathFilter> filters;
  175.  
  176. public MultiPathFilter(List<PathFilter> filters) {
  177. this.filters = filters;
  178. }
  179.  
  180. public boolean accept(Path path) {
  181. for (PathFilter filter : this.filters) {
  182. if (!(filter.accept(path))) {
  183. return false;
  184. }
  185. }
  186. return true;
  187. }
  188. }
  189.  
  190. // 文件内容读取, 默认按行读取
  191. @Override
  192. public RecordReader<LongWritable, Text> createRecordReader(
  193. InputSplit split, TaskAttemptContext context) {
  194. String delimiter = context.getConfiguration().get(
  195. "textinputformat.record.delimiter");
  196.  
  197. System.out.println("delimiter ==" + delimiter);
  198. // 默认为空
  199. byte[] recordDelimiterBytes = null;
  200. if (null != delimiter)
  201. recordDelimiterBytes = delimiter.getBytes(Charsets.UTF_8);
  202.  
  203. return new LineRecordReader(recordDelimiterBytes);
  204. }
  205. }

主要功能是计算分片和按照分片给MAP任务读取内容

public abstract class InputFormat<K, V> {
    public abstract List<InputSplit> getSplits(JobContext paramJobContext)
            throws IOException, InterruptedException;

public abstract RecordReader<K, V> createRecordReader(
            InputSplit paramInputSplit,
            TaskAttemptContext paramTaskAttemptContext) throws IOException,
            InterruptedException;
}

从顶层的派生类提供的接口差不多也能看出来。

最简单的Informat实现, 然后我们只要实现RecordReader就可以了

  1. import org.apache.hadoop.fs.Path;
  2. import org.apache.hadoop.io.LongWritable;
  3. import org.apache.hadoop.mapreduce.InputSplit;
  4. import org.apache.hadoop.mapreduce.JobContext;
  5. import org.apache.hadoop.mapreduce.RecordReader;
  6. import org.apache.hadoop.mapreduce.TaskAttemptContext;
  7. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
  8. import org.apache.hadoop.mapreduce.lib.input.LineRecordReader;
  9.  
  10. import com.google.common.base.Charsets;
  11.  
  12. public class MySimpleInformat<V> extends FileInputFormat<LongWritable, V>
  13. {
  14. protected boolean isSplitable(JobContext context, Path filename) {
  15. // 是否需要分片
  16. return false;
  17. }
  18.  
  19. @Override
  20. public RecordReader<LongWritable, V> createRecordReader(
  21. InputSplit split, TaskAttemptContext context) {
  22. String delimiter = context.getConfiguration().get(
  23. "textinputformat.record.delimiter");
  24.  
  25. System.out.println("delimiter ==" + delimiter);
  26. // 默认为空
  27. byte[] recordDelimiterBytes = null;
  28. if (null != delimiter)
  29. recordDelimiterBytes = delimiter.getBytes(Charsets.UTF_8);
  30.  
  31. return (RecordReader<LongWritable, V>) new LineRecordReader(recordDelimiterBytes);
  32. }
  33. }

继承FileInputFormat类来理解 FileInputFormat类的更多相关文章

  1. java 面向对象(三十八):反射(二) Class类的理解与获取Class的实例

    1.Class类的理解 1.类的加载过程:程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾).接着我们使用java.exe命令对某个字节码文件进行解释运行.相当于将某个 ...

  2. Java 访问限制符 在同一包中或在不同包中:使用类创建对象的权限 & 对象访问成员变量与方法的权限 & 继承的权限 & 深入理解protected权限

    一.实例成员与类成员 1. 当类的字节码被加载到内存, 类中类变量.类方法即被分配了相应内存空间.入口地址(所有对象共享). 2. 当该类创建对象后,类中实例变量被分配内存(不同对象的实例变量互不相同 ...

  3. 对C++类的继承和派生的理解

    C++中的继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承类似,例如儿子继承父亲的财产. 1.继承(Inheritance)可以理解为一个类从另一个类获取成员变量和成员函数的过程. ...

  4. Python之美[从菜鸟到高手]--深刻理解原类(metaclass)

    本来想自己写这篇文章的,可当我读了这篇文章http://blog.jobbole.com/21351/,我打消了这个念头,因为肯定写的没有人家的好,说的通俗易懂,面面俱到.就厚着面皮修改下格式,测试下 ...

  5. Java基础12:深入理解Class类和Object类

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  6. 对Java中properties类的理解

    转载于:https://www.cnblogs.com/bakari/p/3562244.html 一.Java Properties类 Java中有个比较重要的类Properties(Java.ut ...

  7. 对类的理解(c++)

    介绍目录: 1.类成员 1.1 成员函数 1.2 构造函数 1.2.1 对构造函数的理解 1.2.2成员初始化列表 1.2.3必须使用成员初始化列表的几种情况 1.2.4对于拷贝构造函数的参数是一个引 ...

  8. [转]深刻理解Python中的元类(metaclass)以及元类实现单例模式

    使用元类 深刻理解Python中的元类(metaclass)以及元类实现单例模式 在看一些框架源代码的过程中碰到很多元类的实例,看起来很吃力很晦涩:在看python cookbook中关于元类创建单例 ...

  9. 深刻理解Python中的元类(metaclass)以及元类实现单例模式

    在理解元类之前,你需要先掌握Python中的类.Python中类的概念借鉴于Smalltalk,这显得有些奇特.在大多数编程语言中,类就是一组用来描述如何生成一个对象的代码段.在Python中这一点仍 ...

随机推荐

  1. jmeter使用总结

    1.1 什么是 JMeter Apache JMeter 是 Apache 组织开发的基于 Java 的压力测试工具.用于对软件做压力测试,它最初被设计用于 Web 应用测试,但后来扩展到其他测试领域 ...

  2. selenium-webdriver(python) (十四) -- webdriver原理(转)

    之前看乙醇视频中提到,selenium 的ruby 实现有一个小后门,在代码中加上$DEBUG=1 ,再运行脚本的过程中,就可以看到客户端请求的信息与服务器端返回的数据:觉得这个功能很强大,可以帮助理 ...

  3. if else 选择机构 _多重if选择机构_if选择结构嵌套(综合练习题——code)

    import java.util.*; class If01{ public static void main(String[ ]args){ //练习1:假如张三参加Java考试,判断如果在95分以 ...

  4. PlayMaker Int的两个数进行比较 Int Compare

    Integer 1 和 Integer 2 进行比较,Integer 1 和  Integer 2 相等的时候 执行 ChangeToGreen; Integer 1 比  Integer 2 大的时 ...

  5. 对象池2(方法功能)Pools

    对象池Pools(主要调用方法功能) namespace kernal { public class Pools : MonoBehaviour { [HideInInspector] public ...

  6. 自定义Qt组件-通讯模块(P1)

    通讯模块Communicator 通讯模块是整个项目设计中位于最底层的模块,用于处理与串口或网络等设备的通讯,所有设备的通讯通过CommManager类完成,上层软件设计时需要根据comm模块(主要是 ...

  7. 高精度运算——java

    java大法 java的框架. import java.io.*; import java.util.*; import java.math.*; public class Main{ public ...

  8. 随机练习:C#实现维吉尼亚加密与解密(解密前提为已知密匙)

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. JavaSE之Java基础(1)

    1.为什么重写equals还要重写hashcode 首先equals与hashcode间的关系是这样的: 1.如果两个对象相同(即用equals比较返回true),那么它们的hashCode值一定要相 ...

  10. SSM环境下配置log4j输出sql和异常到控制台和本地日志文件中

    1.引入日志依赖包 <!--解决Spring使用slf4j输出日志与log4j冲突的问题--> <dependency> <groupId>org.slf4j< ...