HDFS的JAVA API操作

配置Windows下Hadoop环境

在windows上做HDFS客户端应用开发,需要设置Hadoop环境,而且要求是windows平台编译的Hadoop,不然会报以下的错误:
缺少winutils.exe
Could not locate executable null \bin\winutils.exe in the hadoop binaries
缺少hadoop.dll
Unable to load native-hadoop library for your platform… using builtin-Java classes where applicable
搭建步骤:
第一步:将已经编译好的Windows版本Hadoop解压到到一个没有中文没有空格的路径下面
第二步:在windows上面配置hadoop的环境变量: HADOOP_HOME,并将%HADOOP_HOME%\bin添加到path中

第三步:把hadoop2.7.5文件夹中bin目录下的hadoop.dll文件放到系统盘: C:\Windows\System32 目录
第四步:关闭windows重启
11.3.导入Maven依赖

<dependencies>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>2.7.5</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>2.7.5</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-hdfs</artifactId>
        <version>2.7.5</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-mapreduce-client-core</artifactId>
        <version>2.7.5</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

使用文件系统方式访问数据

涉及的主要类
在java中操作HDFS,主要涉及以下Class:
Configuration:该类的对象封转了客户端或者服务器的配置;
FileSystem:该类的对象是一个文件系统对象,可以用该对象的一些方法来对文件进行操作,通过FileSystem的静态方法get获得该对象。
FileSystem fs = FileSystem.get(conf);
get方法从conf中的一个参数 fs.defaultFS的配置值判断具体是什么类型的文件系统。如果我们的代码中没有指定fs.defaultFS,并且工程classpath下也没有给定相应的配置,conf中的默认值就来自于hadoop的jar包中的core-default.xml,默认值为: file:///,则获取的将不是一个DistributedFileSystem的实例,而是一个本地文件系统的客户端对象

hdfs访问权限控制

HDFS权限模型和Linux系统类似。每个文件和目录有一个所有者(owner)和一个组(group)。文件或目录对其所有者、同组的其他用户以及所有其他用户(other)分别有着不同的权限。对文件而言,当读取这个文件时需要有r权限,当写入或者追加到文件时需要有w权限。对目录而言,当列出目录内容时需要具有r权限,当新建或删除子文件或子目录时需要有w权限,当访问目录的子节点时需要有x权限。但hdfs的文件权限需要开启之后才生效,否则在HDFS中设置权限将不具有任何意义!
HDFS的权限设置是通过hdfs-site.xml文件来设置,在搭建Hadoop集群时,将HDFS的权限关闭了,所以对HDFS的任何操作都不会受到影响的。
接下来我们将HDFS的权限开启,测试下HDFS的权限控制。
1.停止hdfs集群,在node1机器上执行以下命令

stop-dfs.sh
  1. 修改node1机器上的hdfs-site.xml当中的配置文件
vim hdfs-site.xml
<property>
	<name>dfs.permissions.enabled</name>
	<value>true</value>
</property>

3.修改完成之后配置文件发送到其他机器上面去

scp hdfs-site.xml node2:$PWD
scp hdfs-site.xml node3:$PWD

4.重启hdfs集群

start-dfs.sh
package org.example.hdfs;


import cn.hutool.json.JSONUtil;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/***
 * HDFS在生产应用中主要是客户端的开发,其核心步骤是从HDFS提供的api中构造一个HDFS的访问客户端对象,然后通过该客户端对象操作(增删改查)HDFS上的文件
 */
public class HDFSDemo {

    private String hfdsUrl = "hdfs://node1:8020/";

    /***
     * 获取文件系统
     * @throws IOException
     */
    @Test
    public FileSystem getFileSystem() throws IOException {
        Configuration configuration = new Configuration();
        configuration.set("fs.defaultFS", hfdsUrl);
        FileSystem fileSystem = FileSystem.get(configuration);
        System.out.println(JSONUtil.toJsonPrettyStr(fileSystem));
        return fileSystem;
    }

    /***
     * 获取hdfs目录下的所有文件
     * @throws IOException
     */
    @Test
    public void showFiles() throws IOException {
        FileSystem fileSystem = getFileSystem();
        //获取RemoteIterator 得到所有的文件或者文件夹,第一个参数指定遍历的路径,第二个参数表示是否要递归遍历
        RemoteIterator<LocatedFileStatus> listFiles = fileSystem.listFiles(new Path("/test_01"), true);
        while (listFiles.hasNext()) {
            LocatedFileStatus next = listFiles.next();
            System.out.println(next.getPath());
        }
        fileSystem.close();
    }

    /***
     * 创建文件夹
     * @throws IOException
     */
    @Test
    public void createDir() throws IOException {
        FileSystem fileSystem = getFileSystem();
        boolean mkdirs = fileSystem.mkdirs(new Path("/test_01/mydir"));
        System.out.println(mkdirs);
        fileSystem.close();
    }

    @Test
    public void downLoadFile() throws IOException {
        FileSystem fileSystem = getFileSystem();
        FSDataInputStream open = fileSystem.open(new Path("/dir1/b.txt"));
        FileOutputStream fileOutputStream = new FileOutputStream(new File("E:\\tmp\\b.txt"));
        IOUtils.copy(open, fileOutputStream);
        IOUtils.closeQuietly(open);
        IOUtils.closeQuietly(fileOutputStream);
        fileSystem.close();
    }

    /***
     * idea操作hdfs需要在window中安装hadoop环境
     * @throws IOException
     */
    @Test
    public void downLoadFile2() throws IOException {
        FileSystem fileSystem = getFileSystem();
        fileSystem.copyToLocalFile(new Path("/dir1/b.txt"), new Path("E:\\tmp\\b1.txt"));
        fileSystem.close();
    }

    /***
     * 上传文件
     */
    @Test
    public void uploadFile() throws IOException {
        FileSystem fileSystem = getFileSystem();
        fileSystem.copyFromLocalFile(new Path("file:///c:\\install.log"), new Path("/hello/mydir/test"));
        fileSystem.close();
    }

    /***
     * 文件合并<br/>
     * 由于 Hadoop 擅长存储大文件,因为大文件的元数据信息比较少,如果 Hadoop 集群当中有大量的小文件,<br/>那么每个小文件都需要维护一份元数据信息,会大大的增加集群管理元数据的内存压力,所以在实际工作当中,如果有必要一定要将小文件合并成大文件进行一起处理,可以在上传的时候将小文件合并到一个大文件里面去
     */
    @Test
    public void mergeFile() throws IOException {
        FileSystem fileSystem = getFileSystem();
        FSDataOutputStream outputStream = fileSystem.create(new Path("/bigfile.txt"));

        //获取本地文件系统
        LocalFileSystem local = FileSystem.getLocal(new Configuration());

        //通过本地文件系统获取文件列表,为一个集合
        FileStatus[] fileStatuses = local.listStatus(new Path("file:///E:\\input"));

        for (FileStatus fileStatus : fileStatuses) {
            FSDataInputStream inputStream = local.open(fileStatus.getPath());
            IOUtils.copy(inputStream,outputStream);
            IOUtils.closeQuietly(inputStream);
        }
        IOUtils.closeQuietly(outputStream);
        local.close();
        fileSystem.close();
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值