[toc]

Hadoop系列资源:
关注公众号:雨中散步撒哈拉,回复关键词:024

一、客户端环境准备

  1. 找到Windows依赖文件夹,拷贝hadoop-3.1.0到非中文路径(比如e:).

  2. 配置HADOOP_HOME环境变量
    image.png

  3. 配置Path环境变量。
    注意:如果环境变量不起作用,可以重启电脑试试。
    image.png

验证Hadoop环境变量是否正常。双击winutils.exe,如果报如下错误。说明缺少微软运行库(正版系统往往有这个问题)。再资料包里面有对应的微软运行库安装包双击安装即可。
image.png

二、IDEA创建项目

1. 创建HdfsClientDemo项目

在IDEA中创建一个Maven工程HdfsClientDemo

2. 修改pom文件

修改指定的maven环境下,要不然依赖全下到c盘!
image.png

导入相应的依赖坐标+日志添加

<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>

3. 创建日志配置文件

在项目的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

4. 编写代码

  1. 创建包名:com.liudd.hdfs
  2. 创建HdfsClient类
package com.liudd.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class HdfsClient {

    private FileSystem fs = null;
    private String hdfsPath = "hdfs://hadoop102:8020";
    private String linuxUser = "liudd";

    @Before
    public void init() throws IOException, URISyntaxException, InterruptedException {
        // 1 获取文件系统
        Configuration configuration = new Configuration();

        // FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration);
        fs = FileSystem.get(new URI(hdfsPath), configuration,linuxUser);
    }

    @Test
    public void testMkdirs() throws IOException{
        // 2 创建目录
        fs.mkdirs(new Path("/xiyou/huaguoshan/"));
    }

    @After
    public void destroy() throws IOException{

        // 3 关闭资源
        if (null != fs){
            fs.close();
        }
    }
}

5. 执行程序

image.png

image.png

注意:
客户端去操作HDFS时,是有一个用户身份的。默认情况下,HDFS客户端API会从采用Windows默认用户访问HDFS,会报权限异常错误。所以在访问HDFS时,一定要配置用户。

org.apache.hadoop.security.AccessControlException: Permission denied: user=56576, access=WRITE, inode="/xiyou/huaguoshan":liudd:supergroup:drwxr-xr-x

三、HDFS的API案例实操

1. HDFS文件上传(测试参数优先级)

package com.liudd.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class HdfsClient {

    private FileSystem fs = null;
    private String hdfsPath = "hdfs://hadoop102:8020";
    private String linuxUser = "liudd";

    @Before
    public void init() throws IOException, URISyntaxException, InterruptedException {
        // 1 获取文件系统
        Configuration configuration = new Configuration();
        
        // 配置文件优先级
        // 1. 代码中Configuration,进行设值参数(优先级最高)
        // 2. 项目下resources中的配置文件(第二)
        // 3. 远程Hadoop中的配置文件hdfs-site.yaml(第三)
        // 4. 远程Hadoop中的配置文件hdfs-default.yaml(第四)
        // configuration.set("dfs.replication", "2");

        // FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration);
        fs = FileSystem.get(new URI(hdfsPath), configuration,linuxUser);
    }


    @Test
    public void testCopyFromLocal() throws IOException{
	// 参数一:是否删除源文件
        // 参数二:是否覆盖远程文件
        // 参数三:本地文件路径
        // 参数四:远程文件路径
        fs.copyFromLocalFile(false, true, new Path("D:\\learn\\hadoop3.x\\sunwukong.txt"),
                new Path("/xiyou/huaguoshan"));
    }

    @After
    public void destroy() throws IOException{

        // 3 关闭资源
        if (null != fs){
            fs.close();
        }
    }
}

参数优先级
参数优先级排序(由高到低):

  1. 客户端代码中设置的值
  2. ClassPath下的用户自定义配置文件
  3. 然后是服务器的自定义配置(xxx-site.xml)
  4. 服务器的默认配置(xxx-default.xml)

2. HDFS文件下载

    @Test
    public void testCopyToLocal() throws IOException{
        // 参数一:是否删除源文件
        // 参数二:远程文件路径
        // 参数三:本地文件路径
        // 参数四:是否开启crc循环冗余校验(远程文件和本地文件是否一致检测)
        fs.copyToLocalFile(false, new Path("/xiyou/huaguoshan"),
                new Path("D:\\learn\\hadoop3.x\\sunwukong2.txt"), true);
    }

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

3. HDFS文件更名和移动

    @Test
    public void testReName() throws Exception{
        // 参数一:源文件路径
        // 参数二:目标文件路径

        // 修改名称
//        fs.rename(new Path("/xiyou/huaguoshan/sunwukong.txt"), new Path("/xiyou/huaguoshan/sunwukong2.txt"));

        // 移动目录并修改名称
//        fs.rename(new Path("/xiyou/huaguoshan/sunwukong2.txt"), new Path("/xiyou/tianting/sunwukong11.txt"));

        // 目录改名
        fs.rename(new Path("/xiyou/tianting"), new Path("/xiyou/titing2"));
    }

4. HDFS文件详情查看

查看文件名称、权限、长度、块信息

@Test
    public void testListFiles() throws Exception{
        // 参数一:文件路径
        // 参数二:是否递归
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
        while (listFiles.hasNext()) {
            LocatedFileStatus fileStatus = listFiles.next();

            System.out.println("========" + fileStatus.getPath() + "=========");
            System.out.println(fileStatus.getPermission());
            System.out.println(fileStatus.getOwner());
            System.out.println(fileStatus.getGroup());
            System.out.println(fileStatus.getLen());
            System.out.println(fileStatus.getModificationTime());
            System.out.println(fileStatus.getReplication());
            System.out.println(fileStatus.getBlockSize());
            System.out.println(fileStatus.getPath().getName());

            // 获取块信息
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
            System.out.println(Arrays.toString(blockLocations));
        }
    }

image.png

5. HDFS文件和文件夹判断

    @Test
    public void testListStatus() throws Exception{
        // 参数一:文件路径
        FileStatus[] listStatus = fs.listStatus(new Path("/"));
        for (FileStatus fileStatus : listStatus) {
            // 如果是文件
            if (fileStatus.isFile()) {
                System.out.println("文件:"+fileStatus.getPath().getName());
            }else {
                System.out.println("文件夹:"+fileStatus.getPath().getName());
            }
        }
    }

image.png

6. HDFS删除文件和目录

    @Test
    public void testDelete() throws Exception{
        // 参数一:文件路径
        // 参数二:是否递归

        // 删除空文件夹
//        fs.delete(new Path("/xiyou/huaguoshan"), false);

        // 删除文件
//        fs.delete(new Path("/xiyou/titing2/sunwukong11.txt"), false);

        // 递归删除文件和文件夹
        fs.delete(new Path("/xiyou"), true);
    }

附录

整体测试案例

package com.liudd.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.After;
import org.junit.Before;
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 = null;
    private String hdfsPath = "hdfs://hadoop102:8020";
    private String linuxUser = "liudd";

    @Before
    public void init() throws IOException, URISyntaxException, InterruptedException {
        // 1 获取文件系统
        Configuration configuration = new Configuration();

        // 配置文件优先级
        // 1. 代码中Configuration,进行设值参数(优先级最高)
        // 2. 项目下resources中的配置文件(第二)
        // 3. 远程Hadoop中的配置文件hdfs-site.yaml(第三)
        // 4. 远程Hadoop中的配置文件hdfs-default.yaml(第四)
        // configuration.set("dfs.replication", "2");

        // FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration);
        fs = FileSystem.get(new URI(hdfsPath), configuration,linuxUser);
    }

    @Test
    public void testMkdirs() throws IOException{
        // 2 创建目录
        fs.mkdirs(new Path("/xiyou/huaguoshan/"));
    }

    @Test
    public void testCopyFromLocal() throws IOException{
        // 参数一:是否删除源文件
        // 参数二:是否覆盖远程文件
        // 参数三:本地文件路径
        // 参数四:远程文件路径
        fs.copyFromLocalFile(false, true, new Path("D:\\learn\\hadoop3.x\\sunwukong.txt"),
                new Path("/xiyou/huaguoshan"));
    }


    @Test
    public void testCopyToLocal() throws IOException{
        // 参数一:是否删除源文件
        // 参数二:远程文件路径
        // 参数三:本地文件路径
        // 参数四:是否开启crc循环冗余校验(远程文件和本地文件是否一致检测)
        fs.copyToLocalFile(false, new Path("/xiyou/huaguoshan"),
                new Path("D:\\learn\\hadoop3.x\\sunwukong2.txt"), true);
    }





    @Test
    public void testReName() throws Exception{
        // 参数一:源文件路径
        // 参数二:目标文件路径

        // 修改名称
//        fs.rename(new Path("/xiyou/huaguoshan/sunwukong.txt"), new Path("/xiyou/huaguoshan/sunwukong2.txt"));

        // 移动目录并修改名称
//        fs.rename(new Path("/xiyou/huaguoshan/sunwukong2.txt"), new Path("/xiyou/tianting/sunwukong11.txt"));

        // 目录改名
        fs.rename(new Path("/xiyou/tianting"), new Path("/xiyou/titing2"));
    }


    @Test
    public void testListFiles() throws Exception{
        // 参数一:文件路径
        // 参数二:是否递归
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
        while (listFiles.hasNext()) {
            LocatedFileStatus fileStatus = listFiles.next();

            System.out.println("========" + fileStatus.getPath() + "=========");
            System.out.println(fileStatus.getPermission());
            System.out.println(fileStatus.getOwner());
            System.out.println(fileStatus.getGroup());
            System.out.println(fileStatus.getLen());
            System.out.println(fileStatus.getModificationTime());
            System.out.println(fileStatus.getReplication());
            System.out.println(fileStatus.getBlockSize());
            System.out.println(fileStatus.getPath().getName());

            // 获取块信息
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
            System.out.println(Arrays.toString(blockLocations));
        }
    }



    @Test
    public void testListStatus() throws Exception{
        // 参数一:文件路径
        FileStatus[] listStatus = fs.listStatus(new Path("/"));
        for (FileStatus fileStatus : listStatus) {
            // 如果是文件
            if (fileStatus.isFile()) {
                System.out.println("文件:"+fileStatus.getPath().getName());
            }else {
                System.out.println("文件夹:"+fileStatus.getPath().getName());
            }
        }
    }

    @Test
    public void testDelete() throws Exception{
        // 参数一:文件路径
        // 参数二:是否递归

        // 删除空文件夹
//        fs.delete(new Path("/xiyou/huaguoshan"), false);

        // 删除文件
//        fs.delete(new Path("/xiyou/titing2/sunwukong11.txt"), false);

        // 递归删除文件和文件夹
        fs.delete(new Path("/xiyou"), true);
    }

    @After
    public void destroy() throws IOException{

        // 3 关闭资源
        if (null != fs){
            fs.close();
        }
    }
}

Q.E.D.


只有创造,才是真正的享受,只有拚搏,才是充实的生活。