任务2 HDFS基本操作
关键步骤如下。
掌握使用shell访问HDFS文件系统。
掌握使用Java API访问HDFS文件系统。
2.2.1 使用HDFS shell访问
HDFS Shell访问
1.概述
HDFS为使用者提供了基于shell操作命令来管理HDFS上的数据的功能。这些shell命令和Linux的命令十分类似,这样设计的好处是让已经熟悉Linux的用户可以更加快速地对HDFS的数据进行操作,减少学习的时间。
注意
使用HDFS shell之前需要先启动Hadoop。
HDFS的基本命令格式如下。
bin/hdfs dfs -cmd <args>
注意
cmd就是具体的命令,cmd前面的“-”千万不要省略。
2.列出文件目录
命令:hadoop fs -ls 目录路径
示例:查看HDFS根目录下的文件
[hadoop@hadoop000 ~]$ hadoop fs -ls /
Found 4 items
-rw-r--r-- 1 hadoop supergroup 159 2017-01-15 05:11/README.html
drwxr-xr-x -hadoop supergroup 0 2017-01-15 05:15/data
drwxr-xr-x -hadoop supergroup 0 2017-01-15 05:31/datas
-rw-r--r-- 1 hadoop supergroup 40 2017-01-15 05:13/text.log
如果想递归查看文件,可以使用-ls -R命令,即该命令不仅会打印出目录路径下的文件,而且会打印出其子目录和子目录的文件。例如想查看/data下的所有文件。
[hadoop@hadoop000 ~]$ hadoop fs -ls -R /data
drwxr-xr-x -hadoop supergroup 0 2017-01-15 05:12/data/input
-rw-r--r-- 1 hadoop supergroup 21102856 2017-01-15 05:12/data/input/src.zip
-rw-r--r-- 1 hadoop supergroup 40 2017-01-15 05:15/data/text.log
3.在HDFS中创建文件夹
命令:hadoop fs -mkdir 文件夹名称
示例:在HDFS的根目录下创建名为datatest的文件夹
[hadoop@hadoop000 ~]$ hadoop fs -mkdir /datatest
[hadoop@hadoop000 ~]$ hadoop fs -ls /
Found 5 items
-rw-r--r-- 1 hadoop supergroup 159 2017-01-15 05:11/README.html
drwxr-xr-x -hadoop supergroup 0 2017-01-15 05:15/data
drwxr-xr-x -hadoop supergroup 0 2017-01-15 05:31/datas
drwxr-xr-x -hadoop supergroup 0 2017-01-17 03:39/datatest
-rw-r--r-- 1 hadoop supergroup 40 2017-01-15 05:13/text.log
如果想级联创建一个文件夹,需要在-mkdir 命令后指定-p参数。例如,我们想在HDFS上创建这样一个目录:/datatest/mr/input,而mr目录在之前是不存在的,所以想一次性创建成功,必须加上-p参数,否则会报错,命令为:hadoop fs -mkdir -p /datatest/mr/input。
[hadoop@hadoop000 ~]$ hadoop fs -mkdir -p /datatest/mr/input
[hadoop@hadoop000 ~]$ hadoop fs -ls /datatest
Found 1 items
drwxr-xr-x - hadoop supergroup 0 2017-01-17 03:41 /datatest/mr
[hadoop@hadoop000 ~]$ hadoop fs -ls /datatest/mr
Found 1 items
drwxr-xr-x - hadoop supergroup 0 2017-01-17 03:41 /datatest/mr/input
4.上传文件至HDFS
命令:hadoop fs -put 源路径目标存放路径
示例:将本地Linux文件系统目录/home/hadoop/data/下的input.txt文件上传至HDFS文件目录/datatest下
[hadoop@hadoop000 ~]$ hodoop fs -put /home/hadoop/data/input.txt /datatest
[hadoop@hadoop000 ~]$ hodoop fs -ls /datatest
Found 2 items
-rw-r--r-- 1 hadoop supergroup 343 2017-01-17 03:44/datatest/input.txt
drwxr-xr-x -hadoop supergroup 0 2017-01-17 03:41/datatest/mr
5.从HDFS上下载文件
命令:hdfs dfs -get HDFS文件路径本地存放路径
示例:将刚刚上传的input.txt文件下载到本地用户的目录下
[hadoop@hadoop000~]$ hdfs dfs -get /datatest/input.txt /home/hadoop/app
[hadoop@hadoop000~]$ ll
-rw-r--r--.1 hadoop hadoop 343 Jan 17 03:48 input.txt
6.查看HDFS上某个文件的内容
命令:hadoop fs-text(cat) HDFS上的文件存放路径
示例:查看刚刚上传的input.txt文件
[hadoop@hadoop000~]$ hodoop fs -text /datatest/input.txt
spark hadoop spark hadoop hive
hadoop kafka Hbase spark Hadoop
spark hive cisco ES hadoop flume
注意
text命令和cat命令都可以用来查看文件内容,这里只演示了text命令,cat命令请读者自己动手操作。
7.统计目录下各文件的大小
命令:hodoop fs -du 目录路径
示例:查看/data test/目录下各个文件的大小
[hadoop@hadoop000 ~]$ hodoop fs -du /datatest/
96 96 /datatest/input.txt
0 0 /datatest/mr
注意
统计目录下文件大小使用的单位是字节。
8.删除HDFS上的某个文件或者文件夹
命令:hodoop fs -rm(r) 文件存放路径
示例:删除刚刚上传的input.txt文件
[hadoop@hadoop000 ~]$ hodoop fs -rm /datatest/input.txt
Deleted /datatest/input.txt
[hadoop@hadoop000 ~]$ hodoop fs -ls /datatest/
Found 1 items
drwxr-xr-x -hadoop supergroup 0 2017-01-17 03:41/datatest/mr
在HDFS中删除文件与删除目录所使用命令有区别,一个是-rm,表示删除指定的文件或者空目录;一个是-rmr,表示递归删除指定目录下的所有子目录和文件。如下面的命令是删除output下的所有子目录和文件。
hodoop fs -rmr /test/output
注意
在生产环境中要慎用-rmr,容易引起误删除操作。
9.使用help命令寻求帮助
命令:hodoop fs -help 命令
示例:查看rm命令的帮助
[hadoop@hadoop000~]$hodoop fs-help rm
-rm[-f][-r|-R][-skipTrash]<src>...:
Delete all files that match the specified file pattern.Equivalent to the Unix
command"rm<src>"
-skipTrash option bypasses trash,if enabled,and immediately deletes<src>
-f If the file does not exist,do not display a diagnostic message or
modify the exit status to reflect an error.
-[rR] Recursively deletes directories
以上讲解的命令是日常工作中使用频次较高的,所以务必要熟练掌握。如果还想学习其他shell命令操作,可以访问官网(http://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-common/File System Shell.html)、使用help帮助或者在网络上搜索,在此不再赘述。
2.2.2 使用Java API访问
1.概述
除了可以使用HDFS shell的方式来访问HDFS上的数据,Hadoop还提供了以Java API的方式来操作HDFS上的数据。我们实际开发的大数据应用都是以代码的方式提交的,所以在代码中使用API的方式来操作HDFS数据也必须掌握。下面介绍如何使用Java API对HDFS中的文件进行操作。
2.搭建开发环境
我们使用Maven来构建Java应用程序,所以需要添加maven的依赖包。
代码2.1 Maven pom文件
<properties>
<project.build.source Encoding>UTF-8</project.build.source Encoding>
<hadoop.version>2.6.0-cdh5.7.0</hadoop.version>
</properties>
<dependencies>
<dependency>
<group Id>org.apache.hadoop</group Id>
<artifact Id>hadoop-common</artifact Id>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<group Id>org.apache.hadoop</group Id>
<artifact Id>hadoop-hdfs</artifact Id>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<group Id>junit</group Id>
<artifact Id>junit</artifact Id>
<version>4.10</version>
</dependency>
</dependencies>
注意
在执行单元测试之前,需要在$HADOOP_HOME/etc/hadoop/hdfs-site.xml中添加如下配置,并重启HDFS集群。
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
3.单元测试的set Up和tear Down方法
在单元测试中,一般将初始化的操作放在set Up方法中完成,将关闭资源的操作放在tear Down方法中完成。那么我们在测试HDFS时,打开文件系统的操作就可以放在set Up中,而关闭文件系统的操作就可以放在tear Down中。
代码2.2 单元测试set Up和tear Down方法
package com.kgc.bigdata.hadoop.hdfs.api;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.net.URI;
/ **
* HDFS Java API操作
*/
public class HDFSApp {
public static final String HDFS_PATH ="hdfs://hadoop000:8020";
Configuration configuration = null;
File System file System = null;
@Before
public void set Up() throws Exception{
System.out.println("HDFSApp.set Up()");
configuration = new Configuration();
file System = File System.get(new URI(HDFS_PATH), configuration);
}
@After
public void tear Down() throws Exception{
file System = null;
configuration = null;
System.out.println("HDFSApp.tear Down()");
}
}
4.使用Java API操作HDFS的常用操作
代码2.3 Java API操作HDFS文件
/ **
*创建目录
*/
@Test
public void mkdir() throws Exception {
file System.mkdirs(new Path("/hdfsapi/test"));
}
/ **
*创建文件
*/
@Test
public void create() throws Exception {
FSData Output Stream output = file System.create(new Path("/hdfsapi/test/a.txt"));
output.write("hello world".get Bytes());
output.flush();
output.close();
}
/ **
*重命名
*/
@Test
public void rename() throws Exception {
Path old Path = new Path("/hdfsapi/test/a.txt");
Path new Path = new Path("/hdfsapi/test/b.txt");
System.out.println(file System.rename(old Path, new Path));
}
/ **
*上传本地文件到HDFS
*/
@Test
public void copyFromLocalFile() throws Exception {
Path src = new Path("/home/hadoop/data/hello.txt");
Path dist = new Path("/hdfsapi/test/");
fileSystem.copyFromLocalFile(src, dist);
}
/ **
* 查看某个目录下的所有文件
*/
@Test
public void listFiles() throws Exception {
FileStatus[] listStatus = fileSystem.listStatus(new Path("/hdfsapi/test"));
for (FileStatus fileStatus : listStatus) {
String isDir=fileStatus.isDirectory()?"文件夹":"文件"; //文件/文件夹
String permission = fileStatus.getPermission().toString(); //权限
short replication = fileStatus.getReplication(); //副本系数
long len = fileStatus.getLen(); //长度
String path = fileStatus.getPath().toString(); //路径
System.out.println(isDir + "\t" + permission + "\t" + replication + "\t" + len + "\t" + path);
}
}
/ **
* 查看文件块信息
*/
@Test
public void getFileBlockLocations() throws Exception {
FileStatus fileStatus = fileSystem.getFileStatus(new Path("/hdfsapi/test/b.txt"));
BlockLocation[] blocks = fileSystem.getFileBlockLocations(fileStatus, 0, fileStatus.getLen());
for (BlockLocation block : blocks) {
for (String host : block.getHosts()) {
System.out.println(host);
}
}
}