Hadoop文件系统操作之读取写入数据

一.从hadoop文件系统hdfs读取文件

  读取hdfs文件有两种方法:

  1.使用java.net.URL对象打开数据流,从中读取代码

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.commons.compress.utils.IOUtils;
import org.apache.hadoop.fs.FsUrlStreamHandlerFactory;


public class URLCat 
{
    static 
  { URL.setURLStreamHandlerFactory(
new FsUrlStreamHandlerFactory()); } public static void main(String [] args) throws MalformedURLException, IOException { try(InputStream in = new URL(args[0]).openStream();) { IOUtils.copy(in, System.out); } } }

  要想让java程序能识别Hadoop的hdfs URL必须通过FsUrlStreamHandlerFactory实例调用java.net.URL对象的setURLStreamHandlerFactory方法,然而每个java虚拟机只能调用一次这个方法,这意味着如果如果程序的其他组件已经声明了一个URLStreamHandlerFactory对象,将无法用这种方法从hadoop读取文件

  2.通过调用FileSystem API 读取数据

import java.io.*;
import java.net.URI;

import org.apache.commons.compress.utils.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

public class FileSystemCat 
{
    public static void main(String [] args) throws IOException
    {
        String uri = args[0];
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(URI.create(uri),conf);
        try(InputStream in = fs.open(new Path(uri)))
        {
            IOUtils.copy(in,System.out);
            //((FSDataInputStream) in).seek(0);
            //IOUtils.copy(in, System.out);
        }
    }
}

  

  Configuration 对象封装了客户端或者服务端的配置

  public static FileSystem.get(URI uri,Configuration conf)通过给定的URL来确定要使用的文件系统

  Public FSDateInputStream open(Path f) throws IOException用来获取文件的输入流

  FSDateInputStream类继承了Seekable接口和PositionedReadable接口,因此可以从流的随意位置读取数据,Seelable接口提供的seek()类是一个相对高开销的操作,需要谨慎使用

 

二.向hadoop文件系统hdfs写入数据

 

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.util.Progressable;

public class FileCopyWithProgress 
{
    public static void main(String[] args) throws IOException
    {
        String localsrc = args[0];
        String dst = args[1];
        InputStream in = new BufferedInputStream(new FileInputStream(localsrc));
        
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(URI.create(dst),conf);
        
        try (OutputStream out = fs.create(new Path(dst),new Progressable(){
            public void progress()
            {
                System.out.print(".");//用于显示文件复制进度
            }
        }))
            {
                IOUtils.copy(in, out);
            }    
    }     
}

 

使用运行参数:"/home/hadoop/Desktop/1.txt"     "hdfs://localhost/user/hadoop/output/1.txt"

程序在运行时可能会出现错误:

Exception in thread "main" java.net.ConnectException: Call From thewolf/127.0.1.1 to localhost:8020 failed on connection exception: java.net.ConnectException: Connection refused; For more details see:  http://wiki.apache.org/hadoop/ConnectionRefused

原因:是没有指定访问分布式文件系统的端口号:即配置文件里面设定的文件系统端口,执行程序会根据默认的8020端口去访问文件系统,而访问不到出现上述错误。

解决方法:指定访问hdfs的端口号(自己配置的端口号,我配置的是9000):更改运行参数为:"/home/hadoop/Desktop/1.txt"     "hdfs://localhost:9000/user/hadoop/output/1.txt"

 

  public FSDataOutputStream create(Path f) throws IOException 能够为需要写入切当前不存在的文件创建父文件目录,可先用exists()方法检查父目录是否存在;append()方法用于在一个已经存在的文件末尾追加数据

  FSDataInputStream继承了借口Syncable,可用getPos()方法查询文件当前位置,但是FSDataInputStream类不允许在文件中定位,因为HDFS只允许对一个已打开文件顺序写入,或者在现有文件后面追加数据。

  Progressable用于传递回调接口,每次Hadoop将64KB数据写入datanode管线后都会调用Progressable接口的progress

public interface Progressable
{
  public void progress();           
}

      

转载于:https://www.cnblogs.com/langzaichi/p/5960168.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值