博主上一篇博客分享了namenode和datanode的工做原理,本章节将继前面的HDFS的java客户端简单API后深度讲述HDFS流处理API。java
场景:博主前面的文章介绍过HDFS上存的大文件会成不一样的块存储在不一样的datanode节点上,对外提供统一的访问视图。可是,若是这个须要处理的文件总体特别大,咱们在mapreduce程序中若是每次都所有下载到本地在执行那会很是耗时耗空间;那么,有没有一种好的方式,能够实现当前这个mapreduce任务处理的那个分片数据,就下载分片这一段的数据到本地进行处理。答案:HDFS流客户端APInode
package com.empire.hadoop.hadoop_demo; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.URI; import org.apache.commons.io.IOUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.junit.Before; import org.junit.Test; /** * 用流的方式来操做hdfs上的文件 * 能够实现读取指定偏移量范围的数据 * @author * */ public class HdfsStreamAccess { FileSystem fs = null; Configuration conf = null; @Before public void init() throws Exception{ conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://master:9000"); //客户端去操做hdfs时,是有一个用户身份的 //默认状况下,hdfs客户端api会从jvm中获取一个参数来做为本身的用户身份:-DHADOOP_USER_NAME=hadoop //拿到一个文件系统操做的客户端实例对象 /*fs = FileSystem.get(conf);*/ System.setProperty("hadoop.home.dir", "E:\\\\hadoop-2.9.1"); //能够直接传入 uri和用户身份 //centos-aaron-h1为namenode的主机名或者域名 fs = FileSystem.get(new URI("hdfs://centos-aaron-h1:9000"),conf,"hadoop"); //最后一个参数为用户名 } /** * 经过流的方式上传文件到hdfs * @throws Exception */ @Test public void testUpload() throws Exception { FSDataOutputStream outputStream = fs.create(new Path("/angelababy.love"), true); FileInputStream inputStream = new FileInputStream("c:/angelababy.love"); IOUtils.copy(inputStream, outputStream); } /** * 经过流的方式获取hdfs上数据 * @throws Exception */ @Test public void testDownLoad() throws Exception { FSDataInputStream inputStream = fs.open(new Path("/angelababy.love")); FileOutputStream outputStream = new FileOutputStream("d:/angelababy.love"); IOUtils.copy(inputStream, outputStream); } @Test public void testRandomAccess() throws Exception{ FSDataInputStream inputStream = fs.open(new Path("/angelababy.love")); inputStream.seek(12); FileOutputStream outputStream = new FileOutputStream("d:/angelababy.love.part2"); IOUtils.copy(inputStream, outputStream); } /** * 显示hdfs上文件的内容 * @throws IOException * @throws IllegalArgumentException */ @Test public void testCat() throws IllegalArgumentException, IOException{ FSDataInputStream in = fs.open(new Path("/angelababy.love")); IOUtils.copy(in, System.out); //hadoop的IOUtils更容易实现文件偏移分片处理 // IOUtils.copyBytes(in, System.out, 1024); } }
前面的一些疑问总结:apache
hdfs dfsadmin -report 打印集群的状态,看到的内容至关准确 start-dfs.sh 若是namenode没关,也不要紧
HDFS listFiles()为什么不直接反回List而是返回一个迭代器?由于若是listFiles参数传递的目录中包含几十亿个文件,那List直接放客户端内存,可能会让客户端吃不消;迭代器为什么就行呢,迭代器其实不是个集合,它只是取数据的一种方式,它并不存数据,只是提供给一个方法,让你能够经过next(),nexthas()方法获取数据。centos
mapreduce相对于HDFS来讲,实际上是一个HDFS客户端的角色。api
最后寄语,以上是博主本次文章的所有内容,若是你们以为博主的文章还不错,请点赞;若是您对博主其它服务器大数据技术或者博主本人感兴趣,请关注博主博客,而且欢迎随时跟博主沟通交流。服务器