HDFS应用开发篇

HDFS的java操作

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

7.1 搭建开发环境

1、引入依赖


<dependency>

<groupId>org.apache.hadoop</groupId>

<artifactId>hadoop-client</artifactId>

<version>2.6.1</version>

</dependency>

注:如需手动引入jar包,hdfs的jar包----hadoop的安装目录的share下

2、window下开发的说明

建议在linux下进行hadoop应用的开发,不会存在兼容性问题。如在window上做客户端应用开发,需要设置以下环境:

A、在windows的某个目录下解压一个hadoop的安装包

B、将安装包下的lib和bin目录用对应windows版本平台编译的本地库替换

C、在window系统中配置HADOOP_HOME指向你解压的安装包

D、在windows系统的path变量中加入hadoop的bin目录

7.2 获取api中的客户端对象

在java中操作hdfs,首先要获得一个客户端实例


Configuration conf = new Configuration()

FileSystem fs = FileSystem.get(conf)

而我们的操作目标是HDFS,所以获取到的fs对象应该是DistributedFileSystem的实例;

get方法是从何处判断具体实例化那种客户端类呢?

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

如果我们的代码中没有指定fs.defaultFS,并且工程classpath下也没有给定相应的配置,conf中的默认值就来自于hadoop的jar包中的core-default.xml,默认值为: file:///,则获取的将不是一个DistributedFileSystem的实例,而是一个本地文件系统的客户端对象

7.3 DistributedFileSystem实例对象所具备的方法

7.4 HDFS客户端操作数据代码示例:

hdfs dfsadmin -report查看状态

7.4.1 文件的增删改查


public class HdfsClient {

FileSystem fs = null;

@Before

public void init() throws Exception {

// 构造一个配置参数对象,设置一个参数:我们要访问的hdfs的URI

// 从而FileSystem.get()方法就知道应该是去构造一个访问hdfs文件系统的客户端,以及hdfs的访问地址

// new Configuration();的时候,它就会去加载jar包中的hdfs-default.xml

// 然后再加载classpath下的hdfs-site.xml

Configuration conf = new Configuration();

conf.set("fs.defaultFS", "hdfs://hdp-node01:9000");

/**

* 参数优先级: 1、客户端代码中设置的值 2、classpath下的用户自定义配置文件 3、然后是服务器的默认配置

*/

conf.set("dfs.replication", "3");

// 获取一个hdfs的访问客户端,根据参数,这个实例应该是DistributedFileSystem的实例

// fs = FileSystem.get(conf);

// 如果这样去获取,那conf里面就可以不要配"fs.defaultFS"参数,而且,这个客户端的身份标识已经是hadoop用户

fs = FileSystem.get(new URI("hdfs://hdp-node01:9000"), conf, "hadoop");

}

/**

* 往hdfs上传文件

*

* @throws Exception

*/

@Test

public void testAddFileToHdfs() throws Exception {

// 要上传的文件所在的本地路径

Path src = new Path("g:/redis-recommend.zip");

// 要上传到hdfs的目标路径

Path dst = new Path("/aaa");

fs.copyFromLocalFile(src, dst);

fs.close();

}

/**

* 从hdfs中复制文件到本地文件系统

*

* @throws IOException

* @throws IllegalArgumentException

*/

@Test

public void testDownloadFileToLocal() throws IllegalArgumentException, IOException {

fs.copyToLocalFile(new Path("/jdk-7u65-linux-i586.tar.gz"), new Path("d:/"));

fs.close();

}

@Test

public void testMkdirAndDeleteAndRename() throws IllegalArgumentException, IOException {

// 创建目录

fs.mkdirs(new Path("/a1/b1/c1"));

// 删除文件夹 ,如果是非空文件夹,参数2必须给值true

fs.delete(new Path("/aaa"), true);

// 重命名文件或文件夹

fs.rename(new Path("/a1"), new Path("/a2"));

}

/**

* 查看目录信息,只显示文件

*

* @throws IOException

* @throws IllegalArgumentException

* @throws FileNotFoundException

*/

@Test

public void testListFiles() throws FileNotFoundException, IllegalArgumentException, IOException {

// 思考:为什么返回迭代器,而不是List之类的容器

RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);

while (listFiles.hasNext()) {

LocatedFileStatus fileStatus = listFiles.next();

System.out.println(fileStatus.getPath().getName());

System.out.println(fileStatus.getBlockSize());

System.out.println(fileStatus.getPermission());

System.out.println(fileStatus.getLen());

BlockLocation[] blockLocations = fileStatus.getBlockLocations();

for (BlockLocation bl : blockLocations) {

System.out.println("block-length:" + bl.getLength() + "--" + "block-offset:" + bl.getOffset());

String[] hosts = bl.getHosts();

for (String host : hosts) {

System.out.println(host);

}

}

System.out.println("--------------为angelababy打印的分割线--------------");

}

}

/**

* 查看文件及文件夹信息

*

* @throws IOException

* @throws IllegalArgumentException

* @throws FileNotFoundException

*/

@Test

public void testListAll() throws FileNotFoundException, IllegalArgumentException, IOException {

FileStatus[] listStatus = fs.listStatus(new Path("/"));

String flag = "d--             ";

for (FileStatus fstatus : listStatus) {

if (fstatus.isFile())  flag = "f--         ";

System.out.println(flag + fstatus.getPath().getName());

}

}

}

7.4.2 通过流的方式访问hdfs


/**

 * 相对那些封装好的方法而言的更底层一些的操作方式

 * 上层那些mapreduce   spark等运算框架,去hdfs中获取数据的时候,就是调的这种底层的api

 * @author

 *

 */

public class StreamAccess {

FileSystem fs = null;

 

@Before

public void init() throws Exception {

 

Configuration conf = new Configuration();

fs = FileSystem.get(new URI("hdfs://hdp-node01:9000"), conf, "hadoop");

 

}

@Test

public void testDownLoadFileToLocal() throws IllegalArgumentException, IOException{

//先获取一个文件的输入流----针对hdfs上的

FSDataInputStream in = fs.open(new Path("/jdk-7u65-linux-i586.tar.gz"));

//再构造一个文件的输出流----针对本地的

FileOutputStream out = new FileOutputStream(new File("c:/jdk.tar.gz"));

//再将输入流中数据传输到输出流

IOUtils.copyBytes(in, out, 4096);

}

/**

 * hdfs支持随机定位进行文件读取,而且可以方便地读取指定长度

 * 用于上层分布式运算框架并发处理数据

 * @throws IllegalArgumentException

 * @throws IOException

 */

@Test

public void testRandomAccess() throws IllegalArgumentException, IOException{

//先获取一个文件的输入流----针对hdfs上的

FSDataInputStream in = fs.open(new Path("/iloveyou.txt"));

//可以将流的起始偏移量进行自定义

in.seek(22);

//再构造一个文件的输出流----针对本地的

FileOutputStream out = new FileOutputStream(new File("c:/iloveyou.line.2.txt"));

IOUtils.copyBytes(in,out,19L,true);

}

/**

 * 显示hdfs上文件的内容

 * @throws IOException

 * @throws IllegalArgumentException

 */

@Test

public void testCat() throws IllegalArgumentException, IOException{

FSDataInputStream in = fs.open(new Path("/iloveyou.txt"));

IOUtils.copyBytes(in, System.out, 1024);

}

}

7.4.3 场景编程

在mapreduce 、spark等运算框架中,有一个核心思想就是将运算移往数据,或者说,就是要在并发计算中尽可能让运算本地化,这就需要获取数据所在位置的信息并进行相应范围读取

以下模拟实现:获取一个文件的所有block位置信息,然后读取指定block中的内容


@Test

public void testCat() throws IllegalArgumentException, IOException{

FSDataInputStream in = fs.open(new Path("/weblog/input/access.log.10"));

//拿到文件信息

FileStatus[] listStatus = fs.listStatus(new Path("/weblog/input/access.log.10"));

//获取这个文件的所有block的信息

BlockLocation[] fileBlockLocations = fs.getFileBlockLocations(listStatus[0], 0L, listStatus[0].getLen());

//第一个block的长度

long length = fileBlockLocations[0].getLength();

//第一个block的起始偏移量

long offset = fileBlockLocations[0].getOffset();

System.out.println(length);

System.out.println(offset);

//获取第一个block写入输出流

//IOUtils.copyBytes(in, System.out, (int)length);

byte[] b = new byte[4096];

FileOutputStream os = new FileOutputStream(new File("d:/block0"));

while(in.read(offset, b, 0, 4096)!=-1){

os.write(b);

offset += 4096;

if(offset>=length) return;

};

os.flush();

os.close();

in.close();

}

时间: 2024-10-03 21:58:39

HDFS应用开发篇的相关文章

【COCOS CREATOR 系列教程之二】脚本开发篇&事件监听、常用函数等示例整合

[Cocos Creator ](千人群):  432818031 上一篇,介绍了Himi在使用过cc所有组件后的一篇总结,没有具体介绍每个组件的原因在于官方文档很齐全,而且也有视频的介绍. 所以希望童鞋们可以把我这两篇博文当成对组件.脚本两部分开发的整理与总结. 后续的文章,Himi应该主要更新一些官方还未补充或者还没有的教程.避免无用功. 下面直接放出代码,因为不是很难理解.所以不再一一赘述,都是常用的函数.事件监听.动作回调.定时器等开发过程中必接触的. 大致内容如下: cc 属性介绍 获

Android NDK开发篇(五):Java与原生代码通信(数据操作)

尽管说使用NDK能够提高Android程序的运行效率,可是调用起来还是略微有点麻烦.NDK能够直接使用Java的原生数据类型,而引用类型,由于Java的引用类型的实如今NDK被屏蔽了,所以在NDK使用Java的引用类型则要做对应的处理. 一.对引用数据类型的操作 尽管Java的引用类型的实如今NDK被屏蔽了,JNI还是提供了一组API,通过JNIEnv接口指针提供原生方法改动和使用Java的引用类型. 1.字符串操作 JNI把Java的字符串当作引用来处理,在NDK中使用Java的字符串,须要相

小试ImageMagik——开发篇

ImageMagick的使用和开发的文章: 小试ImageMagik--使用篇 小试ImageMagik--开发篇 ====================== 本文介绍使用ImageMagick开发程序的方法.ImageMagick安装之后就可以支持C/C++程序的开发,提供了3种接口.在这里首先介绍一下ImageMagick的3种接口. MagickCore: 底层的C语言接口.较复杂,但是可以修改很多参数,只适合高端用户使用. MagickWand: 推荐的C语言接口.相比于MagickC

邮件模板——开发篇

其实网上有关于邮件模板开发的文章其实不少,但是都是面向开发人员的,对于非技术的同事有一定的门槛,因此我将邮件模板系列分为三个部分,以便朋友们能更快的找到自己需要的.前两篇文章 “科普篇”.“基础篇”分别面向产品设计同事和零基础的使用邮件模板的同事,下面的“开发篇”主要是面向邮件模板的前端开发的同事.“开发篇”参考了不少网上的文章,结合我在开发中遇到的一些坑,做了一些汇总: html: 1.!Doctype声明:为了向前兼容和避免某些浏览器的怪癖,使用html5的!doctype声明,格式如下:<

mysql开发篇目录

(1)SQL基本查询 (2)mysql支持的数据类型总结 (3)mysql中的运算符 (4)mysql中的常用函数 (5)mysql常用存储引擎 (6)mysql中的字符集 (7)mysql索引的设计和使用 (8)mysql中的视图 (9)mysql中的存储过程和自定义函数 (10)mysql中的变量 (11)mysql中的条件定义.处理 (12)mysql中的光标 (13)mysql中的流程控制 (14)mysql中的事件 (15)mysql中的触发器 (16)mysql中的表锁定及事务控制

Android官方开发文档之从Eclipse迁移到Android Studio开发篇

Android官方开发文档之从Eclipse迁移到Android Studio开发篇 1.前言 从Eclipse迁移项目到Android Studio需要适应一个新的项目结构,建立系统和IDE的功能.为了简化迁移过程,Android Studio提供了重要工具使你可以快速地将现有代码移动到Android Studio项目基础建设的文件和工具. 2.Android Studio的基础(Android Studio Basics) 当你将Eclipse项目迁移到Android Studio时,你应该

IntelliJ IDEA教程之Andriod项目开发篇(全集)

此教程图文讲解使用IntelliJ IDEA开发Andriod项目,人门篇,希望对初学者有所帮助! IntelliJ IDEA教程之Andriod项目开发篇:准备工作 IntelliJ IDEA教程之Andriod项目开发篇: 新项目设置 IntelliJ IDEA教程之Andriod项目开发篇:现有项目导入设置 IntelliJ IDEA教程之Andriod项目开发篇:理解项目结构 IntelliJ IDEA教程之Andriod项目开发篇:构建应用程序配置 IntelliJ IDEA教程之An

数据库开发篇(一)——转换日期类型

原文:数据库开发篇(一)--转换日期类型 SQL Server支持的日期时间格式 SQL code Select CONVERT(varchar(100), GETDATE(), 0): 05 16 2006 10:57AM Select CONVERT(varchar(100), GETDATE(), 1): 05/16/06 Select CONVERT(varchar(100), GETDATE(), 2): 06.05.16 Select CONVERT(varchar(100), GE

R的极客理想——高级开发篇

这篇是计算机类的优质预售推荐>>>><R的极客理想--高级开发篇> 资深R语言用户多年实战经验的结晶 编辑推荐 资深R语言用户多年实战经验的结晶,介绍R语言本身的核心技术以及R语言在不同领域的跨学科综合应用,借助每日中国天气的应用案例和游戏开发的案例,揭秘完整的R包开发流程,帮助读者创建自己的R包,打开R语言产品化的思路. 内容简介 本书的内容来自作者使用R语言的实践经验总结,以R语言的高级编程为主,辅以跨界知识的综合运用,涉及计算机.统计.数学.金融四个学科的知识.书