首页 > 大数据 阅读:1,954

HDFS两种操作方式:命令行和Java API

< 上一页HDFS读取和写入数据 NoSQL简介下一页 >

HDFS 文件操作有两种方式:一种是命令行方式,Hadoop 提供了一套与 Linux 文件命令类似的命令行工具;另一种是 Java API,即利用 Hadoop 的 Java 库,采用编程的方式操作 HDFS 的文件。

本节将介绍 Linux 操作系统中关于 HDFS 文件操作的常用命令行,并将介绍利用 Hadoop 提供的 Java API 进行基本的文件操作,以及利用 Web 界面查看和管理 HDFS 的方法。

HDFS 常用命令

Linux 命令行终端,可以使用命令行工具对 HDFS 进行操作。使用这些命令行可以完成 HDFS 文件的上传、下载和复制,还可以查看文件信息、格式化 NameNode 等。

HDFS 命令行的统一格式如下。

hadoop fs -cmd <args>

其中,cmd是具体的文件操作命令,<args>是一组数目可变的参数。

1. 添加文件和目录

HDFS 有一个默认工作目录 /usr/$USER,其中,$USER是登录用户名,如 root。该目录不能自动创建,需要执行 mkdir 命令创建。

hadoop fs -mkdir /usr/root

使用 Hadoop 的命令put将本地文件 README.txt 上传到 HDFS。

hadoop fs -put README.txt

注意,上面这个命令的最后一个参数是:“.”,这意味着把本地文件上传到默认的工作目录下,该命令等价于以下代码。

hadoop fs -put README.txt /user/root

2. 下载文件

下载文件是指从 HDFS 中获取文件,可以使用 Hadoop 的 get 命令。例如,若本地文件没有 README.txt 文件,则需要从 HDFS 中取回,可以执行以下命令。

hadoop fs -get README.txt

或者执行以下命令。

hadoop fs -get README.txt /usr/root/README.txt

3. 删除文件

Hadoop 删除文件的命令为rm。例如,要删除从本地文件上传到 HDFS 的 README.txt,可以执行以下命令。

hadoop fs -rm README.txt

4. 检索文件

检索文件即查阅 HDFS 中的文件内容,可以使用 Hadoop 中的cat命令。例如,要查阅 README.txt 的内容,可以执行以下命令。

hadoop fs -cat README.txt

另外,Hadoop 的cat命令的输出也可以使用管道传递给 UNIX 命令的 head,可以只显示文件的前一千个字节。

hadoop fs -cat README.txt | head

Hadoop 也支持使用tail命令查看最后一千字节。例如,要查阅 README.txt 最后一千个字节,可以执行如下命令。

hadoop fs -tail README.txt

5. 查阅帮助

查阅 HDFS 命令帮助,可以更好地了解和使用 Hadoop 的命令。用户可以执行hadoop fs来获取所用版本 HDFS 的一个完整命令类别,也可以使用help来显示某个具体命令的用法及简短描述。

例如,要了解ls命令,可执行以下命令。

hadoop fs -help ls

HDFS 的 Web 界面

在配置好 Hadoop 集群之后,用户可以通过 Web 界面查看 HDFS 集群的状态,以及访问 HDFS,访问地址如下。

http://[NameNodeIP]:50070

其中,[NameNodeIP]为 HDFS 集群的 NameNode 的 IP 地址。登录后,用户可以查看 HDFS 的信息。

如图 1 所示,通过 HDFS NameNode 的 Web 界面,用户可以查看 HDFS 中各个结点的分布信息,浏览 NameNode 上的存储、登录等日志,以及下载某个 DataNode 上某个文件的内容。

通过 HDFS 的 Web 界面,还可以查看整个集群的磁盘总容量,HDFS 已经使用的存储空间量,非 HDFS 已经使用的存储空间量,HDFS 剩余的存储空间量等信息,以及查看集群中的活动结点数和宕机结点数。

图 2 显示了一个 DataNode 的信息,如磁盘的数量,每块磁盘的使用情况等。通过 Web 界面中的“Utilities”→“Browse the file system”可以查看当前 HDFS 的目录列表,以及每个目录的相关信息,包括访问权限、最后修改日期、文件拥有者、目录大小等。

进一步,用户还可以通过 Web 界面查看文件的信息,如图 3 所示。用户不仅可以查看文件的权限、大小等信息,还可以查看该文件的每个数据块所在的数据结点。

因为每一个文件都是分成好多数据块的,每个数据块又有 3 个副本,这些数据块的副本全部分布存放在多个 DataNode 中,所以用户不可能像传统文件系统那样来访问文件。HDFS Web 界面给用户提供了一个方便、直观地查看 HDFS 文件信息的方法。通过 Web 界面完成的所有操作,都可以通过 Hadoop 提供的命令来实现。

HDFS NameNode的WEB界面
图 1  HDFS NameNode的WEB界面
 
HDFS DataNode的WEB界面
图 2  HDFS NameNode的WEB界面
 
HDFS文件界面
图 3  HDFS文件界面

HDFS 的 Java API

HDFS 设计的主要目的是对海量数据进行存储,也就是说在其上能够存储很大量的文件。

HDFS 将这些文件分割之后,存储在不同的 DataNode 上,HDFS 提供了通过Java API 对 HDFS 里面的文件进行操作的功能,数据块在 DataNode 上的存放位置,对于开发者来说是透明的。

使用 Java API 可以完成对 HDFS 的各种操作,如新建文件、删除文件、读取文件内容等。下面将介绍 HDFS 常用的 Java API 及其编程实例。

对 HDFS 中的文件操作主要涉及以下几个类。
名称 作用
org.apache.hadoop.con.Configuration 该类的对象封装了客户端或者服务器的配置。
org.apache.hadoop.fs.FileSystem 该类的对象是一个文件系统对象,可以用该对象的一些方法来对文件进行操作。
org.apache.hadoop.fs.FileStatus 该类用于向客户端展示系统中文件和目录的元数据,具体包括文件大小、块大小、副本信息、所有者、修改时间等。
org.apache.hadoop.fs.FSDatalnputStream 该类是 HDFS 中的输入流,用于读取 Hadoop 文件。
org.apache.hadoop.fs.FSDataOutputStream 该类是 HDFS 中的输出流,用于写 Hadoop 文件;
org.apache.hadoop.fs.Path 该类用于表示 Hadoop 文件系统中的文件或者目录的路径。

下面通过一个实例来说明如何对文件进行具体操作。

1. 获取文件系统

/**
 * 获取文件系统
 * @return FileSystem
 */
public static FileSystem getFileSystem(){
    // 读取配置文件
    Configuration conf = new Configuration();
    // 文件系统
    FileSystem fs = null;
    String hdfsUri = HDFSUri;
    if(StringUtils.isBlank(hdfsUri)){
        // 返回默认文件系统,如果在Hadoop集群下运行,使用此方法可直接获取默认文件系统
        try{
            fs = FileSystem.get(conf);
        }catch(IOException e){
            logger.error("",e);
        }
    }else{
        // 根据指定的文件系统,如果在本地测试,需要使用此方法获取文件系统
        try{
            URI uri = new URI(hdfsUri.trim());
            fs = FileSystem.get(uri,conf);
        }catch(URISyntaxException | IOExeption e){
            logger.error("",e);
        }
    }
    return fs;
}

2. 创建文件目录

/**
* 创建文件目录
* @param path
*/
public static void mkdir(String path){
    try{
        // 获取文件系统
        FileSystem fs = getFileSystem();
        String hdfsUri = HDFSUri;
        if(StringUtils.isNotBlank(hdfsUri)){
            path = hdfsUri + path;
        }
        // 创建目录
        fs.mkdirs(new Path(path));
        // 释放资源
        fs.close();
    }catch(IllegalArgumentException | IOException e){
        logger.error("",e);
    }
}

3. 删除文件或者文件目录

/**
* 删除文件或者文件目录
* @param path
*/
public static void rmdir(String path){
    try{
        // 返回 FileSystem 对象
        FileSystem fs = getFileSystem();
        String hdfsUri = HDFSUri;
        if(StringUtils.isNotBlank(hdfsUri)){
            path = hdfsUri + path;
        }
        // 删除文件或者文件目录
        fs.delete(new Path(path),true);
        // 释放资源
        fs.close();
    }catch(IllegalArgumentException | IOException e){
        logger.error("",e);
    }
}

4. 将文件上传至 HDFS

/**
* 将文件上传至 HDFS
* @param delSrc
* @param overwrite
* @param srcFile
* @param destPath
*/
public static void copyFileToHDFS(boolean delSrc,boolean overwrite,String srcFile,String destPath){
    // 源文件路径是 Linux 下的路径
    Path srcPath = new Path(srcFile);
    // 目的路径
    String hdfsUri = HDFSUri;
    if(StringUtils.isNotBlank(hdfsUri)){
        destPath = hdfsUri + destPath;
    }
    Path dstPath = new Path(destPath);
    // 实现文件上传
    try{
        // 获取 FileSystem 对象
        FileSystem fs = getFileSystem();
        fs.copyFromLocalFile(srcPath,dstPath);
        fs.copyFromLocalFile(delSrc,overwrite,srcPath,dstPath);
        // 释放资源
        fs.close();
    }catch(IOException e){
        logger.error("",e);
    }
}

5. 从 HDFS 下载文件

/**
* 从 HDFS 下载文件
* @param srcFile
* @param destPath
*/
public static void getFile(String srcFile,String destPath){
    // 源文件路径
    String hdfsUri = HDFSUri;
    if(StringUtils.isNotBlank(hdfsUri)){
        srcFile = hdfsUri + srcFile;
    }
    Path srcPath = new Path(srcFile);
    // 目的路径是 Linux 下的路径
    Path dstPath = new Path(destPath);
    try{
        // 获取FileSystem对象
        FileSystem fs = getFileSystem();
        // 下载HDFS上的文件
        fs.close();
    }catch(IOException e){
        logger.error("",e);
    }
}
< 上一页HDFS读取和写入数据 NoSQL简介下一页 >