HDFS API操作

1、客户端环境准备

1、将Windows 依赖文件夹,拷贝hadoop-3.1.0 到非中文路径。
注意windows依赖需要与虚拟机中的hadoop版本保持一致。如果你安装了3.1.0我这里有对应的依赖文件和微软运行库。
链接:Windows 依赖文件-hadoop-3.1.0
提取码:19nk
2、配置HADOOP_HOME 环境变量 。
在这里插入图片描述
  
3、配置Path 环境变量。
注意:如果环境变量不起作用,可以重启电脑试试
在这里插入图片描述
  
4、验证Hadoop 环境变量是否正常。双击hadoop-3.1.0\bin目录下的winutils.exe,如果报如下错误。说明缺少微软运行库。将上面链接压缩包里面的微软运行库安装包双击安装即可。
  

2、IDEA项目搭建

1、在IDEA 中创建一个Maven 工程,并导入如下相应的依赖坐标:

<dependencies> 
    <dependency> 
        <groupId>org.apache.hadoop</groupId> 
        <artifactId>hadoop-client</artifactId> 
        <version>3.1.3</version> 
    </dependency> 
    <dependency> 
        <groupId>junit</groupId> 
        <artifactId>junit</artifactId> 
        <version>4.12</version> 
    </dependency> 
    <dependency> 
        <groupId>org.slf4j</groupId> 
        <artifactId>slf4j-log4j12</artifactId> 
        <version>1.7.30</version> 
    </dependency> 
</dependencies>

  
在项目的src/main/resources 目录下,新建一个文件,命名为“log4j.properties”,在文件中填入以下内容:

log4j.rootLogger=INFO, stdout   
log4j.appender.stdout=org.apache.log4j.ConsoleAppender   
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout   
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n   
log4j.appender.logfile=org.apache.log4j.FileAppender   
log4j.appender.logfile.File=target/spring.log   
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout   
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

了解配置参数优先级(不限于hdfs-xx.xml):

  • 集群中的hdfs-default.xml -->集群中的hdfs.site.xml -->资源目录中的hdfs.site.xml -->代码中的configuration配置

  • 集群中的hdfs-default.xml:虚拟机中hadoop集群默认配置,如副本数量等

  • 集群中的hdfs.site.xml:用户配置的虚拟机中hadoop集群的相关配置

  • 资源目录中的hdfs.site.xml:IDEA项目下resources包中的配置
    在这里插入图片描述

  • 代码中的configuration配置:获取了API对象后对其进行的设置,如:
    在这里插入图片描述

  
2、创建HdfsClient 类(以下所有代码均放在该类中)
API操作大致也就三步:

  • 1.获取一个API对象
  • 2.执行相关操作命令(如文件的“增删改查”)
  • 3.关闭资源

以下代码为基本API结构,后面我们为了方便会把它改成一个内部方法

public class HdfsClient { 
 
    @Test 
    public void mkdirs() throws IOException,URISyntaxException,InterruptedException { 
        // 1 获取文件系统
        Configuration configuration = new Configuration();  
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop100:8020"), configuration,"user"); //在此处传入用户user
 
        // 2 创建目录 
        fs.mkdirs(new Path("/hello")); //hdfs中的文件目录

        // 3 关闭资源 
        fs.close(); 
    } 
}

  
API去操作HDFS 时,是有一个用户身份的。默认情况下,HDFS 客户端API 会采用Windows 默认用户访问HDFS,会报Permission denied错误。所以在访问HDFS 时,一定要配置用户。
在这里插入图片描述
  

3、HDFS 的API 实际操作

1、HDFS API对象获取和资源释放

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

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
public class HdfsClient {
    private FileSystem fs;//全局变量
    /**
     * 获取连接:初始化、连接集群
     */
    public void init(){
        //1.获取连接
        URI uri;
        try {
            //连接集群须使用hdfs(namenode地址)内部端口号
            uri = new URI("hdfs://hadoop100:8020");
        } catch (URISyntaxException e) {
            throw new RuntimeException("URI错误!\n"+e);
        }
        //创建一个配置文件
        Configuration configuration = new Configuration();
//        configuration.set();//配置一些相关属性如副本数量
        //还须指定连接的集群属于哪个用户,否则会报错 AccessControlException: Permission denied
        String user = "user";
        //获取到客户端对象
        try{
            fs = FileSystem.get(uri, configuration, user);
        }catch (Exception e){
            throw new RuntimeException("对象获取失败!\n"+e);
        }
    }

    /**
     * 关闭资源
     */
    public void close(){
        //3.关闭资源
        try {
            fs.close();
        }catch (IOException e){
            throw new RuntimeException("资源关闭失败!\n"+e);
        }
    }

  

2、创建文件目录

/**
     * 创建文件(目录)
     * @param filepath 创建文件(目录)的路径
     */
    public void mkdir(String filepath){
        init();
        try{
            fs.mkdirs(new Path(filepath));
        }catch (IOException e){
            throw new RuntimeException("创建文件(目录)失败!\n"+e);
        }finally {
            close();
        }

    }

  

3、上传文件(测试参数优先级)

/**
     * 使用API上传文件到HDFS
     * 配置参数优先级
     *      集群的hdfs-default.xml -->集群的hdfs.site.xml
     *      -->资源目录中hdfs.site.xml -->代码中configuration配置
     */
    public void put(String srcPath,String dstPath){
        init();
        try{
            //delsrc:表示上传后删除源路径
            //overwrite:表示目标(路径)文件存在时是否覆盖
            //path 源路径
            //path 目标路径
            fs.copyFromLocalFile(false,false, new Path(srcPath), new Path(dstPath));
        }catch (IOException e){
            throw new RuntimeException("文件(目录)上传失败!\n"+e);
        }finally {
            close();
        }
    }

将hdfs-site.xml 拷贝到项目的resources 资源目录下

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?> 
 
<configuration> 
	 <property> 
	 	<!-- 集群副本数量-->
	 	<name>dfs.replication</name>
	 	<value>1</value> 
	 </property> 
</configuration>

  
尝试将dfs.replication的值改为其他值然后上传文件,查看网页界面文件的副本数量
在这里插入图片描述
  

4、HDFS 文件下载

/**
     * 使用API下载文件到本地
     * @param delSrc    下载后是否删除源(路径)文件
     * @param srcPath   源路径
     * @param dstPath   目标路径
     * @param useRawLocalFileSystem 是否开启本地校验文件完整性
     */
    public void get(boolean delSrc,String srcPath,String dstPath, boolean useRawLocalFileSystem){
        init();
        try {
            fs.copyToLocalFile(delSrc, new Path(srcPath), new Path(dstPath),useRawLocalFileSystem);
        }catch (IOException e){
            throw new RuntimeException("文件(目录)下载失败!\n"+e);
        }finally {
            close();
        }
    }

注意:如果执行上面代码,下载不了文件,有可能是你电脑的微软支持的运行库少,需要安装一下微软运行库
  

5、HDFS 文件更名和移动

    /**
     * 使用API移动或更名文件
     * @param path  需要修改或移动的文件(目录)
     * @param path1 path1 改动后的结果
     */
    public void rename(String path, String path1){
        init();
        try{
            //path 需要修改或移动的文件(目录)
            //path1 改动后的结果
            fs.rename(new Path(path),new Path(path1));
        }catch (IOException e){
            throw new RuntimeException(e);
        }finally {
            close();
        }
    }

  

6、删除文件和目录

    /**
     * 使用API删除文件(目录)
     * @param path  要删除的路径
     * @param recursion 是否递归删除
     */
    public void delete(String path,boolean recursion){
        init();
        try {
            //删除文件
//            fs.delete(new Path(path),recursion);
            //删除非空目录
//            fs.delete(new Path(path));
            //删除非空目录
            fs.delete(new Path(path),recursion);
        }catch (IOException e){
            throw new RuntimeException("文件(目录)删除失败!\n"+e);
        }finally {
            close();
        }

    }

  

7、HDFS 查看文件详情

    /**
     * 获取与UI界面相同的文件(目录)参数
     * @param path
     * @param recursion
     */
    public void viewFileDetails(String path, boolean recursion){
        init();
        try{
            RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path(path),recursion);
            while (listFiles.hasNext()){
                LocatedFileStatus fileStatus = listFiles.next();
                System.out.println("==========="+fileStatus.getPath()+"===========");
                System.out.print(fileStatus.getPermission()+"\t");
                System.out.print(fileStatus.getOwner()+"\t");
                System.out.print(fileStatus.getGroup()+"\t");
                System.out.print(fileStatus.getLen()+"\t");
                System.out.print(fileStatus.getModificationTime()+"\t");
                System.out.print(fileStatus.getReplication()+"\t");
                System.out.print(fileStatus.getBlockSize()+"\t");
                System.out.print(fileStatus.getPath().getName());
                System.out.println();
                //获取块信息
                BlockLocation[] blockLocations = fileStatus.getBlockLocations();
                System.out.println("Block information: "+Arrays.toString(blockLocations));
                System.out.println();
            }
        }catch (IOException e){
            throw new RuntimeException(e);
        }finally {
            close();
        }
    }

  

8、判断是文件还是文件夹

    /**
     * 判断是文件还是文件夹
     * @param path
     */
    public void isFileOrDirectory(String path){
        init();
        try{
            FileStatus[] listStatus = fs.listStatus(new Path(path));
            for (FileStatus status : listStatus) {
                if (status.isFile()) {
                    System.out.println("File: "+status.getPath().getName());
                }else {
                    System.out.println("Directory: "+status.getPath().getName());
                }
            }
        }catch (IOException e){
            throw new RuntimeException(e);
        }finally {
            close();
        }
    }

使用单元测试调用指定方法进行测试

    @Test
    public void test(){
        String str2 = "/software/";
        delete(str2,false);
    }
}
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江韵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值