HDFS编程实践

本文详细介绍了在Linux环境下如何使用shell命令与HDFS进行交互,包括目录操作和文件操作,如上传、下载和拷贝。此外,还讲解了如何通过Web界面管理和使用JavaAPI进行更高级的文件操作,包括创建项目、添加依赖、编写及运行Java程序来与HDFS交互。
摘要由CSDN通过智能技术生成

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


让我们开始吧!启动Hadoop~

cd /usr/local/hadoop #到Hadoop安装目录
./sbin/start-dfs.sh #启动hadoop

一、利用shell命令和HDFS进行交互

  • 三种shell命令方式:
  1. hadoop fs
    适用于任何不同的文件系统,比如本地文件系统和HDFS文件系统。
  2. hadoop dfs
    只能适用于HDFS文件系统
  3. hdfs dfs
    同上,只能适用于HDFS系统

  • 查看fs总共支持了哪些命令
./bin/hadoop fs

在这里插入图片描述

  • 查看具体某个命令的作用
./bin/hadoop fs -help put # 以查看put命令如何使用为例

在这里插入图片描述

1.目录操作

hadoop系统安装后,第一次使用HDFS时,需要先在HDFS中创建用户目录。
而本博客中采用Hadoop用户登录Linux系统,因此,需要在HDFS中为hadoop用户创建一个用户目录。

cd /usr/local/hadoop # 设置当前目录
./bin/hdfs dfs -mkdir -p /user/hadoop

其中:

  • -mkdir是创建目录
  • -p表示若是多级目录,则父目录和子目录一起创建。本例中"/user/hadoop"就是一个多级目录,所以必须要使用参数-p(否则会出错)
  • “/** ”表示绝对目录,“* *”表示相对目录
  • ~ 代表是home目录,也就是家目录, / 代表的是根目录

"/user/hadoop"目录成为hadoop用户对应的用户目录。显示HDFS中与当前hadoop对应的用户目录下的内容

./bin/hdfs dfs -ls .

其中:

  • -ls表示列出HDFS某个目录下的所有内容
  • .表示HDFS中的当前用户目录,即"/user/hadoop"目录。因此,命令也等价于
./bin/hdfs dfs -ls /user/hadoop

列出HDFS上的所有目录

./bin/hdfs dfs -ls

创建一个input目录

./bin/hdfs dfs -mkdir input

在创建input目录时,采用了相对路径形式。actually,这个input目录创建成功后,在HDFS中的完整路径是"/user/hadoop/input"。若在HDFS的根目录下创建一个名称为input的目录,需要使用如下命名

./bin/hdfs dfs -mkdir /input

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

./bin/hdfs dfs -rm -r /inout

其中:

  • -r参数表示删除"/input"目录及其子目录下的所有内容。若删除的一个目录包含了子目录,则必须使用“-r”参数,否则会执行失败(可以类比数据库中的级联cascade和限制restrict)

2.文件操作

在实际应用中,经常需要从本地文件系统向HDFS中上传文件 或 把HDFS中的文件下载到本地文件系统中。

本地上传到HDFS(-put)

firstly,使用vim编辑器,在本地Linux文件系统的"/home/hadoop"目录下创建一个文件myLocalFile.txt,输入任意单词做内容。例如

harder
stronger
freer

把本地文件系统的"/home/hadoop/myLocalFile.txt"上传到HDFS中的当前用户目录的input目录下,即上传到HDFS的"/user/hadoop/input/"目录下

./bin/hdfs dfs -put /home/hadoop/myLocalFile.txt input # Ubuntu中不以后缀名区分文件,仅供用户辨别这是个文本文件而非目录啥的

使用-ls命令查看文件是否成功上传到HDFS

./bin/hdfs dfs -ls input

查看HDFS中的myLocalFile.txt文件中的内容

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

在这里插入图片描述
在这里插入图片描述

HDFS中下载到本地(-get)

把HDFS中的myLocalFile.txt文件下载到本地文件系统中的"/home/hadoop/下载/"中

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

到本地文件系统查看下载下来的文件myLocalFile.txt

cd ~
cd 下载
ls
cat myLocalFile.txt

在这里插入图片描述

HDFS不同目录间的拷贝(-cp)

关于把文件从HDFS中的一个目录拷贝到HDFS中的另外一个目录。比如,若把HDFS的"/user/hadoop/input/myLocalFile.txt"文件,拷贝到HDFS的另外一个目录"/input"中(这个input目录位于HDFS根目录下)

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

在这里插入图片描述

二、利用Web界面管理HDFS

打开Linux自带的Firefox浏览器,输入localhost:9870即可看到HDFS的web管理界面
在这里插入图片描述

三、利用Java API和HDFS进行交互

Hadoop API文档
Hadoop采用Java语言开发,提供了Java API和HDFS进行交互。Hadoop不同的文件系统之间通过调用Java API进行交互,上文介绍的shell命令,本质上是Java API的应用。利用Java API进行交互,需要利用软件Eclipse编写Java程序。

1.在Ubuntu中安装Eclipse

eclipse官网
下载后可通过FileZilla或者其他方法传到linux系统中。以存在"~/Downloads"下,为例。

  • 解压缩
cd ~/Downloads
sudo tar -zxvf ./eclipse-4.7.0-Linux.gtk.x86_64.tar.gz -C /usr/local

把Downloads目录下的这个eclipse解压到C盘的"/usr/local"中

  • 启动eclipse
cd /usr/local/eclipse
./eclipse # 而后出现蓝色开启界面

2.使用eclipse开发调试HDFS Java程序

为了提高程序编写和调试效率,本教程采用eclipse工具编写Java程序。
本次小实践任务:
若在目录"hdfs://localhost:9000/user/hadoop"下有文件file1.txt,file2.txt,file3.txt,file4.abc和file5.abc。
需要从该目录中过滤出所有后缀名不为“.abc”的文件,对过滤之后的文件进行读取,并将这些文件的内容合并到文件"hdfs://localhost:9000/user/hadoop/merge.txt"中

(1)在eclipse中创建项目

启动eclipse后,提示设置工作空间workspace。可以直接选择默认设置“/home/hadoop/workspace”,点击ok
在这里插入图片描述

file→New→选择Java Project→finsh.
输入工程名→JRE选择之前安装的JDK
→next
在这里插入图片描述

(2)为项目添加需要的JAR包

Libraries→Add External JARS导入外部jar包
在这里插入图片描述
选择需要的jar包(注意是jar包,不要带上目录下的其他文件夹)→🆗
需要添加的jar包有:

  • “/usr/local/hadoop/share/hadoop/common”目录下的所有jar包(四个)
    在这里插入图片描述
  • “/usr/local/hadoop/share/hadoop/common/lib”目录下的所有jar包
  • “/usr/local/hadoop/share/hadoop/hdfs”目录下的所有jar包
  • “/usr/local/hadoop/share/hadoop/hdfs/lib”目录下的所有jar包
    全部添加后,点击finish.
    弹出的界面中选择Open Perspective打开视图
    在这里插入图片描述

(3)编写Java应用程序

eclipse工作界面左侧的"package explorer"面板中,右键点击刚才建好的工程名称“HDFSExample”→New→Class
在这里插入图片描述
类名为MergeFile,其他采用默认设置即可。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();
    }
}

(4)编译运行程序

注意:在Hadoop启动的基础上,再去编译运行程序

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

在HDFS的“/user/hadoop”目录下创建五个文件。
先在本地创建五个文件
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
在这里插入图片描述
用put命令把本地文件上传到HDFS中

./bin/hdfs dfs -put ./file1.txt /user/hadoop # 以file1.txt为例

在这里插入图片描述
编译运行
在这里插入图片描述
控制台输出
在这里插入图片描述
在HDFS中查看生成的merge.txt文件

cd /usr/local/hadoop
./bin/hdfs dfs -ls /user/hadoop
./bin/hdfs dfs -cat /user/hadoop/merge.txt

在这里插入图片描述

(5)应用程序的部署

把Java应用程序生成jar包,部署到Hadoop平台上运行。

  1. 在Hadoop安装目录中新建一个名为myapp的目录,用来存放我们自己编写的hadoop应用程序
cd /usr/local/hadoop
mkdir myapp
  1. 在eclipse工作界面左边的“package explorer”面板中的工程名称"HDFSExample"上右键,选择"Export"导出⇨选择runnable JAR file⇨next
  2. “Launch configuration”:设置生成的jar包被部署启动时运行的主类。本例中在下拉列表中选择刚才配置的类"MergeFile-HDFSExample"。
    “Export destination”:设置jar包要保存到哪个目录。本例中设置为“/usr/local/hadoop/myapp/HDFSExample.jar”,其中在myapp目录下对jar包起名为HDFSExample
    “Library handling”选择“Extra required libraries into generated JAR”。
    最后点击finish,然后无视之后的警告一路🆗即可。
    在这里插入图片描述
  3. 上述已完成了HDFSExample工程打包生成的HDFSExample.jar文件。
    在Linux系统中查看生成的HDFSExample.jar文件。
cd /usr/local/hadoop/myapp
ls

由于之前已经运行过一次程序并生成了merge.txt。因此,首先删除该文件

cd /usr/local/hadoop
./bin/hdfs dfs -rm /user/hadoop/merge/txt

在Linux系统中,使用hadoop jar命令运行程序

cd /usr/local/hadoop
./bin/hadoop jar ./myapp/HDFSExample.jar

再次执行完程序后,在HDFS中产看生成的merge.txt文件

cd /usr/local/hadoop
./bin/hdfs dfs -ls /user/hadoop
./bin/hdfs dfs -cat /user/hadoop/merge/txt

在这里插入图片描述

补充(练习代码文件)

  1. 写入文件
        import org.apache.hadoop.conf.Configuration;  
        import org.apache.hadoop.fs.FileSystem;
        import org.apache.hadoop.fs.FSDataOutputStream;
        import org.apache.hadoop.fs.Path;
 
        public class Chapter3 {    
                public static void main(String[] args) { 
                        try {
                                Configuration conf = new Configuration();  
                                conf.set("fs.defaultFS","hdfs://localhost:9000");
                                conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");
                                FileSystem fs = FileSystem.get(conf);
                                byte[] buff = "Hello world".getBytes(); // 要写入的内容
                                String filename = "test"; //要写入的文件名
                                FSDataOutputStream os = fs.create(new Path(filename));
                                os.write(buff,0,buff.length);
                                System.out.println("Create:"+ filename);
                                os.close();
                                fs.close();
                        } catch (Exception e) {  
                                e.printStackTrace();  
                        }  
                }  
        }
  1. 判断文件存在
        import org.apache.hadoop.conf.Configuration;
        import org.apache.hadoop.fs.FileSystem;
        import org.apache.hadoop.fs.Path;
 
        public class Chapter3 {
                public static void main(String[] args) {
                            try {
                                    String filename = "test";
 
                                    Configuration conf = new Configuration();
                                    conf.set("fs.defaultFS","hdfs://localhost:9000");
                                    conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");
                                    FileSystem fs = FileSystem.get(conf);
                                    if(fs.exists(new Path(filename))){
                                            System.out.println("文件存在");
                                    }else{
                                            System.out.println("文件不存在");
                                    }
                                    fs.close();
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                }
        } 
  1. 读取文件
        import java.io.BufferedReader;
        import java.io.InputStreamReader;
 
        import org.apache.hadoop.conf.Configuration;
        import org.apache.hadoop.fs.FileSystem;
        import org.apache.hadoop.fs.Path;
        import org.apache.hadoop.fs.FSDataInputStream;
 
        public class Chapter3 {
                public static void main(String[] args) {
                        try {
                                Configuration conf = new Configuration();
                                conf.set("fs.defaultFS","hdfs://localhost:9000");
                                conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");
                                FileSystem fs = FileSystem.get(conf);
                                Path file = new Path("test"); 
                                FSDataInputStream getIt = fs.open(file);
                                BufferedReader d = new BufferedReader(new InputStreamReader(getIt));
                                String content = d.readLine(); //读取文件一行
                                System.out.println(content);
                                d.close(); //关闭文件
                                fs.close(); //关闭hdfs
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                }
        }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值