HDFS 文件操作有两种方式:一种是命令行方式,Hadoop 提供了一套与 Linux 文件命令类似的命令行工具;另一种是 Java API,即利用 Hadoop 的 Java 库,采用编程的方式操作 HDFS 的文件。
本节将介绍 Linux 操作系统中关于 HDFS 文件操作的常用命令行,并将介绍利用 Hadoop 提供的 Java API 进行基本的文件操作,以及利用 Web 界面查看和管理 HDFS 的方法。在 Linux 命令行终端,可以使用命令行工具对 HDFS 进行操作。使用这些命令行可以完成 HDFS 文件的上传、下载和复制,还可以查看文件信息、格式化 NameNode 等。
HDFS 命令行的统一格式如下。其中,cmd是具体的文件操作命令,
例如,要了解ls命令,可执行以下命令。在配置好 Hadoop 集群之后,用户可以通过 Web 界面查看 HDFS 集群的状态,以及访问 HDFS,访问地址如下。其中,[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 常用命令
1. 添加文件和目录
hadoop fs -mkdir /usr/root
hadoop fs -put README.txt
hadoop fs -put README.txt /user/root
2. 下载文件
hadoop fs -get README.txt
hadoop fs -get README.txt /usr/root/README.txt
3. 删除文件
4. 检索文件
hadoop fs -cat README.txt
hadoop fs -cat README.txt | head
hadoop fs -tail README.txt
5. 查阅帮助
HDFS 的 Web 界面
http://[NameNodeIP]:50070
图 1 HDFS NameNode的WEB界面
HDFS 设计的主要目的是对海量数据进行存储,也就是说在其上能够存储很大量的文件。
HDFS 将这些文件分割之后,存储在不同的 DataNode 上,HDFS 提供了通过Java API 对 HDFS 里面的文件进行操作的功能,数据块在 DataNode 上的存放位置,对于开发者来说是透明的。
使用 Java API 可以完成对 HDFS 的各种操作,如新建文件、删除文件、读取文件内容等。下面将介绍 HDFS 常用的 Java API 及其编程实例。
对 HDFS 中的文件操作主要涉及以下几个类。
下面通过一个实例来说明如何对文件进行具体操作。
图 2 HDFS NameNode的WEB界面
HDFS 的 Java API
名称 | 作用 |
---|---|
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);
}
}