File Hadoop在Java中映射整个文件

File Hadoop在Java中映射整个文件,file,hadoop,split,mapper,File,Hadoop,Split,Mapper,我正在尝试在java中使用Hadoop来处理多个输入文件。目前我有两个文件,一个大的要处理,一个小的用作索引 我的问题是,在将大文件分发给每个映射程序时,我需要保持整个索引文件未被丢弃。Hadoop API提供了什么方法来实现这种功能 如果我没有正确地表达自己,这里有一个链接,指向一幅代表我正在努力实现的目标的图片: 更新: 按照Santiago提供的说明,我现在可以将Amazon S3中的一个文件(或URI)插入分布式缓存,如下所示: job.addCacheFile(new Path("s3

我正在尝试在java中使用Hadoop来处理多个输入文件。目前我有两个文件,一个大的要处理,一个小的用作索引

我的问题是,在将大文件分发给每个映射程序时,我需要保持整个索引文件未被丢弃。Hadoop API提供了什么方法来实现这种功能

如果我没有正确地表达自己,这里有一个链接,指向一幅代表我正在努力实现的目标的图片:

更新:

按照Santiago提供的说明,我现在可以将Amazon S3中的一个文件(或URI)插入分布式缓存,如下所示:

job.addCacheFile(new Path("s3://myBucket/input/index.txt").toUri());
但是,当映射程序尝试读取它时,会出现“未找到文件”异常,这对我来说似乎很奇怪。我已经检查了S3的位置,一切似乎都很好。我使用了其他S3位置来介绍输入和输出文件

错误(请注意s3:后面的单斜杠)

FileNotFoundException:s3:/myBucket/input/index.txt(没有这样的文件或目录)

以下是我用于从分布式缓存读取文件的代码:

URI[] cacheFile = output.getCacheFiles();
BufferedReader br = new BufferedReader(new FileReader(cacheFile[0].toString()));
while ((line = br.readLine()) != null) {
     //Do stuff        
}

我正在使用Amazon的EMR、S3和Hadoop的2.4.0版。

您可以将索引文件推送到分布式缓存,并在执行映射程序之前将其复制到节点


查看此图。

您可以将索引文件推送到分布式缓存,并在执行映射程序之前将其复制到节点


请参见此图。

如上所述,将索引文件添加到分布式缓存中,然后在映射器中访问该文件。在幕后。Hadoop框架将确保在执行任何任务之前将索引文件发送给所有任务跟踪器,并可供您处理。在这种情况下,数据只传输一次,将可用于与您的工作相关的所有任务

但是,与其在映射程序代码中将索引文件添加到分布式缓存中,不如让驱动程序代码实现ToolRunner接口并重写run方法。这提供了在提交作业时通过命令提示符将索引文件传递到分布式缓存的灵活性

如果使用的是ToolRunner,则可以在运行作业时直接从命令行将文件添加到分布式缓存中。无需先将文件复制到HDFS。使用-files选项添加文件

hadoop jar yourjarname.jar YourDriverClassName -files cachefile1, cachefile2, cachefile3, ...
您可以访问Mapper或Reducer代码中的文件,如下所示:

File f1 = new File("cachefile1");
File f2 = new File("cachefile2");
File f3 = new File("cachefile3");

如上所述,将索引文件添加到分布式缓存,然后在映射器中访问该文件。在幕后。Hadoop框架将确保在执行任何任务之前将索引文件发送给所有任务跟踪器,并可供您处理。在这种情况下,数据只传输一次,将可用于与您的工作相关的所有任务

但是,与其在映射程序代码中将索引文件添加到分布式缓存中,不如让驱动程序代码实现ToolRunner接口并重写run方法。这提供了在提交作业时通过命令提示符将索引文件传递到分布式缓存的灵活性

如果使用的是ToolRunner,则可以在运行作业时直接从命令行将文件添加到分布式缓存中。无需先将文件复制到HDFS。使用-files选项添加文件

hadoop jar yourjarname.jar YourDriverClassName -files cachefile1, cachefile2, cachefile3, ...
您可以访问Mapper或Reducer代码中的文件,如下所示:

File f1 = new File("cachefile1");
File f2 = new File("cachefile2");
File f3 = new File("cachefile3");

以下是帮助我解决问题的方法

因为我在S3中使用Amazon的EMR,所以我需要稍微修改一下语法,如下所述

必须添加系统从缓存读取文件时要使用的名称,如下所示:

URI[] cacheFile = output.getCacheFiles();
BufferedReader br = new BufferedReader(new FileReader(#the filename#));
while ((line = br.readLine()) != null) {
     //Do stuff        
}
addCacheFile(新URI(“s3://myBucket/input/index.txt”+“#index.txt”)

这样,程序就知道引入缓存的文件名为just index.txt。我还需要更改语法以从缓存中读取文件。不必读取存储在分布式缓存上的整个路径,只需使用文件名,如下所示:

URI[] cacheFile = output.getCacheFiles();
BufferedReader br = new BufferedReader(new FileReader(#the filename#));
while ((line = br.readLine()) != null) {
     //Do stuff        
}

以下是帮助我解决问题的方法

因为我在S3中使用Amazon的EMR,所以我需要稍微修改一下语法,如下所述

必须添加系统从缓存读取文件时要使用的名称,如下所示:

URI[] cacheFile = output.getCacheFiles();
BufferedReader br = new BufferedReader(new FileReader(#the filename#));
while ((line = br.readLine()) != null) {
     //Do stuff        
}
addCacheFile(新URI(“s3://myBucket/input/index.txt”+“#index.txt”)

这样,程序就知道引入缓存的文件名为just index.txt。我还需要更改语法以从缓存中读取文件。不必读取存储在分布式缓存上的整个路径,只需使用文件名,如下所示:

URI[] cacheFile = output.getCacheFiles();
BufferedReader br = new BufferedReader(new FileReader(#the filename#));
while ((line = br.readLine()) != null) {
     //Do stuff        
}

实际上,我正在使用amazon为Elastic MapReduce提供的SDK,所以我根本不使用命令行。不过,我很感激你的回答,我期待着你的回答。我实际上正在使用amazon为Elastic MapReduce提供的SDK,所以我根本不使用命令行。不过,我很感激你的回答,我期待着你的回答。嗨,我已经设法将文件的URI引入到分布式缓存中。但是,当我尝试从映射器中读取它时,会发生“未找到文件”异常。我正在AmazonEMR和S3上工作,目前正在使用新的HadoopAPI(2.4.0)。我已经检查了文件的位置,所有的东西似乎都准备好了(其他s3文件使用起来没有问题)。嗨,我已经设法将文件的URI引入到分布式缓存中。但是,当我尝试从映射器中读取它时,会发生“未找到文件”异常。我正在AmazonEMR和S3上工作,目前正在使用新的HadoopAPI(2.4.0)。我已经检查了文件的位置,一切似乎都准备就绪(其他s3文件已经使用,没有问题)。你修复了FileNotFoundException吗?是的,我的答案是他