使用java操作HDFS

2023-10-08 大数据

创建Maven工程,引入依赖,注意版本号保持和Hadoop安装的版本一致。

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

在D盘新建user.txt文件,使用java代码上传到HDFS中

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;

public static void main(String[] args) throws IOException {
    // 创建一个配置对象
    Configuration conf = new Configuration();
    // 指定HDFS地址
    conf.set("fs.defaultFS","hdfs://192.168.133.101:9000");
    // 获取操作HDFS的对象
    FileSystem fileSystem = FileSystem.get(conf);

    // 获取HDFS文件系统的输出流
    FSDataOutputStream fos = fileSystem.create(new Path("/user.txt"));
    // 获取本地文件输出流
    FileInputStream fis = new FileInputStream("D:\\user.txt");
    // 上传文件
    IOUtils.copyBytes(fis,fos,1024,true);
}

执行代码,发现报错,提示权限拒绝,说明windows中的这个用户没有权限向HDFS中写入数据。

解决办法有两个,第一种是去掉hdfs的用户权限检验机制,通过在hdfs-site.xml中配置dfs.permissions.enabled为false即可;第二种是把代码打包到linux中执行。这里为了测试方便,我们采用第一种方法

[root@bigdata01 hadoop-3.2.3]# sbin/stop-all.sh #先停止Hadoop集群
[root@bigdata01 hadoop-3.2.3]# vi etc/hadoop/hdfs-site.xml 

修改后的文件内容如下

<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
    <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>bigdata01:50090</value>
    </property>
    <property>
        <name>dfs.permissions.enabled</name>
        <value>false</value>
    </property>
</configuration>

然后再重新运行Hadoop,执行代码测试能够正常执行。

# slf4j日志配置

我们在执行代码的时候会发现输出了很多红色的警告信息,虽然不影响代码执行,但是看起来很碍眼。

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.3</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>2.0.3</version>
</dependency>

resource目录下新建log4j.properties文件

log4j.rootLogger=info,stdout

log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR

# IDEA报错解决

[WARN ] 2022-10-11 21:36:13,655 method:org.apache.hadoop.util.Shell.<clinit>(Shell.java:693)
Did not find winutils.exe: {}
java.io.FileNotFoundException: java.io.FileNotFoundException: HADOOP_HOME and hadoop.home.dir are unset. -see https://wiki.apache.org/hadoop/WindowsProblems
	at org.apache.hadoop.util.Shell.fileNotFoundException(Shell.java:548)
	at org.apache.hadoop.util.Shell.getHadoopHomeDir(Shell.java:569)
	at org.apache.hadoop.util.Shell.getQualifiedBin(Shell.java:592)

出现以上错误不要慌,windows也需要安装Hadoop才能用,直接复制错误搜索安装步骤安装Hadoop即可,输入hadoop version出现以下字符代表正常

PS D:\Desktop> hadoop version
Hadoop 3.2.3
Source code repository https://github.com/apache/hadoop -r abe5358143720085498613d399be3bbf01e0f131
Compiled by ubuntu on 2022-03-20T01:18Z
Compiled with protoc 2.5.0
From source with checksum 39bb14faec14b3aa25388a6d7c345fe8
This command was run using /D:/develop/hadoop-3.2.3/share/hadoop/common/hadoop-common-3.2.3.jar

# 文件上传与下载

public static void main(String[] args) throws IOException {
    // 创建一个配置对象
    Configuration conf = new Configuration();
    // 指定HDFS地址
    conf.set("fs.defaultFS","hdfs://192.168.133.101:9000");
    // 获取操作HDFS的对象
    FileSystem fileSystem = FileSystem.get(conf);
    // 调用文件上传与下载方法
    put(fileSystem);
    get(fileSystem);
}

文件上传

private static void put(FileSystem fileSystem) throws IOException {
    // 获取HDFS文件系统的输出流
    FSDataOutputStream fos = fileSystem.create(new Path("/user.txt"));
    // 获取本地文件输出流
    FileInputStream fis = new FileInputStream("D:\\user.txt");
    // 上传文件:通过工具类把输入流拷贝到输出流里面,实现本地文件上传到HDFS
    IOUtils.copyBytes(fis,fos,1024,true);
}

文件下载

private static void get(FileSystem fileSystem) throws IOException {
    // 获取HDFS文件系统的输出流
    FSDataInputStream fis = fileSystem.open(new Path("/README.txt"));
    // 获取本地文件输出流
    FileOutputStream fos = new FileOutputStream("D:\\README.txt");
    IOUtils.copyBytes(fis,fos,1024,true);
}

# 文件删除

目录也可以删除,如果需要递归删除,第二个参数需要设置为true,如果是删除文件或空目录,第二个参数会被忽略

private static void del(FileSystem fileSystem) throws IOException {
    // 目录也可以删除,如果需要递归删除,第二个参数需要设置为true,如果是删除文件或空目录,第二个参数会被忽略
    boolean flag = fileSystem.delete(new Path("/user.txt"), true);
    if (flag) {
        System.out.println("删除成功");
    }else {
        System.err.println("删除失败");
    }
}
上次更新: 4 个月前