Hadoop HDFS API 编程开发(使用Java)

本篇博客介绍使用Java API操作HDFS的方法。为本人的学习笔记。
学习参考视频教程:https://coding.imooc.com/class/301.html

方法

我们想要使用Java 来操作HDFS,就要先连接到HDFS文件系统,好在Hadoop 已经有了官方的jar包可以直接使用里面的类和方法。使用下面的定义的方法要首先创建一个maven项目,导入hadoop的依赖和junit的依赖。在pom.xml文件中的<dependencies>标签下增加下面的内容:

<dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>hadoop.version</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

注意,要根据你hadoop的版本来确定配置文件中hadoop.version 的具体值。

在开发前,请确保正确安装了Hadoop,并且已经启动了HDFS,具体的操作可以查看我上一篇博客。需要注意的是,关于HDFS操作的相关端口要记得全部开放,所有的端口信息如下所示:

参数描述默认配置文件例子值
fs.default.name.namenodenamenode RPC交互端口8020core-site.xmlhdfs://master:8020
dfs.http.addressNameNode web管理端口50070hdfs- site.xml0.0.0.0:50070
dfs.datanode.addressdatanode 控制端口50010hdfs -site.xml0.0.0.0:50010
dfs.datanode.ipc.addressdatanode的RPC服务器地址和端口50020hdfs-site.xml0.0.0.0:50020
dfs.datanode.http.addressdatanode的HTTP服务器和端口50075hdfs-site.xml0.0.0.0:50075
dfs.secondary.http.addresssecondary NameNode web管理端口50090hdfs-site.xml0.0.0.0:50090

如果在非生产环境下,比如只是为了学习,服务器是一个虚拟机,那么就可以偷个懒,直接把防火墙关闭了,所有端口就都开放了。也可以通过命令来开放这些端口,具体的操作方法见上一个博客。

示例代码

做好上面的步骤之后,就可以编写测试代码了,相关方法和注释见下面的代码示例:

package com.xjtu;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.util.Progressable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

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

public class JavaHadoopHDFSApiTest {
    // 定义HDFS的连接地址(这里要改成你自己的配置)
    public static String HDFS_PATH="hdfs://192.168.31.25:8020";
    FileSystem fileSystem=null;
    Configuration configuration=null;
    // 指定连接的用户是谁(这里要改成你自己的用户)
    String user="root";


    /**
     * 所有方法开始前都会运行这个方法,用于连接HDFS文件系统,获取FileSystem对象。
     * @throws URISyntaxException
     * @throws IOException
     * @throws InterruptedException
     */
    @Before
    public void setUp() throws URISyntaxException, IOException, InterruptedException {
        configuration=new Configuration();
        // 设置副本数目为 1 (我在开发时没有设置集群,只有一个机器,副本数量设置为1就行)
        configuration.set("dfs.replication","1");
        fileSystem=FileSystem.get(new URI(HDFS_PATH),configuration,user);
    }

    /**
     * 在HDFS上创建一个新的目录
     * @throws IOException
     */
    @Test
    public void mkdirs() throws IOException {
        String path="/qianqianjun/code";
        Boolean result=fileSystem.mkdirs(new Path(path));
        System.out.println(result);
    }

    /**
     * 读取HDFS文件上的一个文本的内容
     * @throws IOException
     */
    @Test
    public void text() throws IOException {
        String path="/qianqianjun/code/a.cpp";
        FSDataInputStream in=fileSystem.open(new Path(path));
        IOUtils.copyBytes(in,System.out,1024);
    }

    /**
     * 将HDFS上的一个文件重命名
     * @throws IOException
     */
    @Test
    public void rename() throws IOException {
        String oldpath="/love.cpp";
        String newpath="/love.txt";
        Boolean result=fileSystem.rename(new Path(oldpath),new Path(newpath));
        if (result){
            System.out.println("修改成功!");
        }else{
            System.out.println("修改失败!");
        }
    }

    /**
     * 将本地文件上传到HDFS
     * @throws IOException
     */
    @Test
    public void copyFromLocalFile() throws IOException {
    	// src 是本地文件,dst是将本地文件上传到HDFS之后的位置
        Path src=new Path("/home/qianqianjun/CODE/CPP/Clion/letcode/demo.cpp");
        Path dst=new Path("/demo.cpp");
        fileSystem.copyFromLocalFile(src,dst);
    }

    /**
     * 带有进度条的大文件上传实现。
     * @throws IOException
     */
    @Test
    public void copyFromLocalBigFile() throws IOException {
        String fileName="/home/qianqianjun/下载/deepin.com.qq.im_9.1.8deepin0_i386.deb";
        InputStream in=new BufferedInputStream(
                new FileInputStream(new File(fileName))
        );

        FSDataOutputStream out=fileSystem.create(new Path("/software/qq.deb"),
        new Progressable() {
            @Override
            public void progress() {
            	// 这里只实现了一个简单的功能,每上传4096字节,就输出一个“-”。
                System.out.print("-");
            }
        });
        IOUtils.copyBytes(in,out,4096);
    }

    /**
     * 在HDFS上创建一个文件,并写入内容。
     * @throws IOException
     */
    @Test
    public void create() throws IOException {
        String path="/love.cpp";
        FSDataOutputStream out=fileSystem.create(new Path(path));
        out.writeUTF("hello world!\n");
        out.writeUTF("best wishes\n");
        // 将缓冲区中的内容全部写入文件。
        out.flush();
        out.close();
    }

    /**
     * 将HDFS的文件下载到本地
     * @throws IOException
     */
    @Test
    public void download() throws IOException {
        Path src=new Path("/demo.cpp");
        Path dst=new Path("/home/qianqianjun/桌面/download.cpp");
        // src 是HDFS上文件的地址,dst是下载后的本地地址
        fileSystem.copyToLocalFile(src,dst);
    }

    /**
     * 列出对应HDFS目录的文件和文件夹
     * @throws IOException
     */
    @Test
    public void listFiles() throws IOException {
        Path path=new Path("/");
        FileStatus[] fileStatuses=fileSystem.listStatus(path);
        for(FileStatus file:fileStatuses){
            String isDir=file.isDirectory()? "文件夹":"文件";
            String permission=file.getPermission().toString();
            short replication=file.getReplication();
            long len=file.getLen();
            String fullpath=file.getPath().toString();
            System.out.printf("%s\t%s\t%d\t%d\t%s\n",isDir,permission,replication,len,fullpath);
        }
    }

    /**
     * 递归输出文件夹下面的文件。
     * @throws IOException
     */
    @Test
    public void listFilesRecursive() throws IOException {
        RemoteIterator<LocatedFileStatus> files=fileSystem.listFiles(new Path("/"),true);
        while (files.hasNext()){
            LocatedFileStatus file=files.next();
            String isDir=file.isDirectory()? "文件夹":"文件";
            String permission=file.getPermission().toString();
            short replication=file.getReplication();
            long len=file.getLen();
            String fullpath=file.getPath().toString();
            System.out.printf("%s\t%s\t%d\t%d\t%s\n",isDir,permission,replication,len,fullpath);
        }
    }

    /**
     * 获得HDFS上某个文件的块信息(开发中常用操作)
     * @throws IOException
     */
    @Test
    public void getFileBlockLocations() throws IOException {
        FileStatus fileStatus=fileSystem.getFileStatus(new Path("/software/qq.deb"));
        BlockLocation[] blocks= fileSystem.getFileBlockLocations(fileStatus,0,fileStatus.getLen());
        for(BlockLocation block:blocks){
            for(String name:block.getNames()){
                System.out.println(name+" : "+block.getOffset()+" : "+block.getLength());
            }
        }
    }


    /**
     * 删除HDFS上的一个文件或者目录
     * @throws IOException
     */
    @Test
    public void deleteHDFS() throws IOException {
        Boolean result=fileSystem.delete(new Path("/software"),true);
        System.out.println(result);
    }

    /***
     * 定义执行完一个方法之后的操作。
     */
    @After
    public void endUp(){
        configuration=null;
        fileSystem=null;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值