Hadoop大数据技术开发实战
上QQ阅读APP看书,第一时间看更新

4.4.1 读取数据

FileSystem是HDFS Java API的核心工具类,该类是一个抽象类,其中封装了很多操作文件的方法,使用这些方法可以很轻松地操作HDFS中的文件。例如,在HDFS文件系统的根目录下有一个文件file.txt,可以直接使用FileSystem API读取该文件内容,具体操作步骤如下。

1. 编写程序

在新建的hdfs_demo项目中新建Java类FileSystemCat.java,写入查询显示HDFS中的/file.txt文件内容的代码,代码编写步骤如下:

 创建Configuration对象。

 得到FileSystem对象。

 进行文件操作。完整代码如下所示:

代码分析:

❶ 在运行HDFS程序之前,需要先初始化Configuration对象,该对象的主要作用是读取HDFS的系统配置信息,也就是安装Hadoop时候的配置文件,例如core-site.xml、hdfs-site.xml、mapred-site.xml等文件。

❷ FileSystem是一个普通的文件系统API,可以使用静态工厂方法取得FileSystem实例,并传入Configuration对象参数。FileSystem类的继承结构如图4-9所示。

图4-9 FileSystem类的继承结构

❸ 通过调用FileSystem对象的open()方法,取得文件的输入流。该方法实际上返回的是一个FSDataInputStream对象,而不是标准的java.io类对象。FSDataInputStream类是继承了java.io.DataInputStream类的一个特殊类,支持随机访问,因此可以从流的任意位置读取数据。FSDataInputStream类的主要作用是使用DataInputStream包装一个输入流,并且使用BufferedInputStream实现对输入的缓冲。FSDataInputStream类的部分定义源码如下:

FSDataInputStream类的继承结构如图4-10所示。

图4-10 FSDataInputStream类的继承结构

2. 运行程序

直接在Eclipse中右键单击代码空白处,选择【Run As】/【Java Application】运行该程序即可,若控制台中能正确输出文件file.txt的内容,说明代码编写正确。

当然,也可以将项目导出为jar包,然后上传jar包到Hadoop集群的任意一个节点上,执行以下命令运行该程序:

上述命令需要到$HADOOP_HOME/bin目录中执行,若配置了该目录的系统PATH变量,则可以在任意目录执行。其中的hdfs_demo.jar为项目导出的jar包名称,此处为相对路径,hdfs.demo为类FileSystemCat所在的包名。

4.4.2 创建目录

使用FileSystem的创建目录方法mkdirs(),可以创建未存在的父目录,就像java.io.File的mkdirs()方法一样。如果目录创建成功,它会返回true。

下面这个例子是在HDFS文件系统根目录下创建一个名为mydir的文件夹。

1. 编写程序

在新建的hdfs_demo项目中新建Java类CreateDir.java,该类的完整代码如下所示:

2. 运行程序

代码的运行参考4.4.1节,若控制台中能正确输出“创建目录成功!”,说明代码编写正确。

4.4.3 创建文件

使用FileSystem的创建文件方法create(),可以在HDFS文件系统的指定路径创建一个文件,并向其写入内容。例如,在HDFS系统根目录创建一个文件newfile2.txt,并写入内容“我是文件内容”,代码如下:

代码分析:

❶ FileSystem实例的create()方法返回一个文件输出流对象FSDataOutputStream,该类继承了java.io.DataOutputStream类。与FSDataInputStream类不同的是,FSDataOutputStream类不支持随机访问,因此不能从文件的任意位置写入数据,只能从文件末尾追加数据。

create()方法有多个重载方法,允许指定是否强制覆盖已有文件(默认覆盖)、文件副本数量、写入文件的缓冲大小、文件块大小、文件权限许可等。create()方法的其中几个重载方法的定义源码如下:

在调用create()方法时,还可以传入一个Progressable对象,该Progressable是一个接口,其中定义了一个progress()回调方法,使用该方法可以得知数据被写入数据节点的进度。Progressable接口的源码如下:

例如,上传文件D:/soft/test.zip到HDFS根目录,并通过在控制台打印“.”显示上传进度,代码如下:

运行上述代码,当每次上传64 KB数据包到Hadoop数据节点时将调用一次progress()方法。

此外,还可以使用FileSystem的append()方法在文件末尾追加数据。这对于日志文件需要持续写入数据非常有用。append()方法的调用源码如下:

4.4.4 删除文件

使用FileSystem的deleteOnExit()方法,可以对HDFS文件系统中已经存在的文件进行删除。例如,删除HDFS系统根目录下的文件newfile.txt,代码如下:

4.4.5 遍历文件和目录

使用FileSystem的listStatus()方法,可以对HDFS文件系统中指定路径下的所有目录和文件进行遍历。例如,递归遍历HDFS系统根目录下的所有文件和目录并输出路径信息,代码如下:

上述代码通过调用FileSystem的listStatus()方法获得指定路径下的一级子目录及文件,并将结果存储于FileStatus类型的数组中;然后循环遍历该数组,当遇到目录时,再次调用listStatus()方法取得该目录下的所有子目录及文件,从而能够递归取得指定路径下的所有目录及文件。

假设HDFS文件系统的根目录有文件夹input、文件newfile.txt,文件夹input中有文件test.txt,则上述代码的输出结果为:

4.4.6 获取文件或目录的元数据

使用FileSystem的getFileStatus ()方法,可以获得HDFS文件系统中的文件或目录的元数据信息,包括文件路径、文件修改日期、文件上次访问日期、文件长度、文件备份数、文件大小等。getFileStatus ()方法返回一个FileStatus对象,元数据信息则封装在了该对象中。

获取文件或目录元数据的代码如下:

上述代码的输出结果如下:

4.4.7 上传本地文件

使用FileSystem的copyFromLocalFile()方法,可以将操作系统本地的文件上传到HDFS文件系统中,该方法需要传入两个Path类型的参数,分别代表本地目录/文件和HDFS目录/文件。

例如,将Windows系统中D盘的copy_test.txt文件上传到HDFS文件系统的根目录,代码如下:

4.4.8 下载文件到本地

使用FileSystem的copyToLocalFile()方法,可以将HDFS文件系统中的文件下载到操作系统本地,该方法需要传入两个Path类型的参数,分别代表HDFS目录/文件和本地目录/文件。例如,将HDFS文件系统根目录的文件newfile2.txt下载到Windows系统中D盘根目录,并重命名为new.txt,代码如下: