1.开发环境

​ Win10+IDEA2019.2+JDK1.8+Maven

2.maven依赖

 	   <!-- hadoop-client Hadoop客户端maven依赖 注意版本-->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.7.3</version>
        </dependency>
        <!-- junit 用于单元测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>

3.log4j配置

# 全局日志配置
log4j.rootLogger=DEBUG, stdout
# MyBatis 日志配置
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

级别为DEBUG,在程序运行的时候可以打印出比较详细的信息,仅供学习时使用,需要创建一个log4j.properties文件,并将这个文件放在当前项目的classpath下

4.WindowsHadoop本地环境配置

由于Hadoop在编写时还依赖了一些C语言的本地库,在进行客户端编程的时候需要有本地环境依赖,本文使用的Hadoop版本为2.7.3,因此需要使用2.7.3的本地环境依赖。本地环境依赖需要下载Hadoop的源码进行编译,编译的过程比较浪费时间,可以在github中下载已经编译好的Hadoop Windows本地环境依赖。

winutils 链接:https://github.com/cdarlint/winutils

在这里插入图片描述

下载整个项目,在压缩包中根据自己的Hadoop版本选择对应版本。然后配置环境变量,Windos的配置如下:

系统变量中添加HADOOP_HOME,指向根据自己版本编译的Hadoop本地依赖
在这里插入图片描述
在系统变量中的PATH变量添加%HADOOP_HOME%\bin
在这里插入图片描述

5.Java客户端代码

注意在编写代码测试之前需要在Hadoop集群上启动HDFS,启动命令start-dfs.sh

package cn.xiaoyu;

import jdk.nashorn.internal.ir.CallNode;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.http.annotation.ThreadSafe;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

public class HDFSClientTest {

    // 定义全局的文件系统实例
    FileSystem fs = null;

    @Before
    public void setup() throws IOException {
        // 1.伪装成root用户
        System.setProperty("HADOOP_USER_NAME","root");
        // 2.创建配置对象
        Configuration conf = new Configuration();
        // 3.设置文件系统为hdfs 这里需要和服务器上的配置一致
        conf.set("fs.defaultFS","hdfs://192.168.56.77:9000/");
        // 4.获取Hadoop文件系统的实例
        fs = FileSystem.get(conf);
    }

    // 创建文件夹
    @Test
    public void testCreate() throws IOException {
        // 跟一个文件夹的路径 mkdirs可以直接创建多级文件夹
        // mkdir只能创建一级文件夹 
        boolean result = fs.mkdirs(new Path("/xxx"));
        System.out.println("mkdir => /xxx :" + result);
    }

    // 上传文件到HDFS
    @Test
    public void testUpload() throws IOException {
        //  src 本地文件路径(可以使用相对路径) dst hdfs路径
        fs.copyFromLocalFile(new Path("C:\\Users\\killer\\Desktop\\1.png"),new Path("/xxx"));
    }

    // 从HDFS下载文件到本地
    @Test
    public void testDownload() throws IOException {
        // 文件下载 src  hdfs路径  dst 本地文件路径
        // 会附带一个crc的校验文件
        fs.copyToLocalFile(new Path("/xxx/1.png"),new Path("1.png"));
    }

    // 删除HDFS上的文件和文件夹
    @Test
    public void testDelete() throws IOException {
        // 删除文件 这里的文件可以是 文件 也可以是文件夹 第二个参数为是否递归删除
        boolean result1 = fs.delete(new Path("/jdk-8u171-linux-x64.tar.gz"), true);
        System.out.println("delete => /jdk-8u171-linux-x64.tar.gz:" + result1);
        // 删除文件夹第二个参数为true会递归删除文件夹中的内容
        boolean result2 = fs.delete(new Path("/xxx"), true);
        System.out.println("delete => /xxx :" + result2);
    }

    // 遍历HDFS文件系统中的文件的信息
    @Test
    public void testList() throws IOException {
        // 返回的是一个远程迭代器 由于HDFS上文件有可能很多 如果直接全部返回 数据量过大可能会造成JVM内存溢出
        // 第一个参数 想要遍历路径 第二个参数 是否递归遍历
        RemoteIterator<LocatedFileStatus> files = fs.listFiles(new Path("/"), true);
        // 遍历
        while (files.hasNext()){
            // 获取一个文件状态对象 这个对象存储的就是文件信息了
            LocatedFileStatus fileStatus = files.next();
            // 打印文件信息
            // 路径
            System.out.println("path : " + fileStatus.getPath());
            // 文件所属的用户组
            System.out.println("group : " + fileStatus.getGroup());
            // 文件块的大小
            System.out.println("block size : " + fileStatus.getBlockSize());
            // 文件的所有者信息
            System.out.println("owner : " + fileStatus.getOwner());
            // 文件的大小 字节为单位
            System.out.println("len : " + fileStatus.getLen());
            //  访问时间
            System.out.println("access time : " + fileStatus.getAccessTime());
            // 修改时间
            System.out.println("modification time : " + fileStatus.getModificationTime());
            // 文件的权限 读 写 执行
            System.out.println("permission : " + fileStatus.getPermission());
            // 副本数
            System.out.println("replication : " + fileStatus.getReplication());
            // 是否为文件夹
            System.out.println("is directory : " + fileStatus.isDirectory());
            // 文件块的存放位置
            System.out.println("block locations : " + fileStatus.getBlockLocations());
            System.out.println("----------------------------");
        }
    }

    // 关闭连接
    @After
    public void clean() throws IOException {
        fs.close();
    }
}
  • HDFS的Java API使用还是比较易用的
  • 对于文件的遍历写的有问题,需要写一个递归方法实现
  • 还有一些比较有意思的API没有使用 create 、append、access包括一些权限相关的API
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐