2022-07-03 HDFS概述、Shell与API操作

Hadoop搭建完全分布式(非高可用)

一、HDFS概述

  1. 组成架构
    在这里插入图片描述
    (1) NameNode: 存储文件的元数据以及每个文件的快列表和块所在的DataNode;
    (2)DataNode: 存储文件块数据以及校验和;
    (3) Secondary NameNode: 每隔一段时间对NameNode元数据进行备份;
  2. HDFS文件块大小
    HDFS中的文件在物理上是分块(Block)存储,可以通过参数dfs.blocksize(hdfs-default.xml)配置,在Hadoop2.x以后的版本中,默认块大小是128M。可以根据磁盘传输速率(mb/s)配置最接近的块大小。

二、HDFS的Shell操作

  1. 基本语法:hdfs dfs 操作命令

  2. 上传操作:

    语法											说明
    hdfs dfs -moveFromLocal local hdfs			将local剪切到hdfs中
    hdfs dfs -appendToFile local-file hdfs		将local-file的内容追加到hdfs-file中
    hdfs dfs -put local hdfs					将local复制一份到hdfs中
    
  3. 下载操作:

    语法											说明
    hdfs dfs -get hdfs local					将hdfs复制一份到local
    hdfs dfs -getmerge hdfs-files local-file	将hdfs-files的内容合并在一起,下载到本地,需要为合并后的文件命名
    
  4. HDFS直接操作(类Linux命令):

    语法													说明
    hdfs dfs -ls hdfs-path								展示某一文件信息或者某一目录下的文件列表信息
    hdfs dfs -mkdir [-p] hdfs-path						创建目录,-p可以递归创建多级目录
    hdfs dfs -cat hdfs-file								显示文件内容
    hdfs dfs -chmod 744 hdfs-file						改变文件权限
    hdfs dfs -chmod ([ugo]|a)[+-=][rwx] hdfs-file		改变文件权限
    hdfs dfs -chown user-name[:group-name] hdfs-file	改变文件所属用户和用户组
    hdfs dfs -cp hdfs-src hdfs-dest						复制
    hdfs dfs -mv hdfs-src hdfs-dest						移动+改名
    hdfs dfs -head hdfs-file							查看文件开头内容
    hdfs dfs -tail hdfs-file							查看文件结尾内容
    hdfs dfs -rm -r file-or-folder						删除文件或者文件夹
    hdfs dfs -rmdir empty-folder						删除空目录
    hdfs dfs -setrep hdfs-file							设置文件的副本数
    

三、HDFSJava API操作

  1. Windows开发环境准备
    (1) 将依赖下载并放置到任意位置上

    # 也可自行到github上下载
    链接:https://pan.baidu.com/s/1cmrKssqrGlg0REw5RGMNdw 
    提取码:ehh7 
    

    (2) 将依赖目录下的hadoop.dllwinutils.exe拷贝到C:\Windows\System32\
    (3) 配置环境变量HADOOP_HOMEPATH

    变量名称				说明								例子
    HADOOP_HOME			依赖路径							D:\moudle\hadoop-3.1.0
    PATH				PATH后添加:%HADOOP_HOME%\bin	PATH后添加:%HADOOP_HOME%\bin
    

    (4) 创建工程,引入依赖

    <dependencies>
    	<!-- junit测试依赖坐标 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- 日志依赖坐标 -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.12.0</version>
        </dependency>
        <!-- hadoop依赖坐标 -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.1.3</version>
        </dependency>
    </dependencies>
    

    (5) 在resources目录下创建log4j的配置文件

    <!-- 配置文件名为:log4j2.xml -->
    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="error" strict="true" name="XMLConfig">
        <Appenders>
            <!-- 类型名为Console,名称为必须属性 -->
            <Appender type="Console" name="STDOUT">
                <!-- 布局为PatternLayout的方式,
                输出样式为[INFO] [2018-01-22 17:34:01][org.test.Console]I'm here -->
                <Layout type="PatternLayout"
                        pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss}][%c{10}]%m%n" />
            </Appender>
    
        </Appenders>
    
        <Loggers>
            <!-- 可加性为false -->
            <Logger name="test" level="info" additivity="false">
                <AppenderRef ref="STDOUT" />
            </Logger>
    
            <!-- root loggerConfig设置 -->
            <Root level="info">
                <AppenderRef ref="STDOUT" />
            </Root>
        </Loggers>
    </Configuration>
    
  2. API操作
    要导入的包为:

    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.*;
    import java.net.URI;
    

    (1) 获取HDFS客户端对象,所有的API操作都必须基于该对象

    // NameNode的通信地址
    URI uri = URI.create("hdfs://hadoop101:9820");
    /*
    	配置对象
    	默认会从resources目录下读取配置文件:各种-site.xml文件
    	如果没有读取到配置文件,采用节点上的配置
    	也可以通过conf.set(key, value)方法指定配置
    	配置优先级:conf.set(key, value) > resources > 节点上的配置 > 默认配置
    */
    Configuration conf = new Configuration();
    // 操作用户
    String user = "soro";
    // 获取客户端对象
    FileSystem fs = FileSystem.get(uri, conf, user);
    
    /*
    	todo
    */    
    
    // 释放资源
    fs.close();
    

    (2) 上传

    /**
    * fs.copyFromLocalFile(delSrc, overwrite, src, dst);
    * 参数解读:
    *  delSrc: 
    *          boolean, 是否删除源文件
    *          true=>删除、false=>不删除
    *  overwrite:
    *          boolean, 当hdfs中已经存在要上传文件时,是否使用新文件覆盖旧文件
    *          true=>删除,false=>不删除
    *  src: 
    *          要上传的文件
    *  dest: 
    *          文件上传至hdfs的位置,需指定文件名
    */
    

    (3) 下载

    /**
     * fs.copyToLocalFile(delSrc, src, dst, useRawLocalFileSystem);
     * 参数解读:
     *  delSrc:
     *          boolean, 是否删除源文件
     *          true=>删除、false=>不删除
     *  src:
     *          要下载的文件
     *  dst:
     *          文件下载至本地的位置,需指定文件名
     *  useRawLocalFileSystem:
     *          是否连同校验文件一并下载到本地
     *          true=>不下载, false=>下载
     */
    

    (4) 删除

    /**
     * fs.delete(f, recursive);
     * 参数解读:
     *  f:
     *          要删除的文件或者目录
     *  recursive:
     *          boolean,是否递归删除
     *          true=>递归删除,false=>不递归删除
     */
    

    (5) 文件更名和移动

    /**
     * fs.rename(src, dst)
     * 参数解读:
     *  src: 
     *          源文件
     *  dst: 
     *          移动或者改名后的文件
     */
    

    (6) 获取文件详细信息

    /**
     * fs.listFiles(root, recursive)
     * 参数解读:
     *  root:
     *          根目录,从这个目录开始找文件
     *  recursive:
     *          boolean,是否递归找文件
     *          true=>递归,false=>不递归
     */
    RemoteIterator<LocatedFileStatus> iterator = fs.listFiles(new Path("/"), true);
    while (iterator.hasNext()){
        // 文件信息对象
        LocatedFileStatus fileStatus = iterator.next();
        
        // 可以使用文件信息的getXXX()方法,获取文件的详细信息
        // todo
        
        // 获取文件的块信息
        BlockLocation[] blockLocations = fileStatus.getBlockLocations();
        
        // 可以调用每一个BlockLocation对象的getXXX()方法获取块的详细信息
        // todo
    }
    

    (7) 判断文件是否为目录
    获取到文件的FileStatus对象,调用其中的isDirectory()isFile()方法进行判断,获取方法有:
    powershell fs.listStatus() fs.listFiles(new Path("/"), true).next() fs.getFileStatus(new Path("path"))
    3. 封装HDFS客户端对象,简化部分操作
    (1) 封装类名为:FSSharper

    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.FSDataInputStream;
    import org.apache.hadoop.fs.FSDataOutputStream;
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.io.IOUtils;
    import java.io.IOException;
    import java.net.URI;
    
    
    /**
     * 简化获取FileSystem类的用法
     */
    public class FSSharper {
        /**
         * 异常类,把众多的其他异常简化为一个异常类
         */
        public static class FSSharperException extends Exception{
            public FSSharperException(String tip){
                super(tip);
            }
    
            /**
             * 抛出异常的静态方法
             * @param tip 异常的提示信息
             * @throws FSSharperException
             */
            public static void throwException(String tip) throws FSSharperException {
                throw new FSSharperException(tip);
            }
        }
    
        // 文件系统对象
        private FileSystem fs = null;
        // 输出流
        private FSDataOutputStream fsDataOutputStream = null;
        // 输入流
        private FSDataInputStream fsDataInputStream = null;
    
    
        /**
         * 构造方法
         * @param conf 配置对象
         * @throws FSSharperException
         */
        public FSSharper(Configuration conf) throws FSSharperException {
            try {
                fs = FileSystem.get(conf);
            } catch (IOException e) {
                FSSharperException.throwException("异常发生于:public FSSharper(Configuration conf){...}");
            }
        }
    
        /**
         * 构造方法
         * @param uriString 文件系统对象要连接的址
         * @param conf  配置对象
         * @param user  用哪一个用户连接
         * @throws FSSharperException
         */
        public FSSharper(String uriString, Configuration conf, String user) throws FSSharperException {
            try {
                fs = FileSystem.get(URI.create(uriString), conf, user);
            } catch (Exception e) {
                FSSharperException.throwException("错误发生于:public FSSharper(String uriString, Configuration conf, String user){...}");
            }
        }
    
        /**
         * 利用FileSystem对象创建文件的输出流
         * @param path  文件路径
         * @param overwrite 如果path已经存在,是否要覆盖,true表示覆盖,false表示不覆盖
         * @return  输出流
         * @throws FSSharperException
         */
        public FSDataOutputStream getOutputStream(String path, boolean overwrite) throws FSSharperException {
            if (fsDataOutputStream != null) return fsDataOutputStream;
            try {
                fsDataOutputStream = fs.create(new Path(URI.create(path)), overwrite);
            } catch (Exception e) {
                FSSharperException.throwException("错误发生于:public FSDataOutputStream getOutputStream(String path, boolean overwrite){...}");
            }
            return fsDataOutputStream;
        }
    
        /**
         * 利用FileSystem对象创建文件的输入流
         * @param path  文件路径
         * @return  输入流
         * @throws FSSharperException
         */
        public FSDataInputStream getInputStream(String path) throws FSSharperException {
            if (fsDataInputStream != null) return fsDataInputStream;
            try {
                fsDataInputStream = fs.open(new Path(URI.create(path)));
            } catch (IOException e) {
                FSSharperException.throwException("错误发生于:public FSDataInputStream getInputStream(String path){...}");
            }
            return fsDataInputStream;
        }
    
        /**
         * 获取FileSystem对象
         * @return 文件系统对象
         */
        public FileSystem getFs() {
            return fs;
        }
    
        /**
         * 获取创建该文件系统对象的配置对象
         * @return  配置对象
         */
        public Configuration getConf(){
            return fs.getConf();
        }
    
        /**
         * 释放创建的输出流、输入流对象
         */
        public void closeStreams(){
            IOUtils.closeStreams(fsDataOutputStream, fsDataInputStream);
            fsDataOutputStream = null;
            fsDataInputStream = null;
        }
    
        /**
         * 释放文件系统对象的资源
         */
        public void close(){
            IOUtils.closeStream(fs);
            fs = null;
        }
    
        /**
         * 释放所有资源
         */
        public void closeAll(){
            closeStreams();
            close();
        }
    }
    

    (2) 使用示例

       public static void main(String[] args) {
           // 创建FSSharper 对象
           FSSharper fsSharper = null;
           try {
               fsSharper = new FSSharper(new Configuration());
               // 获取客户端连接对象
               FileSystem fs = fsSharper .getFs();
    
            /*
            * todo
            */
            
           } catch (FSSharper.FSSharperException e) {
               e.printStackTrace();
           }finally {
               // 释放资源
               fsSharper .closeAll();
           }
       }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值