《Hadoop MapReduce实战手册》一2.8 使用HDFS的Java API

简介:

本节书摘来异步社区《Hadoop MapReduce实战手册》一书中的第2章,第2.8节,作者: 【美】Srinath Perera , Thilina Gunarathne 译者: 杨卓荦 责编: 杨海玲,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.8 使用HDFS的Java API

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程序执行文件系统操作。

  1. 下面的示例程序会在HDFS中创建一个新文件,写一些文本内容到新建文件,并从HDFS中读回该文件:
importjava.io.IOException;

importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.fs.FSDataInputStream;
importorg.apache.hadoop.fs.FSDataOutputStream;
importorg.apache.hadoop.fs.FileSystem;
importorg.apache.hadoop.fs.Path;

public class HDFSJavaAPIDemo {

  public static void main(String[] args) throws IOException {
   Configuration conf = new Configuration();
   FileSystemfs = FileSystem.get(conf);
   System.out.println(fs.getUri());
   Path file = new Path("demo.txt");

   if (fs.exists(file)) {
   System.out.println("File exists.");
   } else {
    // Writing to file
    FSDataOutputStreamoutStream = fs.create(file);
    outStream.writeUTF("Welcome to HDFS Java API!!!");
    outStream.close();
   }

   // Reading from file
   FSDataInputStreaminStream = fs.open(file);
   String data = inStream.readUTF();
   System.out.println(data);
   inStream.close();

   fs.close();
 }
}
  1. 将上面的程序编译并打包成一个JAR包。解压本章提供的源码包,转到HDFS_Java_API文件夹,然后运行Ant构建即可。HDFSJavaAPI.jar文件将在build文件夹中被创建。
>cd HDFS_java_API
>ant

可以使用下面的Ant构建文件来编译上面的示例程序:

<project name="HDFSJavaAPI" default="compile" basedir=".">
  <property name="build" location="build"/>
  <property environment="env"/>

  <path id="hadoop-classpath">
   <filesetdir="${env.HADOOP_HOME}/lib">
     <include name="**/*.jar"/>
   </fileset>
   <filesetdir="${env.HADOOP_HOME}">
     <include name="**/*.jar"/>
   </fileset>
  </path>

  <target name="compile">
   <mkdirdir="${build}"/>
   <javacsrcdir="src" destdir="${build}">
     <classpathrefid="hadoop-classpath"/>
   </javac>
   <jar jarfile="HDFSJavaAPI.jar" basedir="${build}"/>
   </target>

  <target name="clean">
   <delete dir="${build}"/>
  </target>
</project>
  1. 可以在Hadoop上使用以下命令执行上述示例。使用hadoop脚本运行示例,可以确保它采用了当前配置的HDFS,并从Hadoop的类路径中加载了必要的依赖。
>bin/hadoop jar HDFSJavaAPI.jar HDFSJavaAPIDemo
hdfs://yourhost:9000

Welcome to HDFS Java API!!!

  1. 使用ls命令列出新创建的文件:
>/bin/hadoopfs -ls
Found 1 items
-rw-r--r-- 3 foosupergroup     20 2012-04-27 16:57 /user/
foo/demo.txt

工作原理
为了以编程方式与HDFS进行交互,首先需要得到当前配置文件系统的句柄。实例化一个Configuration对象,并获得一个Hadoop环境中的FileSystem句柄,它将指向当前环境的HDFS NameNode。有几种替代配置FileSystem对象的方法,将在本节的“更多参考”中的“配置文件系统对象”中讨论。

Configuration conf = new Configuration();
FileSystemfs = FileSystem.get(conf);

FileSystem.create(filePath)方法会在指定的路径创建一个新的文件,并提供一个到新创建的文件的FSDataOutputStream对象。FSDataOutputStream封装了java.io.DataOutputStream,并允许程序向文件中写入基本Java数据类型。如果该文件存在,FileSystem.Create()方法将覆盖该文件。在这个例子中,该文件将在HDFS中相对于用户的主目录进行创建,产生类似/user//demo.txt的路径。

Path file = new Path("demo.txt");
FSDataOutputStreamoutStream = fs.create(file);
outStream.writeUTF("Welcome to HDFS Java API!!!");
outStream.close();

FileSystem.open(filePath)打开给定文件的FSDataInputStream。FSDataInputStream封装了java.io.DataInputStream,允许程序从文件中读取基本Java数据类型。

FSDataInputStreaminStream = fs.open(file);
String data = inStream.readUTF();
System.out.println(data);
inStream.close();

更多参考
HDFS的Java API支持的文件系统操作比我们在上面的示例中用到的多得多。完整的API文档可以在
http://hadoop.apache.org/common/docs/current/api/org/apache/hadoop/fs/FileSystem.html找到。

配置文件系统对象
我们也可以在Hadoop的环境之外使用HDFS的Java API。当这样做时,必须显式配置HDFS的NameNode和端口。以下是几种进行该项配置的方法。

可以通过如下方式在获得FileSystem对象之前加载Configuration对象的配置文件。但需要确保将所有的Hadoop和依赖库都添加到类路径中。

Configuration conf = new Configuration(); 
  conf.addResource(new Path("..._/hadoop/conf/core-site.xml_"));
  conf.addResource(new Path("..._/hadoop/conf/hdfs-site.xml_"));

  FileSystemfileSystem = FileSystem.get(conf);

还可以通过如下方式指定NameNode和端口。将NAMENODE_HOSTNAME和PORT替换为HDFS安装的NameNode的主机名和端口。

Configuration conf = new Configuration();
  conf.set("fs.default.name", "hdfs://NAMENODE_HOSTNAME:PORT");
  FileSystemfileSystem = FileSystem.get(conf);

HDFS的文件系统API,是一种支持多个文件系统的抽象。如果上述程序无法找到有效的HDFS配置,它将会指向本地文件系统,而不是HDFS。可以通过如下方式使用getUri()函数识别FileSystem对象的当前文件系统。在使用正确的HDFS配置文件的情况下,会返回hdfs://your_namenode:port,在使用本地文件系统的情况下,则会返回file:///。

fileSystem.getUri();

获取文件的数据块列表
FileSystem对象的getFileBlockLocations()函数,可以用来获取存储在HDFS中的文件数据块的列表,同时也可以获取存储块的主机名和块的偏移量。如果计划使用Hadoop MapReduce之外的其他框架来执行文件数据的任何数据本地化操作,那么这些信息将会非常有用。

FileStatusfileStatus = fs.getFileStatus(file);
BlockLocation[] blocks = fs.getFileBlockLocations(
     fileStatus, 0, fileStatus.getLen());
相关文章
|
14天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
44 2
|
3月前
|
分布式计算 Java Hadoop
java使用hbase、hadoop报错举例
java使用hbase、hadoop报错举例
105 4
|
4月前
|
安全 Java API
告别繁琐编码,拥抱Java 8新特性:Stream API与Optional类助你高效编程,成就卓越开发者!
【8月更文挑战第29天】Java 8为开发者引入了多项新特性,其中Stream API和Optional类尤其值得关注。Stream API对集合操作进行了高级抽象,支持声明式的数据处理,避免了显式循环代码的编写;而Optional类则作为非空值的容器,有效减少了空指针异常的风险。通过几个实战示例,我们展示了如何利用Stream API进行过滤与转换操作,以及如何借助Optional类安全地处理可能为null的数据,从而使代码更加简洁和健壮。
117 0
|
29天前
|
Java API 数据处理
探索Java中的Lambda表达式与Stream API
【10月更文挑战第22天】 在Java编程中,Lambda表达式和Stream API是两个强大的功能,它们极大地简化了代码的编写和提高了开发效率。本文将深入探讨这两个概念的基本用法、优势以及在实际项目中的应用案例,帮助读者更好地理解和运用这些现代Java特性。
|
2月前
|
SQL 分布式计算 Java
Hadoop-11-MapReduce JOIN 操作的Java实现 Driver Mapper Reducer具体实现逻辑 模拟SQL进行联表操作
Hadoop-11-MapReduce JOIN 操作的Java实现 Driver Mapper Reducer具体实现逻辑 模拟SQL进行联表操作
35 3
|
2月前
|
分布式计算 资源调度 Hadoop
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
Hadoop-10-HDFS集群 Java实现MapReduce WordCount计算 Hadoop序列化 编写Mapper和Reducer和Driver 附带POM 详细代码 图文等内容
98 3
|
2月前
|
分布式计算 资源调度 Hadoop
大数据-01-基础环境搭建 超详细 Hadoop Java 环境变量 3节点云服务器 2C4G XML 集群配置 HDFS Yarn MapRedece
大数据-01-基础环境搭建 超详细 Hadoop Java 环境变量 3节点云服务器 2C4G XML 集群配置 HDFS Yarn MapRedece
81 4
|
2月前
|
分布式计算 Java 大数据
大数据-147 Apache Kudu 常用 Java API 增删改查
大数据-147 Apache Kudu 常用 Java API 增删改查
33 1
|
2月前
|
分布式计算 NoSQL Java
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
Hadoop-32 ZooKeeper 分布式锁问题 分布式锁Java实现 附带案例和实现思路代码
45 2
|
2月前
|
分布式计算 Java Hadoop
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
66 1