java api操作HDFS

简介: java api操作HDFS

如果是使用maven的话,导入如下依赖即可,否则需要在解压好的hadoop文件夹下找到common文件夹和hdfs文件夹下的jar包

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

可能出现的问题如下:

Caused by: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.AccessControlException): Permission denied: user=ttc, access=WRITE, inode="/":root:supergroup:drwxr-xr-x

解决办法

System.setProperty("HADOOP_USER_NAME", "root") ;

要进行操作,主要得先拿到客户端对象

public class HdfsClient {
    Configuration conf = null;
    FileSystem fileSystem = null;
    @Before
    public void init() throws Exception{
        conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://192.168.47.140:8020");
        fileSystem = FileSystem.get(conf);
    }
}


解释:我们的操作目标是HDFS,所以获取到的fs对象应该是DistributedFileSystem的实例;get方法是从何处判断具体实例化那种客户端类呢?

——从conf中的一个参数 fs.defaultFS的配置值判断;

如果我们的代码中没有指定fs.defaultFS,并且工程classpath下也没有给定相应的配置,conf中的默认值就来自于hadoop的jar包中的core-default.xml,默认值为: file:///,则获取的将不是一个DistributedFileSystem的实例,而是一个本地文件系统的客户端对象。那么本地(一般我们使用的就是windows)需要安装配置hadoop,还要编译,配置环境变量,会比较麻烦,所以我们连接到linux。

关于conf.set(name,value)是设置配置参数的,也可以在classpath下加入配置文件hdfs-default.xml进行配置,或者使用jar包中的配置(默认的),优先级是由高到低。

比如con.set(“dfs.replication”,4),配置文件中配置的副本为2,包中默认的是3,最后副本数量是4。

1、测试文件上传

/**
     * 测试上传
     * d:/mylog.log传到hdfs路径/mylog.log.copy
     * @throws Exception
     */
    @Test
    public void testUpload() throws Exception{
        fileSystem.copyFromLocalFile(new Path("d:/mylog.log"), new Path("/mylog.log.copy"));
        fileSystem.close();
    }

页面查看效果


image.png


2、测试下载文件,将刚上传的/mylog.log.copy下载到本地指定位置

/**
     * 测试下载
     * 第一个参数表示是否删除源文件,即:剪切+粘贴
     * 最后一个参数表示是否使用本地文件系统,不使用的话会使用io,如果本地没配置hadoop的话会出现空指针异常。
     * @throws Exception
     */
    @Test
    public void testdownLoad() throws Exception{
        fileSystem.copyToLocalFile(true, new Path("/mylog.log.copy"), new Path("d:/zz.log"), 
                true);
        fileSystem.close();
    }

3、获取配置参数

/**
     * 获取配置参数:获取的是jar包中配置的,服务端配置的是不起作用的
     * 但是可以使用配置文件或者用cong.set()来指定
     * 比如副本数量 dfs.replication,3
     * @throws Exception
     */
    @Test
    public void testConfiguration() throws Exception{
        Iterator<Entry<String, String>> it = conf.iterator();
        while (it.hasNext()){
            Entry<String, String> entry = it.next();
            System.out.println(entry.getKey()+","+entry.getValue());
        }
        fileSystem.close();
    }

4、测试创建文件夹,可以创建多层

/**
     * 测试创建文件夹 可以是多层
     * @throws Exception
     */
    @Test
    public void testMkdir() throws Exception{
        boolean b = fileSystem.mkdirs(new Path("/djhot/cls"));
        System.out.println("文件夹是否创建成功:" + b);
        fileSystem.close(); 
    }

5、测试删除文件或文件夹

/**
     * 测试删除文件夹或文件,第二个参数用true则表示递归删除
     * @throws Exception
     */
    @Test
    public void testDelete() throws Exception{
        boolean b = fileSystem.delete(new Path("/djhot"),true);
        System.out.println("文件夹是否删除:" + b);
        boolean c = fileSystem.delete(new Path("/cenos-6.5-hadoop-2.6.4.tar.gz"),true);
        System.out.println("文件是否删除:" + c);
        fileSystem.close(); 
    }

5、列出所有文件以及相关信息

:/wordcount/output/a.txt,/wordcount/output/b.txt,/wordcount/input/a.txt,/wordcount/input/b.txt,

/**
     * 列出指定文件夹下的所有文件,第二个参数true表示递归列出
     * 每次拿到的只有一个文件,如果不使用迭代器一次拿太多内存吃不消
     * @throws Exception
     */
    @Test
    public void testListfiles() throws Exception{
        RemoteIterator<LocatedFileStatus> files = fileSystem.listFiles(new Path("/wordcount"), true);//true表示递归
        while(files.hasNext()){
            LocatedFileStatus fileStatus = files.next();
            System.out.println("blockSize"+fileStatus.getBlockSize());
            System.out.println("owner:"+fileStatus.getOwner());
            System.out.println("replication:"+fileStatus.getReplication());
            //文件路径
            System.out.println("path:"+fileStatus.getPath());
            //文件名
            System.out.println("name:"+fileStatus.getPath().getName());
            //关于block块的一些信息
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
            for (BlockLocation block : blockLocations) {
                System.out.println("块大小:"+block.getLength());
                System.out.println("偏移量:"+block.getOffset());
                String[] hosts = block.getHosts();
                for (String host : hosts) {
                    System.out.println("所在datanode:"+host);
                }
            }
            System.out.println("------------");
        }
        fileSystem.close(); 
    }

输出:

blockSize134217728
owner:root
replication:2
path:hdfs://192.168.25.127:9000/wordcount/input/a.txt
name:a.txt
块大小:71
偏移量:0
所在datanode:mini2
所在datanode:mini3
------------
blockSize134217728
owner:root
replication:2
path:hdfs://192.168.25.127:9000/wordcount/input/b.tx
name:b.tx
块大小:71
偏移量:0
所在datanode:mini2
所在datanode:mini3
------------
blockSize134217728
owner:root
replication:2
path:hdfs://192.168.25.127:9000/wordcount/output/_SUCCESS
name:_SUCCESS
------------
blockSize134217728
owner:root
replication:2
path:hdfs://192.168.25.127:9000/wordcount/output/part-r-00000
name:part-r-00000
块大小:75
偏移量:0
所在datanode:mini2
所在datanode:mini3
------------

6、列出指定目录下的文件或文件夹,不会递归

/**
     * 列出指定目录下的文件夹或文件  并不会递归
     * @throws Exception 
     */
    @Test
    public void testListStatus() throws Exception{
        FileStatus[] listStatus = fileSystem.listStatus(new Path("/wordcount"));
        for (FileStatus fileStatus : listStatus) {
            System.out.println("path:"+fileStatus.getPath());
            System.out.println("name:"+fileStatus.getPath().getName());
        }
        System.out.println("---------------------");
        FileStatus[] listStatus2 = fileSystem.listStatus(new Path("/wordcount/input"));
        for (FileStatus fileStatus : listStatus2) {
            System.out.println("path:"+fileStatus.getPath());
            System.out.println("name:"+fileStatus.getPath().getName());
        }
    }

输出

path:hdfs://192.168.25.127:9000/wordcount/input
name:input
path:hdfs://192.168.25.127:9000/wordcount/output
name:output
---------------------
path:hdfs://192.168.25.127:9000/wordcount/input/a.txt
name:a.txt
path:hdfs://192.168.25.127:9000/wordcount/input/b.tx
name:b.tx

7 、使用流进行文件读写

/**
 * 用流的方式来操作hdfs上的文件,可以实现读取指定偏移量范围的数据
 * @author 12706
 *
 */
public class HdfsStreamAccess {
    Configuration conf=null;
    FileSystem fs=null;
    @Before
    public void init() throws Exception{
        conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://192.168.25.127:9000");
        fs = FileSystem.get(conf);
    }
    /**
     * 通过流,将本地文件D:/liushishi.love写到hdfs下的/liushishi.love
     * @throws Exception
     */
    @Test
    public void testUpload() throws Exception{
        FSDataOutputStream outputStream = fs.create(new Path("/liushishi.love"), true);//有就覆盖
        FileInputStream inputStream = new FileInputStream("D:/liushishi.love");
        IOUtils.copy(inputStream, outputStream);
    }
    /**
     * 通过流,将hdfs下的/liushishi.love文件,写到本地文件D:/liushishi.love2
     * @throws Exception
     */
    @Test
    public void testDownload() throws Exception{
        FSDataInputStream inputStream = fs.open(new Path("/liushishi.love"));
        FileOutputStream outputStream = new FileOutputStream("D:/liushishi.love2");
        IOUtils.copy(inputStream, outputStream);
    }
    /**
     * 指定位置开始写
     * @throws Exception
     */
    @Test
    public void testRandomAccess() throws Exception{
        FSDataInputStream inputStream = fs.open(new Path("/liushishi.love"));
        //FileInoutStream是没有这个方法的,定位到第12个字节处
        inputStream.seek(12);
        FileOutputStream outputStream = new FileOutputStream("D:/liushishi.love2");
        //从第12个字节写到文件末
        IOUtils.copy(inputStream, outputStream);
    }
    /**
     * 将hdfs指定文件内容输出到控制台
     * @throws Exception
     */
    @Test
    public void testCat() throws Exception{
        FSDataInputStream inputStream = fs.open(new Path("/liushishi.love"));
        IOUtils.copy(inputStream, System.out);
    }


目录
相关文章
|
2天前
|
数据采集 JSON Java
Java爬虫获取微店快递费用item_fee API接口数据实现
本文介绍如何使用Java开发爬虫程序,通过微店API接口获取商品快递费用(item_fee)数据。主要内容包括:微店API接口的使用方法、Java爬虫技术背景、需求分析和技术选型。具体实现步骤为:发送HTTP请求获取数据、解析JSON格式的响应并提取快递费用信息,最后将结果存储到本地文件中。文中还提供了完整的代码示例,并提醒开发者注意授权令牌、接口频率限制及数据合法性等问题。
|
2天前
|
数据采集 存储 Java
Java爬虫获取微店店铺所有商品API接口设计与实现
本文介绍如何使用Java设计并实现一个爬虫程序,以获取微店店铺的所有商品信息。通过HttpClient发送HTTP请求,Jsoup解析HTML页面,提取商品名称、价格、图片链接等数据,并将其存储到本地文件或数据库中。文中详细描述了爬虫的设计思路、代码实现及注意事项,包括反爬虫机制、数据合法性和性能优化。此方法可帮助商家了解竞争对手,为消费者提供更全面的商品比较。
|
23天前
|
算法 Java 程序员
菜鸟之路Day06一一Java常用API
《菜鸟之路Day06——Java常用API》由blue编写,发布于2025年1月24日。本文详细介绍了Java中常用的API,包括JDK7的时间类(Date、SimpleDateFormat、Calendar)和JDK8新增的时间API(ZoneId、Instant、DateTimeFormatter等),以及包装类的使用。通过多个实例练习,如时间计算、字符串转整数、十进制转二进制等,帮助读者巩固所学内容,提升编程技能。文章强调了理论与实践结合的重要性,鼓励读者多做练习以提高学习效率。
76 28
|
6天前
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
30 5
|
1月前
|
JSON Java 数据挖掘
利用 Java 代码获取淘宝关键字 API 接口
在数字化商业时代,精准把握市场动态与消费者需求是企业成功的关键。淘宝作为中国最大的电商平台之一,其海量数据中蕴含丰富的商业洞察。本文介绍如何通过Java代码高效、合规地获取淘宝关键字API接口数据,帮助商家优化产品布局、制定营销策略。主要内容包括: 1. **淘宝关键字API的价值**:洞察用户需求、优化产品标题与详情、制定营销策略。 2. **获取API接口的步骤**:注册账号、申请权限、搭建Java开发环境、编写调用代码、解析响应数据。 3. **注意事项**:遵守法律法规与平台规则,处理API调用限制。 通过这些步骤,商家可以在激烈的市场竞争中脱颖而出。
|
2月前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
118 34
|
2月前
|
JSON Java Apache
Java基础-常用API-Object类
继承是面向对象编程的重要特性,允许从已有类派生新类。Java采用单继承机制,默认所有类继承自Object类。Object类提供了多个常用方法,如`clone()`用于复制对象,`equals()`判断对象是否相等,`hashCode()`计算哈希码,`toString()`返回对象的字符串表示,`wait()`、`notify()`和`notifyAll()`用于线程同步,`finalize()`在对象被垃圾回收时调用。掌握这些方法有助于更好地理解和使用Java中的对象行为。
|
2月前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
117 10
|
2月前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
101 6
|
2月前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。