我们是在Hadoop伪分布式下去进行HDFS的编程实践

准备工作:

vm15.5

hadoop3.3.1

eclipse-java-2021-09-R-linux-gtk-x86_64

参考:林子雨:HDFS编程实践(Hadoop3.1.3)_厦大数据库实验室博客 

他使用的是Hadoop3.1.3版本的,过程可能会遇到的坑将在另一篇文章中总结:在进行HDFS实践时遇到的问题:_阿洋太爱大数据的博客 

开始

在HDFS编程实践前,我们需要启动Hadoop(版本是Hadoop3.1.3)。

执行如下命令:

cd /usr/local/hadoop
./sbin/start-dfs.sh

并且jps检查是否启动成功:

[hadoop@localhost hadoop]$ jps
5233 SecondaryNameNode
5382 Jps
5018 DataNode
4893 NameNode

成功后开始我们的实践

一、利用Shell命令与HDFS进行交互

在终端输入如下命令,查看fs总共支持了哪些命令


[hadoop@localhost hadoop]$ ./bin/hadoop fs


在终端输入如下命令,可以查看具体某个命令的作用

例如:我们查看rm命令如何使用,可以输入如下命令

./bin/hadoop fs -help rm

1、目录操作

Hadoop系统安装好以后,第一次使用HDFS时,需要首先在HDFS中创建用户目录。我们在这里采用hadoop用户登录Linux系统,因此,需要在HDFS中为hadoop用户创建一个用户目录,命令如下:

cd /usr/local/hadoop
./bin/hdfs dfs -mkdir -p /user/hadoop

该命令中表示在HDFS中创建一个“/user/hadoop”目录,“–mkdir”是创建目录的操作,“-p”表示如果是多级目录,则父目录和子目录一起创建,这里“/user/hadoop”就是一个多级目录,因此必须使用参数“-p”,否则会出错。 “/user/hadoop”目录就成为hadoop用户对应的用户目录,可以使用如下命令显示HDFS中与当前用户hadoop对应的用户目录下的内容:

[hadoop@localhost hadoop]$ ./bin/hdfs dfs -ls   #该命令中,“-ls”表示列出HDFS某个目录下的所有内容,“.”表示HDFS中的当前用户目录,也就是“/user/hadoop”目录,因此,上面的命令和下面的命令是等价的:
[hadoop@localhost hadoop]$ ./bin/hdfs dfs -ls /user/hadoop
#如果要列出HDFS上的所有目录,可以使用如下命令:
[hadoop@localhost hadoop]$ ./bin/hdfs dfs -ls
#下面,可以使用如下命令创建一个input目录:
[hadoop@localhost hadoop]$ ./bin/hdfs dfs -mkdir input
#在创建个input目录时,采用了相对路径形式,实际上,这个input目录创建成功以后,它在HDFS中的完整路径是“/user/hadoop/input”



可以使用rm命令删除一个目录,比如,可以使用如下命令删除刚才在HDFS中创建的“/input”目录(不是“/user/hadoop/input”目录):

./bin/hdfs dfs –rm –r /input   #“-r”参数表示如果删除“/input”目录及其子目录下的所有内容,如果要删除的一个目录包含了子目录,则必须使用“-r”参数,否则会执行失败。

2.文件操作

在实际应用中,经常需要从本地文件系统向HDFS中上传文件,或者把HDFS中的文件下载到本地文件系统中。 首先,使用vim编辑器,在本地Linux文件系统的“/home/hadoop/”目录下创建一个文件myLocalFile.txt,里面可以随意输入一些单词

[hadoop@localhost ~]$ cd /home
[hadoop@localhost home]$ cd /home/hadoop
[hadoop@localhost ~]$ pwd
/home/hadoop
[hadoop@localhost ~]$ vim myLocalFile.txt

然后,可以使用如下命令把本地文件系统的“/home/hadoop/myLocalFile.txt”上传到HDFS中的当前用户目录的input目录下,也就是上传到HDFS的“/user/hadoop/input/”目录下:(注意路径)

[hadoop@localhost ~]$ cd /usr/local/hadoop
[hadoop@localhost hadoop]$ ./bin/hdfs dfs -put /home/hadoop/myLocalFile.txt  input



可以使用ls命令查看一下文件是否成功上传到HDFS中,具体如下:


[hadoop@localhost hadoop]$ ./bin/hdfs dfs -ls input


Hadoop开发的产品 hadoop开发实战_hadoop

下面使用如下命令查看HDFS中的myLocalFile.txt这个文件的内容:

./bin/hdfs dfs –cat input/myLocalFile.txt

 

Hadoop开发的产品 hadoop开发实战_linux_02

下面把HDFS中的myLocalFile.txt文件下载到本地文件系统中的“/home/hadoop/下载/”这个目录下,命令如下:

./bin/hdfs dfs -get input/myLocalFile.txt  /home/hadoop/下载

Hadoop开发的产品 hadoop开发实战_linux_03

[hadoop@localhost hadoop]$ cd ~
[hadoop@localhost ~]$ cd 下载
[hadoop@localhost 下载]$ ls
hadoop-3.3.1.tar.gz  myLocalFile.txt
[hadoop@localhost 下载]$ cat myLocalFile.txt

最后,了解一下如何把文件从HDFS中的一个目录拷贝到HDFS中的另外一个目录。比如,如果要把HDFS的“/user/hadoop/input/myLocalFile.txt”文件,拷贝到HDFS的另外一个目录“/input”中(注意,这个input目录位于HDFS根目录下),可以使用如下命令:

./bin/hdfs dfs -cp input/myLocalFile.txt  /input

二、利用Web界面管理HDFS

通过浏览器访问:http://localhost:9870

三、利用JAVA API与HDFS进行交互

(一)安装eclipse:

1在centos7中安装eclipse

下载地址:Luna SR2 | Eclipse Packages

2.通过xftp来传输

a)先在Windows环境下下载好文件Luna SR2 | Eclipse Packages选择正确的文件

b)通过xftp远程登录虚拟机来传输文件

Hadoop开发的产品 hadoop开发实战_hadoop_04

名称自定,主机为虚拟机的IP地址(通过ifconfig来查看),用户名为hadoop,密码为自己虚拟机用户的密码,然后点击连接

Hadoop开发的产品 hadoop开发实战_hdfs_05

然后将下载好的eclipse压缩包通过拖拽的方式拖到想要的目录下,此处为下载目录

c)在虚拟机内解压缩eclipse压缩包

已经通过xftp完成了eclipse压缩包的传输,在下载目录下ls查看是否成功:

[hadoop@localhost 下载]$ ls
eclipse-java-2021-09-R-linux-gtk-x86_64.tar.gz  hadoop-3.3.1.tar.gz  myLocalFile.txt

出现了目标的压缩包,则已经成功

解压缩:(eclipse-java-2021-09-R-linux-gtk-x86_64.tar.gz为自己的压缩包文件名)

sudo tar -zxvf ./eclipse-java-2021-09-R-linux-gtk-x86_64.tar.gz -C /usr/local
eclipse/

等待片刻后成功,通过如下启动eclipse:

cd /usr/local/eclipse
./eclipse

(二)使用eclipse开发调试HDFS Java程序

1.在eclipse中创建项目:

启动eclipse,出现以下界面:

Hadoop开发的产品 hadoop开发实战_linux_06

可以直接采用默认的设置“/home/hadoop/workspace”

进入后:选择“File–>New–>Java Project”菜单,开始创建一个Java工程,会弹出如下图所示界面。

Hadoop开发的产品 hadoop开发实战_hadoop_07

在“Project name”后面输入工程名称“HDFSExample”,选中“Use default location”,让这个Java工程的所有文件都保存到“/home/hadoop/workspace/HDFSExample”目录下。在“JRE”这个选项卡中,可以选择当前的Linux系统中已经安装好的JDK

Hadoop开发的产品 hadoop开发实战_linux_08

可以见到我这里是选项Use a project specific JRE选项里面这里是有对应合适的JDK包,但是我刚进去的时候是没有的,需要手动自己配置一下:

点击蓝色字体:Configure JREs...

Hadoop开发的产品 hadoop开发实战_linux_09

点击右侧的Add

Hadoop开发的产品 hadoop开发实战_hdfs_10

Hadoop开发的产品 hadoop开发实战_Hadoop开发的产品_11

点击Standard VM后点击next

再弹出的窗口的JRE home处填入自己的Java安装路径,可以在我教程Java安装教程里面找到,简单来说也就是需要配置环境变量这里的这个路径。

Hadoop开发的产品 hadoop开发实战_大数据_12

 

Hadoop开发的产品 hadoop开发实战_Hadoop开发的产品_13

完成后finish,退出重新打卡,就有了

点击next,在这个界面中加载该Java工程所需要用到的JAR包,这些JAR包都位于Linux系统的Hadoop安装目录下,即“/usr/local/hadoop/share/hadoop”,点击界面中的“Libraries”选项卡,然后,点击界面右侧的“Add External JARs…”按钮。

Hadoop开发的产品 hadoop开发实战_hdfs_14

先点一下ModulePath,再点Add External JARs...

将以下四个文件夹里面的全部JAR包选择添加(不含文件和目录)。

“/usr/local/hadoop/share/hadoop/common”

“/usr/local/hadoop/share/hadoop/common/lib”

“/usr/local/hadoop/share/hadoop/hdfs”

“/usr/local/hadoop/share/hadoop/hdfs/lib”

Hadoop开发的产品 hadoop开发实战_hdfs_15

导入后:

Hadoop开发的产品 hadoop开发实战_linux_16

添加完四个文件夹内的jar包后点击Finish,完成项目创建

2.编写Java应用程序

在Eclipse工作界面左侧的“Package Explorer”面板中,找到刚才创建好的工程名称“HDFSExample”,然后在该工程名称上点击鼠标右键,在弹出的菜单中选择“ New–>Class”菜单

Hadoop开发的产品 hadoop开发实战_大数据_17

只需要在“Name”后面输入Java类文件的名称“MergeFile”,其余设置默认

Hadoop开发的产品 hadoop开发实战_linux_18

在“MergeFile.java”源文件代码写入下代码,先别运行

import java.io.IOException;
import java.io.PrintStream;
import java.net.URI;
 
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
 
/**
 * 过滤掉文件名满足特定条件的文件 
 */
class MyPathFilter implements PathFilter {
     String reg = null; 
     MyPathFilter(String reg) {
          this.reg = reg;
     }
     public boolean accept(Path path) {
        if (!(path.toString().matches(reg)))
            return true;
        return false;
    }
}
/***
 * 利用FSDataOutputStream和FSDataInputStream合并HDFS中的文件
 */
public class MergeFile {
    Path inputPath = null; //待合并的文件所在的目录的路径
    Path outputPath = null; //输出文件的路径
    public MergeFile(String input, String output) {
        this.inputPath = new Path(input);
        this.outputPath = new Path(output);
    }
    public void doMerge() throws IOException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS","hdfs://localhost:9000");
          conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");
        FileSystem fsSource = FileSystem.get(URI.create(inputPath.toString()), conf);
        FileSystem fsDst = FileSystem.get(URI.create(outputPath.toString()), conf);
                //下面过滤掉输入目录中后缀为.abc的文件
        FileStatus[] sourceStatus = fsSource.listStatus(inputPath,
                new MyPathFilter(".*\\.abc")); 
        FSDataOutputStream fsdos = fsDst.create(outputPath);
        PrintStream ps = new PrintStream(System.out);
        //下面分别读取过滤之后的每个文件的内容,并输出到同一个文件中
        for (FileStatus sta : sourceStatus) {
            //下面打印后缀不为.abc的文件的路径、文件大小
            System.out.print("路径:" + sta.getPath() + "    文件大小:" + sta.getLen()
                    + "   权限:" + sta.getPermission() + "   内容:");
            FSDataInputStream fsdis = fsSource.open(sta.getPath());
            byte[] data = new byte[1024];
            int read = -1;
 
            while ((read = fsdis.read(data)) > 0) {
                ps.write(data, 0, read);
                fsdos.write(data, 0, read);
            }
            fsdis.close();          
        }
        ps.close();
        fsdos.close();
    }
    public static void main(String[] args) throws IOException {
        MergeFile merge = new MergeFile(
                "hdfs://localhost:9000/user/hadoop/",
                "hdfs://localhost:9000/user/hadoop/merge.txt");
        merge.doMerge();
    }
}

Hadoop的准备:

确保Hadoop已经启动运行,如果还没有启动,需要打开一个Linux终端,输入以下命令启动Hadoop:

$   cd /usr/local/hadoop
$   ./sbin/start-dfs.sh

在Linux创建5个文件,file1.txt、file2.txt、file3.txt、file4.abc和file5.abc。假设内容如下:(vim 创建,填写内容)

file1.txt的内容是: this is file1.txt

file2.txt的内容是: this is file2.txt

file3.txt的内容是: this is file3.txt

file4.abc的内容是: this is file4.abc

file5.abc的内容是: this is file5.abc

然后将这五个文件转到HDFS(其他文件同理),这里我把5个文件放到了/home//hadoop/下了

通过$ ./bin/hdfs dfs -put file1.txt的路径

[hadoop@localhost bin]$ cd /home/hadoop/
[hadoop@localhost ~]$ vim file2.txt
[hadoop@localhost ~]$ vim file3.txt
[hadoop@localhost ~]$ vim file4.abc
[hadoop@localhost ~]$ vim file5.abc
[hadoop@localhost ~]$ cd /usr/local/hadoop
[hadoop@localhost hadoop]$ ./bin/hdfs dfs -put /home/hadoop/file2.txt
[hadoop@localhost hadoop]$ ./bin/hdfs dfs -put /home/hadoop/file3.txt
[hadoop@localhost hadoop]$ ./bin/hdfs dfs -put /home/hadoop/file4.abc
[hadoop@localhost hadoop]$ ./bin/hdfs dfs -put /home/hadoop/file5.abc

Hadoop开发的产品 hadoop开发实战_hdfs_19

现在可以让代码运行了,在代码旁边右键鼠标,在弹出的菜单中选择“Run As”,继续在弹出来的菜单中选择“Java Application”

应用部署:Java应用程序生成JAR包,部署到Hadoop平台上运行。首先,在Hadoop安装目录下新建一个名称为myapp的目录,用来存放我们自己编写的Hadoop应用程序,可以在Linux的终端中执行如下命令:

[hadoop@localhost hadoop]$ mkdir myapp
[hadoop@localhost hadoop]$ cd ./myapp

然后,请在Eclipse工作界面左侧的“Package Explorer”面板中,在工程名称“HDFSExample”上点击鼠标右键,在弹出的菜单中选择“Export”,如下图所示。

Hadoop开发的产品 hadoop开发实战_hadoop_20

在弹出的界面中选中JAVA,然后选择Runnable JAR file

Hadoop开发的产品 hadoop开发实战_hdfs_21

点击next,然后在该界面中,“Launch configuration”用于设置生成的JAR包被部署启动时运行的主类,需要在下拉列表中选择刚才配置的类“MergeFile-HDFSExample”。在“Export destination”中需要设置JAR包要输出保存到哪个目录,比如,这里设置为“/usr/local/hadoop/myapp/HDFSExample.jar”。在“Library handling”下面选择“Extract required libraries into generated JAR”。

一定要在此路径下

Hadoop开发的产品 hadoop开发实战_hdfs_22

然后一路OK,遇到警告忽略就可

至此,已经顺利把HDFSExample工程打包生成了HDFSExample.jar

可以在Linux的终端中执行如下命令:

[hadoop@localhost hadoop]$ cd /usr/local/hadoop
[hadoop@localhost hadoop]$ cd ./myapp
[hadoop@localhost myapp]$ ls

可以看到,“/usr/local/hadoop/myapp”目录下已经存在一个HDFSExample.jar文件

Hadoop开发的产品 hadoop开发实战_大数据_23

由于之前已经运行过一次程序,已经生成了merge.txt,因此,需要首先执行如下命令删除该文件:

[hadoop@localhost myapp]$ cd /usr/local/hadoop
[hadoop@localhost hadoop]$ ./bin/hdfs dfs -rm /user/hadoop/merge.txt
Deleted /user/hadoop/merge.txt

现在,就可以在Linux系统中,使用hadoop jar命令运行程序,命令如下(注意是相对路径):

[hadoop@localhost hadoop]$ ./bin/hadoop jar ./myapp/HDFSExample.jar

结果如下:

Hadoop开发的产品 hadoop开发实战_hadoop_24