【Hadoop04】:HDFS基本操作

前言

在熟悉了HDFS的概念后,下面我们使用客户端对HDFS进行一些基本操作,例如读取文件、新建目录、移动文件、删除数据、列出目录等等。本章我们会使用hadoop自带的命令行工具以及Java客户端两种方式与HDFS进行交互。

命令行接口

我们首先使用命令行接口将本地文件上传到HDFS。

1
$ bin/hadoop fs -copyFromLocal README.txt hdfs://hadoop01:9000/README.txt

该命令调用了hadoop文件系统的shell命令fs,后者提供了一系列子命令,在这个例子中,我们使用的是copyFromLocal。本地文件README.txt被上传到了HDFS集群的根目录下。实际上,我们可以简化命令格式,省略NameNode的URI,并使用默认设置,因为该值在core-site.xml中已经设置了。

1
$ bin/hadoop fs -copyFromLocal README.txt /README.txt

我们也可以使用相对路径,相对路径是指当前操作用户在HDFS上的home路径,例如/user/hadoop/user/work等。

1
2
3
4
5
$ bin/hadoop fs -copyFromLocal README.txt README.txt
$ bin/hadoop fs -ls /user/work
Found 2 items
drwx------ - work supergroup 0 2019-03-05 14:05 /user/work/.Trash
-rw-r--r-- 3 work supergroup 1366 2019-03-05 14:47 /user/work/README.txt

现在我们将上传的README.txt文件下载到本地,并检查是否一致。

1
2
3
4
$ bin/hadoop fs -copyToLocal /README.txt README.copy.txt
$ md5sum README.txt README.copy.txt
e3f3778c8e3bc78efc387f91df6a241e README.txt
e3f3778c8e3bc78efc387f91df6a241e README.copy.txt

MD5值一样,说明该文件在经历了HDFS存储后并没有任何损坏。

注意,我们除了使用hadoop fs之外,还可以使用hdfs dfs命令,二者是一样的。

如果不指定任何子命令,就会列出所支持所有子命令,如下所示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
$ bin/hadoop fs
Usage: hadoop fs [generic options]
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
[-checksum <src> ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] [-l] <localsrc> ... <dst>]
[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] [-h] <path> ...]
[-cp [-f] [-p | -p[topax]] <src> ... <dst>]
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] <path> ...]
[-expunge]
[-find <path> ... <expression> ...]
[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getfattr [-R] {-n name | -d} [-e en] <path>]
[-getmerge [-nl] <src> <localdst>]
[-help [cmd ...]]
[-ls [-d] [-h] [-R] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] [-l] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] <src> ...]
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
[-setfattr {-n name [-v value] | -x name} <path>]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] <file>]
[-test -[defsz] <path>]
[-text [-ignoreCrc] <src> ...]
[-touchz <path> ...]
[-truncate [-w] <length> <path> ...]
[-usage [cmd ...]]

Generic options supported are
-conf <configuration file> specify an application configuration file
-D <property=value> use value for given property
-fs <local|namenode:port> specify a namenode
-jt <local|resourcemanager:port> specify a ResourceManager
-files <comma separated list of files> specify comma separated files to be copied to the map reduce cluster
-libjars <comma separated list of jars> specify comma separated jar files to include in the classpath.
-archives <comma separated list of archives> specify comma separated archives to be unarchived on the compute machines.

The general command line syntax is
bin/hadoop command [genericOptions] [commandOptions]

Java接口

下面我们通过HDFS的Java接口来操作HDFS。

首先需要引入相关的依赖:

1
2
3
4
5
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.2</version>
</dependency>

首先,我们将本地的文件上传至HDFS,再下载到本地。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Demo01 {
public static void main(String[] args) throws Exception {
// 初始化文件系统
// 第一个参数是NameNode的地址
// 第二个参数表示客户端配置
// 第三个参数表示我们以哪个用户的身份与HDFS进行交互,这里我设置为hadoop,否则可能会有一些权限问题
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop01:9000"), new Configuration(), "hadoop");
// 上传文件,第一个参数为本地路径,第二个参数是HDFS路径
fs.copyFromLocalFile(new Path("F:\\node.txt"), new Path("/node.txt"));
// 下载文件
fs.copyToLocalFile(new Path("/node.txt"), new Path("F:\\node.copy.txt"));
// 关闭文件系统
fs.close();
}
}

除了以文件的形式直接操作外,我们还可以通过数据流(InputStream/OutputStream)的方式进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Demo02 {
public static void main(String[] args) throws Exception {
FileSystem fs = FileSystem.get(new URI("hdfs://hadoop01:9000"), new Configuration(), "hadoop");
// 以数据流的形式上传数据
InputStream in = new FileInputStream("f:\\node.txt");
FSDataOutputStream out = fs.create(new Path("/node2.txt"));
try {
IOUtils.copyBytes(in, out, 4096);
} finally {
IOUtils.closeStream(in);
IOUtils.closeStream(out);
}
fs.close();
}
}

小结

本章主要使用了HDFS的命令行接口与Java接口两种方式对HDFS进行了操作。操作实际上非常简单,但是底层的交互非常复杂,后续我们会对底层的交互进行详细剖析,从根本上掌握运行原理。

如果您觉得不错,请赞赏一下!