本节书摘来异步社区《hadoop mapreduce实战手册》一书中的第2章,第2.8节,作者: 【美】srinath perera , thilina gunarathne 译者: 杨卓荦 责编: 杨海玲,更多章节内容可以访问云栖社区“异步社区”公众号查看。
hadoop mapreduce实战手册
hdfs java api可用于任何java程序与hdfs交互。该api使我们能够从其他java程序中利用到存储在hdfs中的数据,也能够使用其他非hadoop的计算框架处理该数据。有时,可能也会遇到要直接从mapreduce应用程序中访问hdfs的用例。但是,如果你是在hdfs中直接通过map或reduce任务写入或修改文件,那么你要知道,这样做实际上违反了mapreduce构架的无副作用的本质,可能会导致某些用例出现数据一致性问题。
准备工作
设置hadoop_home环境变量指向hadoop的安装根目录。
操作步骤
下列步骤显示了如何使用hdfs的java api来对hdfs集群使用java程序执行文件系统操作。
下面的示例程序会在hdfs中创建一个新文件,写一些文本内容到新建文件,并从hdfs中读回该文件:
将上面的程序编译并打包成一个jar包。解压本章提供的源码包,转到hdfs_java_api文件夹,然后运行ant构建即可。hdfsjavaapi.jar文件将在build文件夹中被创建。
可以使用下面的ant构建文件来编译上面的示例程序:
可以在hadoop上使用以下命令执行上述示例。使用hadoop脚本运行示例,可以确保它采用了当前配置的hdfs,并从hadoop的类路径中加载了必要的依赖。
welcome to hdfs java api!!!
使用ls命令列出新创建的文件:
工作原理
为了以编程方式与hdfs进行交互,首先需要得到当前配置文件系统的句柄。实例化一个configuration对象,并获得一个hadoop环境中的filesystem句柄,它将指向当前环境的hdfs namenode。有几种替代配置filesystem对象的方法,将在本节的“更多参考”中的“配置文件系统对象”中讨论。
filesystem.create(filepath)方法会在指定的路径创建一个新的文件,并提供一个到新创建的文件的fsdataoutputstream对象。fsdataoutputstream封装了java.io.dataoutputstream,并允许程序向文件中写入基本java数据类型。如果该文件存在,filesystem.create()方法将覆盖该文件。在这个例子中,该文件将在hdfs中相对于用户的主目录进行创建,产生类似/user//demo.txt的路径。
filesystem.open(filepath)打开给定文件的fsdatainputstream。fsdatainputstream封装了java.io.datainputstream,允许程序从文件中读取基本java数据类型。
更多参考
hdfs的java api支持的文件系统操作比我们在上面的示例中用到的多得多。完整的api文档可以在
配置文件系统对象
我们也可以在hadoop的环境之外使用hdfs的java api。当这样做时,必须显式配置hdfs的namenode和端口。以下是几种进行该项配置的方法。
可以通过如下方式在获得filesystem对象之前加载configuration对象的配置文件。但需要确保将所有的hadoop和依赖库都添加到类路径中。
还可以通过如下方式指定namenode和端口。将namenode_hostname和port替换为hdfs安装的namenode的主机名和端口。
hdfs的文件系统api,是一种支持多个文件系统的抽象。如果上述程序无法找到有效的hdfs配置,它将会指向本地文件系统,而不是hdfs。可以通过如下方式使用geturi()函数识别filesystem对象的当前文件系统。在使用正确的hdfs配置文件的情况下,会返回hdfs://your_namenode:port,在使用本地文件系统的情况下,则会返回file:///。
获取文件的数据块列表
filesystem对象的getfileblocklocations()函数,可以用来获取存储在hdfs中的文件数据块的列表,同时也可以获取存储块的主机名和块的偏移量。如果计划使用hadoop mapreduce之外的其他框架来执行文件数据的任何数据本地化操作,那么这些信息将会非常有用。