HDFS基本操作

本篇主要包括:HDFS概念、HDFS命令行操作、HDFS客户端操作,没有涉及到原理性知识,原理性知识将会在下一篇进行介绍。

HDFS概念

概念

​ HDFS,它是一个文件系统,用于存储文件,通过目录树来定位文件;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。

​ HDFS的设计适合一次写入,多次读出的场景,且不支持文件的修改。适合用来做数据分析,并不适合用来做网盘应用。

组成

  • NameNode负责管理整个文件系统的元数据,以及每一个路径(文件)所对应的数据块信息。
  • DataNode 负责管理用户的文件数据块,每一个数据块都可以在多个datanode上存储多个副本。
  • Secondary NameNode用来监控HDFS状态的辅助后台程序,每隔一段时间获取HDFS元数据的快照。

HDFS文件块大小

​ HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数( dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M

HDFS命令行操作

-ls: 显示目录信息

hadoop fs -ls /

-mkdir:在hdfs上创建目录

hadoop fs -mkdir -p /aaa/bbb/cc/dd

-moveFromLocal:从本地剪切粘贴到hdfs

hadoop fs - moveFromLocal /home/hadoop/a.txt /aaa/bbb/cc/dd

-appendToFile :追加一个文件到已经存在的文件末尾

hadoop fs -appendToFile a.txt /user/newDir/test.txt

-cat :显示文件内容

hadoop fs -cat /user/newDir/test.txt

-tail:显示一个文件的末尾

hadoop fs -tail /user/newDir/test.txt

-copyFromLocal:从本地文件系统中拷贝文件到hdfs路径去

hadoop fs -copyFromLocal ./jdk.tar.gz /aaa/

-copyToLocal:从hdfs拷贝到本地

hadoop fs -copyToLocal /aaa/jdk.tar.gz

-cp :从hdfs的一个路径拷贝到hdfs的另一个路径

hadoop fs -cp /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2

-mv:在hdfs目录中移动文件

hadoop fs -mv /aaa/jdk.tar.gz /

-get:等同于copyToLocal,就是从hdfs下载文件到本地

hadoop fs -get /aaa/jdk.tar.gz

-getmerge :合并下载多个文件,比如hdfs的目录 /aaa/下有多个文件:log.1, log.2,log.3,...

hadoop fs -getmerge /aaa/log.* ./log.sum

-put:等同于copyFromLocal

hadoop fs -put /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2

-rm:删除文件或文件夹

hadoop fs -rm -r /aaa/bbb/

-rmdir:删除空目录

hadoop fs -rmdir /aaa/bbb/ccc

-df :统计文件系统的可用空间信息

hadoop fs -df -h /

-du:统计文件夹的大小信息

hadoop fs -du -s -h /aaa/*

-count:统计一个指定目录下的文件节点数量

hadoop fs -count /aaa/

-setrep:设置hdfs中文件的副本数量

hadoop fs -setrep 3 /aaa/jdk.tar.gz

HDFS客户端操作

添加依赖

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>2.7.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.7.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs -->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-hdfs</artifactId>
    <version>2.7.2</version>
</dependency>

通过API操作HDFS

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;

import java.net.URI;

/**
 * @author sixiaojie
 * @date 2019-11-13 13:38
 */
public class HDFSClientDemo {
    public static void main(String[] args) throws Exception{
        //创建配置信息对象
        Configuration configuration = new Configuration();
        //获取文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.48.111:9000"),configuration,"root");

        //操作文件系统

        //上传本地数据到集群
        fs.copyFromLocalFile(new Path("E:\\test.png"),new Path("/user/sixj/test2.png"));
        //下载
        fs.copyToLocalFile(false,new Path("/user/sixj/test2.png"),new Path("E:\\test2.png"),true);
        //创建目录
        fs.mkdirs(new Path("/user/sixj/client"));
        //重命名文件或目录
        fs.rename(new Path("/user/sixj/test2.png"),new Path("/user/sixj/testRename.png"));
        //删除目录,如果是非空目录,参数2必须为true
        fs.delete(new Path("/user/sixj/test1.png"),true);
        //查看文件详情
        readFileAtHdfs(fs);
        //查看文件夹
        findAtHdfs(fs);
        //关闭fs
        fs.close();
    }

    /**
     * 查看文件详情
     * @param fs
     * @throws Exception
     */
    static void readFileAtHdfs(FileSystem fs) throws Exception{
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/user/sixj"), true);
        while (listFiles.hasNext()){
            LocatedFileStatus status = listFiles.next();
            // 文件名称
            System.out.println(status.getPath().getName());
            // 文件内容长度
            System.out.println(status.getLen());
            // 文件权限
            System.out.println(status.getPermission());
            //文件块的具体信息
            BlockLocation[] blockLocations = status.getBlockLocations();
            for (BlockLocation block : blockLocations) {
                System.out.println(block.getOffset());
                String[] hosts = block.getHosts();
                for (String host : hosts) {
                    System.out.println(host);
                }
            }
        }
    }

    /**
     * 获取查询路径下的文件状态信息
     * @param fs
     * @throws Exception
     */
    static void findAtHdfs(FileSystem fs) throws Exception {
        FileStatus[] listStatus = fs.listStatus(new Path("/user/sixj"));
        // 遍历所有文件状态
        for (FileStatus status : listStatus) {
            if (status.isFile()) {
                System.out.println("f--" + status.getPath().getName());
            } else {
                System.out.println("d--" + status.getPath().getName());
            }
        }

    }
}

如果在开发过程中出现这个异常:java.io.IOException: HADOOP_HOME or hadoop.home.dir are not set

​ 需要解压hadoop程序包到本地非中文目录,同时在你的环境变量中的系统变量中配置了HADOOP_HOME并且指向hadoop程序包的本目录即可,并且在系统变量的path中附加了%HADOOP_HOME%/bin(这里一定要指向到bin这一级才行),然后一定要重启电脑才行。

hadoop程序包下载地址:

win10:pan.baidu.com/s/1PYEyGRBb…

win7:pan.baidu.com/s/1up3G8lra…

通过IO流操作HDFS

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;

import java.io.*;
import java.net.URI;

/**
 * @author sixiaojie
 * @date 2019-11-13 17:30
 */
public class IOToHDFS {

    /**
     * 文件上传
     * 客户端通过输入流读取磁盘上文件,通过输出流上传到文件系统
     * @throws Exception
     */
    static void putFileToHDFS() throws Exception{
        //创建配置信息对象
        Configuration configuration = new Configuration();
        //获取文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.48.111:9000"),configuration,"root");
        //获取输出流
        FSDataOutputStream fos = fs.create(new Path("/user/sixj/hadoop-2.7.2.rar"));
        //获取输入流
        FileInputStream fis = new FileInputStream(new File("E:\\hadoop-2.7.2.rar"));
        try{
            //流对接
            IOUtils.copyBytes(fis,fos,4096,false);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeStream(fis);
            IOUtils.closeStream(fos);
        }
        //关闭fs
        fs.close();
    }

    /**
     * 文件下载
     * @throws Exception
     */
    static void getFileFromHDFS() throws Exception{
        //创建配置信息对象
        Configuration configuration = new Configuration();
        //获取文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.48.111:9000"),configuration,"root");
        //获取输入流
        FSDataInputStream fis = fs.open(new Path("/user/sixj/test.png"));
        //创建输出流
        FileOutputStream fos = new FileOutputStream(new File("E:\\download.png"));
        try{
            //流对接
            IOUtils.copyBytes(fis,fos,4096,false);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeStream(fis);
            IOUtils.closeStream(fos);
        }
        //关闭fs
        fs.close();
    }

    /**
     * 下载大文件的第一块数据
     */
    static void getFileFromHDFSSeek1() throws Exception{
        //创建配置信息对象
        Configuration configuration = new Configuration();
        //获取文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.48.111:9000"),configuration,"root");
        //获取输入流
        FSDataInputStream fis = fs.open(new Path("/user/sixj/hadoop-2.7.2.rar"));
        //创建输出流
        FileOutputStream fos = new FileOutputStream(new File("E:\\hadoop-2.7.2.rar.part1"));
        try{
            byte[] buf = new byte[1024];
            for (int i = 0; i < 128 * 1024; i++) {
                fis.read(buf);
                fos.write(buf);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeStream(fis);
            IOUtils.closeStream(fos);
        }
        //关闭fs
        fs.close();
    }
    /**
     * 下载大文件的第一块数据
     */
    static void getFileFromHDFSSeek2() throws Exception{
        //创建配置信息对象
        Configuration configuration = new Configuration();
        //获取文件系统
        FileSystem fs = FileSystem.get(new URI("hdfs://192.168.48.111:9000"),configuration,"root");
        //获取输入流
        FSDataInputStream fis = fs.open(new Path("/user/sixj/hadoop-2.7.2.rar"));
        //创建输出流
        FileOutputStream fos = new FileOutputStream(new File("E:\\hadoop-2.7.2.rar.part2"));
        try{
            byte[] buf = new byte[1024];
            for (int i = 128 * 1024; i < 2 * 128 * 1024; i++) {
                fis.read(buf);
                fos.write(buf);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            IOUtils.closeStream(fis);
            IOUtils.closeStream(fos);
        }
        //关闭fs
        fs.close();
    }
    public static void main(String[] args) throws Exception{
//        putFileToHDFS();
//        getFileFromHDFS();
//        getFileFromHDFSSeek1();
        getFileFromHDFSSeek2();
    }
}