hadoop深入研究:(二)——java访问hdfs

转载 2013年12月02日 20:37:10

转载请注明出处,http://blog.csdn.net/lastsweetop/article/details/9001467

所有源码在github上,https://github.com/lastsweetop/styhadoop

读数据

使用hadoop url读取

比较简单的读取hdfs数据的方法就是通过java.net.URL打开一个流,不过在这之前先要预先调用它的setURLStreamHandlerFactory方法设置为FsUrlStreamHandlerFactory(由此工厂取解析hdfs协议),这个方法只能调用一次,所以要写在静态块中。然后调用IOUtils类的copyBytes将hdfs数据流拷贝到标准输出流System.out中,copyBytes前两个参数好理解,一个输入,一个输出,第三个是缓存大小,第四个指定拷贝完毕后是否关闭流。我们这里要设置为false,标准输出流不关闭,我们要手动关闭输入流。
[java] view plaincopy
  1. package com.sweetop.styhadoop;  
  2.   
  3. import org.apache.hadoop.fs.FsUrlStreamHandlerFactory;  
  4. import org.apache.hadoop.io.IOUtils;  
  5.   
  6. import java.io.InputStream;  
  7. import java.net.URL;  
  8.   
  9. /** 
  10.  * Created with IntelliJ IDEA. 
  11.  * User: lastsweetop 
  12.  * Date: 13-5-31 
  13.  * Time: 上午10:16 
  14.  * To change this template use File | Settings | File Templates. 
  15.  */  
  16. public class URLCat {  
  17.   
  18.     static {  
  19.         URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());  
  20.     }  
  21.   
  22.     public static void main(String[] args) throws Exception {  
  23.         InputStream in = null;  
  24.         try {  
  25.             in = new URL(args[0]).openStream();  
  26.             IOUtils.copyBytes(in, System.out, 4096false);  
  27.         } finally {  
  28.             IOUtils.closeStream(in);  
  29.         }  
  30.     }  
  31. }  

使用FileSystem API读取数据

首先是实例化FileSystem对象,通过FileSystem类的get方法,这里要传入一个java.net.URL和一个配置Configuration
然后FileSystem可以通过一个Path对象打开一个流,之后的操作和上面的例子一样
[java] view plaincopy
  1. package com.sweetop.styhadoop;  
  2.   
  3. import org.apache.hadoop.conf.Configuration;  
  4. import org.apache.hadoop.fs.FileSystem;  
  5. import org.apache.hadoop.fs.Path;  
  6. import org.apache.hadoop.io.IOUtils;  
  7.   
  8. import java.io.InputStream;  
  9. import java.net.URI;  
  10.   
  11. /** 
  12.  * Created with IntelliJ IDEA. 
  13.  * User: lastsweetop 
  14.  * Date: 13-5-31 
  15.  * Time: 上午11:24 
  16.  * To change this template use File | Settings | File Templates. 
  17.  */  
  18. public class FileSystemCat {  
  19.     public static void main(String[] args) throws Exception {  
  20.         String uri=args[0];  
  21.         Configuration conf=new Configuration();  
  22.         FileSystem fs=FileSystem.get(URI.create(uri),conf);  
  23.         InputStream in=null;  
  24.         try {  
  25.             in=fs.open(new Path(uri));  
  26.             IOUtils.copyBytes(in, System.out, 4096false);  
  27.         }   finally {  
  28.             IOUtils.closeStream(in);  
  29.         }  
  30.     }  
  31. }  

FSDataInputStream

通过FileSystem打开流返回的对象是个FSDataInputStream对象,该类实现了Seekable接口,
[java] view plaincopy
  1. public interface Seekable {  
  2.     void seek(long l) throws java.io.IOException;  
  3.     long getPos() throws java.io.IOException;  
  4.     boolean seekToNewSource(long l) throws java.io.IOException;  
  5. }  
seek方法可跳到文件中的任意位置,我们这里跳到文件的初始位置再重新读一次
[java] view plaincopy
  1. public class FileSystemDoubleCat {  
  2.     public static void main(String[] args) throws Exception {  
  3.         String uri = args[0];  
  4.         Configuration conf = new Configuration();  
  5.         FileSystem fs = FileSystem.get(URI.create(uri), conf);  
  6.         FSDataInputStream in=null;  
  7.         try {  
  8.             in = fs.open(new Path(uri));  
  9.             IOUtils.copyBytes(in, System.out, 4096false);  
  10.             in.seek(0);  
  11.             IOUtils.copyBytes(in, System.out, 4096false);  
  12.         }   finally {  
  13.             IOUtils.closeStream(in);  
  14.         }  
  15.     }  
  16. }  
FSDataInputStream还实现了PositionedReadable接口,
[java] view plaincopy
  1. public interface PositionedReadable {  
  2.     int read(long l, byte[] bytes, int i, int i1) throws java.io.IOException;  
  3.     void readFully(long l, byte[] bytes, int i, int i1) throws java.io.IOException;  
  4.     void readFully(long l, byte[] bytes) throws java.io.IOException;  
  5. }  
可以在任意位置(第一个参数),偏移量(第三个参数),长度(第四个参数),到数组中(第二个参数)
这里就不实现了,大家可以试下

写数据

FileSystem类有很多种创建文件的方法,最简单的一种是
public FSDataOutputStream create(Path f) throws IOException
它还有很多重载方法,可以指定是否强制覆盖已存在的文件,文件的重复因子,写缓存的大小,文件的块大小,文件的权限等。
还可以指定一个回调接口:
[java] view plaincopy
  1. public interface Progressable {  
  2.     void progress();  
  3. }  
和普通文件系统一样,也支持apend操作,写日志时最常用
public FSDataOutputStream append(Path f) throws IOException
但并非所有hadoop文件系统都支持append,hdfs支持,s3就不支持。
以下是个拷贝本地文件到hdfs的例子
[java] view plaincopy
  1. package com.sweetop.styhadoop;  
  2.   
  3. import org.apache.hadoop.conf.Configuration;  
  4. import org.apache.hadoop.fs.FileSystem;  
  5. import org.apache.hadoop.fs.Path;  
  6. import org.apache.hadoop.io.IOUtils;  
  7. import org.apache.hadoop.util.Progressable;  
  8.   
  9. import java.io.BufferedInputStream;  
  10. import java.io.FileInputStream;  
  11. import java.io.InputStream;  
  12. import java.io.OutputStream;  
  13. import java.net.URI;  
  14.   
  15. /** 
  16.  * Created with IntelliJ IDEA. 
  17.  * User: lastsweetop 
  18.  * Date: 13-6-2 
  19.  * Time: 下午4:54 
  20.  * To change this template use File | Settings | File Templates. 
  21.  */  
  22. public class FileCopyWithProgress {  
  23.     public static void main(String[] args) throws Exception {  
  24.         String localSrc = args[0];  
  25.         String dst = args[1];  
  26.   
  27.         InputStream in = new BufferedInputStream(new FileInputStream(localSrc));  
  28.   
  29.         Configuration conf = new Configuration();  
  30.         FileSystem fs = FileSystem.get(URI.create(dst), conf);  
  31.         OutputStream out = fs.create(new Path(dst), new Progressable() {  
  32.             @Override  
  33.             public void progress() {  
  34.                 System.out.print(".");  
  35.             }  
  36.         });  
  37.   
  38.         IOUtils.copyBytes(in, out, 4096true);  
  39.      

目录

创建一个目录的方法:
public boolean mkdirs(Path f) throws IOException
mkdirs方法会自动创建所有不存在的父目录

检索

检索一个目录,查看目录和文件的信息在任何操作系统这些都是不可或缺的功能,hdfs也不例外,但也有一些特别的地方:

FileStatus

FileStatus 封装了hdfs文件和目录的元数据,包括文件的长度,块大小,重复数,修改时间,所有者,权限等信息,FileSystem的getFileStatus可以获得这些信息,
[java] view plaincopy
  1. package com.sweetop.styhadoop;  
  2.   
  3. import org.apache.hadoop.conf.Configuration;  
  4. import org.apache.hadoop.fs.FileStatus;  
  5. import org.apache.hadoop.fs.FileSystem;  
  6. import org.apache.hadoop.fs.Path;  
  7.   
  8. import java.io.IOException;  
  9. import java.net.URI;  
  10.   
  11. /** 
  12.  * Created with IntelliJ IDEA. 
  13.  * User: lastsweetop 
  14.  * Date: 13-6-2 
  15.  * Time: 下午8:58 
  16.  * To change this template use File | Settings | File Templates. 
  17.  */  
  18. public class ShowFileStatus {  
  19.   
  20.     public static void main(String[] args) throws IOException {  
  21.         Path path = new Path(args[0]);  
  22.         Configuration conf = new Configuration();  
  23.         FileSystem fs = FileSystem.get(URI.create(args[0]), conf);  
  24.         FileStatus status = fs.getFileStatus(path);  
  25.         System.out.println("path = " + status.getPath());  
  26.         System.out.println("owner = " + status.getOwner());  
  27.         System.out.println("block size = " + status.getBlockSize());  
  28.         System.out.println("permission = " + status.getPermission());  
  29.         System.out.println("replication = " + status.getReplication());  
  30.     }  
  31. }  

Listing files

有时候你可能会需要找一组符合要求的文件,那么下面的示例就可以帮到你,通过FileSystem的listStatus方法可以获得符合条件的一组FileStatus对象,listStatus有几个重载的方法,可以传入多个路径,还可以使用PathFilter做过滤,我们下面就会讲到它。这里还有一个重要的方法,FileUtils.stat2Paths可以将一组FileStatus对象转换成一组Path对象,这是个非常便捷的方法。

[java] view plaincopy
  1. package com.sweetop.styhadoop;  
  2.   
  3. import org.apache.hadoop.conf.Configuration;  
  4. import org.apache.hadoop.fs.FileStatus;  
  5. import org.apache.hadoop.fs.FileSystem;  
  6. import org.apache.hadoop.fs.FileUtil;  
  7. import org.apache.hadoop.fs.Path;  
  8.   
  9. import java.io.IOException;  
  10. import java.net.URI;  
  11.   
  12. /** 
  13.  * Created with IntelliJ IDEA. 
  14.  * User: lastsweetop 
  15.  * Date: 13-6-2 
  16.  * Time: 下午10:09 
  17.  * To change this template use File | Settings | File Templates. 
  18.  */  
  19. public class ListStatus {  
  20.     public static void main(String[] args) throws IOException {  
  21.         String uri = args[0];  
  22.         Configuration conf = new Configuration();  
  23.         FileSystem fs = FileSystem.get(URI.create(uri), conf);  
  24.   
  25.         Path[] paths = new Path[args.length];  
  26.         for (int i = 0; i < paths.length; i++) {  
  27.             paths[i] = new Path(args[i]);  
  28.         }  
  29.   
  30.         FileStatus[] status = fs.listStatus(paths);  
  31.         Path[] listedPaths = FileUtil.stat2Paths(status);  
  32.         for (Path p : listedPaths) {  
  33.             System.out.println(p);  
  34.         }  
  35.     }  
  36. }  

PathFilter

接着上面我们来讲PathFilter接口,该接口只需实现其中的一个方法即可,即accpet方法,方法返回true时表示被过滤掉,我们来实现一个正则过滤,并在下面的例子里起作用
[java] view plaincopy
  1. package com.sweetop.styhadoop;  
  2.   
  3. import org.apache.hadoop.fs.Path;  
  4. import org.apache.hadoop.fs.PathFilter;  
  5.   
  6. /** 
  7.  * Created with IntelliJ IDEA. 
  8.  * User: lastsweetop 
  9.  * Date: 13-6-3 
  10.  * Time: 下午2:49 
  11.  * To change this template use File | Settings | File Templates. 
  12.  */  
  13. public class RegexExludePathFilter implements PathFilter {  
  14.   
  15.     private final String regex;  
  16.   
  17.     public RegexExludePathFilter(String regex) {  
  18.         this.regex = regex;  
  19.     }  
  20.   
  21.     @Override  
  22.     public boolean accept(Path path) {  
  23.         return !path.toString().matches(regex);  
  24.     }  
  25. }  

File patterns

当需要很多文件时,一个个列出路径是很不便捷的,hdfs提供了一个通配符列出文件的方法,通过FileSystem的globStatus方法提供了这个便捷,globStatus也有重载的方法,使用PathFilter过滤,那么我们结合两个来实现一下
[java] view plaincopy
  1. package com.sweetop.styhadoop;  
  2.   
  3. import org.apache.hadoop.conf.Configuration;  
  4. import org.apache.hadoop.fs.FileStatus;  
  5. import org.apache.hadoop.fs.FileSystem;  
  6. import org.apache.hadoop.fs.FileUtil;  
  7. import org.apache.hadoop.fs.Path;  
  8.   
  9. import java.io.IOException;  
  10. import java.net.URI;  
  11.   
  12. /** 
  13.  * Created with IntelliJ IDEA. 
  14.  * User: lastsweetop 
  15.  * Date: 13-6-3 
  16.  * Time: 下午2:37 
  17.  * To change this template use File | Settings | File Templates. 
  18.  */  
  19. public class GlobStatus {  
  20.     public static void main(String[] args) throws IOException {  
  21.         String uri = args[0];  
  22.         Configuration conf = new Configuration();  
  23.         FileSystem fs = FileSystem.get(URI.create(uri), conf);  
  24.   
  25.         FileStatus[] status = fs.globStatus(new Path(uri),new RegexExludePathFilter("^.*/1901"));  
  26.         Path[] listedPaths = FileUtil.stat2Paths(status);  
  27.         for (Path p : listedPaths) {  
  28.             System.out.println(p);  
  29.         }  
  30.     }  
  31. }  

删除数据

删除数据比较简单
public abstract boolean delete(Path f,
                               boolean recursive)
                        throws IOException
第一个参数很明确,第二个参数表示是否递归删除子目录或目录下的文件,在Path为目录但目录是空的或者Path为文件时可以忽略,但如果Path为目录且不为空的情况下,如果recursive为false,那么删除就会抛出io异常。

Hadoop HDFS (3) JAVA访问HDFS

现在我们来深入了解一下Hadoop的FileSystem类。这个类是用来跟Hadoop的文件系统进行交互的。虽然我们这里主要是针对HDFS,但是我们还是应该让我们的代码只使用抽象类FileSystem...
  • arkwrightzhn
  • arkwrightzhn
  • 2014年09月28日 23:34
  • 3459

Hadoop HDFS文件操作的Java代码

1、创建目录 import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.h...
  • fanhenghui
  • fanhenghui
  • 2016年07月13日 14:07
  • 5273

hadoop源码解析—— conf包中Configuration.java解析(一)

package org.apache.hadoop.conf; import java.io.BufferedInputStream; import java.io.DataInput; impor...
  • yaoxiaochuang
  • yaoxiaochuang
  • 2016年02月11日 01:37
  • 1244

hadoop学习笔记--5.HDFS的java api接口访问

hadoop学习笔记--5.HDFS的java api接口访问 一:几个常用类介绍    (1):configuration类:此类封装了客户端或服务器的配置,通过配置文件来读取类路径实现(一...
  • liuzebin9
  • liuzebin9
  • 2017年04月14日 20:53
  • 984

idea本地运行hdfs程序

上一篇文章已经搭建好了hadoop单机模式的服务,现在我们要在本地idea上操作hdfs。 首先创建一个maven工程 1.目录结构    2.pom.xml junit j...
  • chenzhongwei99
  • chenzhongwei99
  • 2017年05月18日 18:02
  • 1084

【Hadoop】win7下通过intellij idea对hadoop2.7.3进行访问操作的实践

Win7下通过Intellij idea对hadoop进行访问操作的实践
  • lsttoy
  • lsttoy
  • 2016年09月02日 21:35
  • 3425

使用IntelliJ IDEA 16.1写hadoop程序

背景       前段时间配置好了基于mac的hadoop完全分布式环境,一直想着怎么样去用编译器写程序然后直接在hadoop环境中运行呢,经过一番摸索,写下此文章分享交流。环境介绍 os ...
  • wk51920
  • wk51920
  • 2016年06月16日 00:23
  • 7773

Java/Web调用Hadoop进行MapReduce示例

使用Java或JavaWeb封装Hadoop进行远程调用Hadoop MapReduce任务。
  • csj941227
  • csj941227
  • 2017年05月13日 10:35
  • 5660

Hadoop-利用java API操作HDFS文件

这段时间学习了python和hadoop,主要用于数据处理方面,因此打算写几篇这方面的博客。不过不是我的原创,我也是利用前辈的工作展示给大家。把自己学到的东西,也是比较初级的东西展示给需要的同学。 ...
  • u010156024
  • u010156024
  • 2015年11月30日 16:28
  • 12120

hadoop与java简单交互

首先要在linux上搭建hadoop环境,具体的实现步骤在http://phey.cc/build_signal_node_hadoop20.html 搭建好之后,在Eclipse 或Myeclips...
  • baobaolx
  • baobaolx
  • 2015年01月12日 12:10
  • 1712
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hadoop深入研究:(二)——java访问hdfs
举报原因:
原因补充:

(最多只允许输入30个字)