Java远程操作HDFS文件系统

目标:通过Java编程实现远程HDFS文件系统的增、删、改、查,并且解释原理。

一、准备工作

集群:搭建Hadoop集群,并且启动HDFS。详细过程可以参考:Hadoop-2.5.1安装步骤及异常处理

二、创建Maven工程

选择创建工程:

在这里插入图片描述

选择JDK版本,并勾选"create from archetype"选项,千万不要手贱选择“quick start”,选快速开启的话,创建的maven工程中是看不到src目录的!!!
在这里插入图片描述

然后选择next。

在下面的界面中,GroupId就是单位域名的反写,ArtifactId就是工程名。

在这里插入图片描述

填写好上面的项目后,进入到工程名设置,如下所示:

在这里插入图片描述

填写好工程名后,选择Finish就可以了。

三、开始编程

首先看一下每个简单功能的核心代码,最后会给出完整的源代码和pom.xml文件的内容。

1、查看

列出hdfs上所有的文件或文件夹

public static void listFiles() throws IOException {
    Configuration conf = new Configuration();
    conf.set("fs.defaultFS", "hdfs://vm-01:9000");
    FileSystem fs = FileSystem.newInstance(conf);
    // true 表示递归查找 ; false 表示不进行递归查找
    RemoteIterator<LocatedFileStatus> iterator = fs.listFiles(new Path("/"), true);
    while (iterator.hasNext()){
       LocatedFileStatus next = iterator.next();
       System.out.println(next.getPath());
    }

    System.out.println("-------------------------------------");
    final FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
    for (int i = 0; i < fileStatuses.length; i++) {
        FileStatus fileStatus = fileStatuses[i];
        System.out.println(fileStatus.getPath());
    }
}

注意,上面代码的"vm-01"是集群中master节点的主机名,也可以换成IP地址,只要确保代码运行的机器能够连接上master节点就行。

运行结果如下:

在这里插入图片描述

2、创建目录

在hdfs的根目录下创建test1文件夹

public static void mkdir() throws IOException {
    Configuration conf = new Configuration();
    conf.set("fs.defaultFS", "hdfs://vm-01:9000");
    FileSystem fs = FileSystem.newInstance(conf);
    fs.mkdirs(new Path("/test1"));

}

第一次运行的时候出现权限不允许的异常,异常信息如下:

在这里插入图片描述

在网上搜索了一下相关资料,原因是,远程操作会被认为没有登录,所以权限是other的组,也就是只有"r-x"权限,对于根目录没有写的权限,自然也就没有创建目录的权限了。

解决方式有三种:

  1. 修改hadoop的配置文件。

    ​  到服务器上修改hadoop的配置文件:conf/hdfs-core.xml, 找到 dfs.permissions 的配置项 , 将value值改为 false

    ​ 修改完貌似要重启下hadoop的进程才能生效

<property>
    <name>dfs.permissions</name>
    <value>false</value>
    <description>
        If "true", enable permission checking in HDFS.
        If "false", permission checking is turned off,
        but all other behavior is unchanged.
        Switching from one parameter value to the other does not change the mode,
        owner or group of files or directories.
    </description>
</property>
  1. 放开目录权限。

    ​ 放开根目录的权限 , 命令如下 :$ hadoop fs -chmod 777 /

  2. 更改windows的用户,或者配置vm参数。

    ​ 另外,可以将本机windows用户改为hadoop的用户,还可以在run configurations配置Arguments的Vm Arguments内容为-DHADOOP_USER_NAME=hadoop

我采用的是第三种方式解决的,在IDEA的run->edit Configurations中配置了vm option为“-DHADOOP_USER_NAME=hadoop”。

然后,再次运行上述程序。使用hdfs的命令可以看到根目录下多出了一个test1目录。

在这里插入图片描述

3、删除

删除hdfs上指定的文件

public static void removeFile() throws IOException {
    Configuration conf = new Configuration();
    conf.set("fs.defaultFS", "hdfs://vm-01:9000");
    FileSystem fs = FileSystem.newInstance(conf);
    fs.delete(new Path("/tmp"), true);
}

执行之前:在这里插入图片描述

执行上述代码之后:

在这里插入图片描述

可以看到/tmp目录已经不存在了。

4、上传

上传文件到hdfs中

public static void upload() throws IOException {
    Configuration conf = new Configuration();
    conf.set("fs.defaultFS", "hdfs://vm-01:9000");
    FileSystem fs = FileSystem.newInstance(conf);
    fs.copyFromLocalFile(new Path("hdfs_Study/src/main/resources/test.txt"), new Path("/"));
}

执行之后可以查看到hdfs的根目录下多出了一个test.txt文件,并且其中写有预先输入的内容。

在这里插入图片描述

5、下载

从hdfs下载文件到本地

public static void download() throws IOException {
    Configuration conf = new Configuration();
    conf.set("fs.defaultFS", "hdfs://vm-01:9000");
    FileSystem fs = FileSystem.newInstance(conf);
    fs.copyToLocalFile(new Path("/a.txt"), new Path("G://"));
}

注意:我是在windows上的IDEA中开发hdfs程序,所以涉及到下载文件到本地时,需要在windows上配置hadoop、相关环境变量和一些附属程序。

如果不做上述步骤的话会报下面的错误:

java.io.FileNotFoundException: java.io.FileNotFoundException: HADOOP_HOME and hadoop.home.dir are unset.

解决办法参看资料:由一个HADOOP_HOME and hadoop.home.dir are unset报错引起的window环境连接调试远程hadoop的一系列问题,hadoop版本 2.8

6、为什么不能更改HDFS上的文件?

HDFS涉及之初就是为了数据分析,一次创建多次查看,为了hdfs的高吞吐量,所以是不支持编辑修改hdfs上的文件。

可以先把文件下载到本地,然后进行修改,最后再上传到hdfs就可以了。

pom.xml文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <artifactId>hdfs_study</artifactId>
    <groupId>com.mucao</groupId>
    <version>1.0-SNAPSHOT</version>


    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.9.2</version>
        </dependency>
    </dependencies>

</project>

完整的源代码:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import java.io.*;

public class HDFS_Test {
    //列出hdfs上所有的文件或文件夹
    public static void listFiles() throws IOException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://vm-01:9000");
        FileSystem fs = FileSystem.newInstance(conf);
        // true 表示递归查找 ; false 表示不进行递归查找
        RemoteIterator<LocatedFileStatus> iterator = fs.listFiles(new Path("/"), true);
        while (iterator.hasNext()){
            LocatedFileStatus next = iterator.next();
            System.out.println(next.getPath());
        }
        System.out.println("-------------------------------------");
        final FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
        for (int i = 0; i < fileStatuses.length; i++) {
            FileStatus fileStatus = fileStatuses[i];
            System.out.println(fileStatus.getPath());
        }
    }

    //在hdfs的根目录下创建test1文件夹
    public static void mkdir() throws IOException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://vm-01:9000");
        FileSystem fs = FileSystem.newInstance(conf);
        fs.mkdirs(new Path("/test1"));
    }

    //删除hdfs上指定的文件
    public static void removeFile() throws IOException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://vm-01:9000");
        FileSystem fs = FileSystem.newInstance(conf);
        fs.delete(new Path("/tmp"), true);
    }

    //上传文件到hdfs中
    public static void upload() throws IOException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://vm-01:9000");
        FileSystem fs = FileSystem.newInstance(conf);
        fs.copyFromLocalFile(new Path("hdfs_Study/src/main/resources/test.txt"), new Path("/"));
    }

    //从hdfs下载文件到本地
    public static void download() throws IOException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://vm-01:9000");
        FileSystem fs = FileSystem.newInstance(conf);
        fs.copyToLocalFile(new Path("/a.txt"), new Path("G://"));
    }

    public static void main(String[] args) throws IOException {
        //listFiles();
        //mkdir();
        //removeFile();
        //upload();
        download();
    }
}

总结:

这篇文章算是梳理清楚了通过Java远程操作HDFS的过程,只涉及到操作,其中的原理暂时没有深入,留待以后研究吧。

参考资料:

JAVA操作HDFS案例

Java 访问 HDFS操作

由一个HADOOP_HOME and hadoop.home.dir are unset报错引起的window环境连接调试远程hadoop的一系列问题,hadoop版本 2.8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值