Hadoop——Java接口[笔记]

Java 接口

Hadoop 有一个抽象的文件系统概念, HDFS 只是其中的一个实现。Java 抽象类org.apache.hadoop.fs.FileSystem 定义了Hadoop 中的一个文件系统接口:与Hadoop 的某一文件系统进行交互的API 。虽然我们主要关注的是HDFS的实例,即DistributedFileSystem,但总体来说,还是应该继承FileSystem抽象类,并编写代码,以保持其在不同文件系统中的可移植性。

从Hadoop URL 中读取数据

要从Hadoop文件系统中读取文件,最简单的方陆是使用java.net.URL 对象打开数据流,进而从中读取数据。具体格式如下:

InputStream in = null;
try {
  in = new URL("hdfs://host/path").openStream();
  // process in
} finally {
  IOUtils.closeStream(in);
}

让Java 程序能够识别Hadoop的hdfs URL 方案还需要一些额外的工作。这里采用的方能是通过FsUrlStreamHandlerFactory 实例调用URL中的setURLStreamHandlerFactory 方法。由于Java 虚拟机只能调用一次上述方法,

因此通常在静态方法中调用上述方法。这个限制意味着如果程序的其他组件(不受你控制的第三方组件)已经声明了一个URLStreamHandlerFactory 实例,

你将无法再使用上述方法从Hadoop 中读取数据。下一节将讨论另一备选方法。

通过URLStreamHandler 实例以标准输出方式显示Hadoop 文件系统的文件

public class URLCat {
static {
URL.setURLStreamHandlerFactorγ(new FsUrlStreamHandler、Factory());
}
public static void main(String[] args) throws Exception {
InputStream in = null;
try {
in = new URL(args[0]).openStream();
IOUtils.copyBytes(in, System.out, 4096, false);
} finally {
IOutils.closeStream(in);
}
}
}


我们可以调用Hadoop 中简洁的IOUtils 类,并在finally 子句中关闭数据流,

同时也可以在输入流和输出流之间复制数据(本例中为System.out)。copyBytes

方法的最后两个参数,第一个用于设置复制的缓冲区大小,第二个用于设置复制结束后是否关闭数据流。这里我们选择自行关闭输入流,因而System.out 不关

闭输入流。

下面是一个运行示例:

% hadoop URLCat hdfs://localhost/user/tom/quangle.txt

On the top of the Crumpetty Tree

The Quangle Wangle sat,

But his face you could not see,

On account of his Beave Hat.

通过FileSystem API 读取数据

正如前一小节所解释的,有时无法在应用中设置URLStreamHandlerFactory实例。这种情况下,需要使用FileSystem API 来打开一个文件的输入流。

Hadoop 文件系统中通过HadoopPath 对象来代表文件(而非java.io.File 对象,因为它的语义与本地文件系统联系太紧密)。你可以将一条路径视为一个Hadoop 文件系统URI ,如hdfs://localhost/userltom/quangle. txt 。

FileSystem 是一个通用的文件系统API,所以第一步是检索我们需要使用的文件系统实例,这里是HDFS 。获取FileSystem 实例有两种静态工广方法:

public staticFileSystem get(Configuration conf) throws IOException

Public staticFileSystem get(URI uri, Configuration conf) throws IOException

Configuration 对象封装了客户端或服务器的配置,通过设置配置文件读取类路径来实现(如conf/core-site. xml) 。第一个方法返回的是默认文件系统(在conf/core-site.xml 中指定的,如果没有指定,则使用默认的本地文件系统)。第二个方法通过给定的URI 方案和权限来确定要使用的文件系统,如果给定URI 中没有指定方案,则返回默认文件系统。

有了FileSystem 实例之后,我们调用open()函数来获取文件的输入流:

Public FSDatalnputStream open(Path f) throws IOException

Public abstract FSDatalnputStream open(Path f , int bufferSize)throws IOException

第一个方法使用默认的缓冲区大小4 KB。

将上述方法结合起来,我们重写上一个例子:

直接使用FileSystem 以标准输出格式显示Hadoop 文件系统中的文件

public class FileSystemCat {
public static void main(String[] args)throws Exception {
String uri = args[0] ;
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(uri), conf);
InputStream in = null;
try {
in = fs.open(new Path(uri));
IOUtils.copyBytes(in , System.out, 4096 ,false);
} finally {
IOUtils.closeStream(in);
}
}
}

FSDatalnputStream

实际上, FileSystem 对象中的open() 方住返回的是FSDatalnputStream对象,而不是标准的java.io 类对象。这个类是继承了java.io.DatalnputStream 接口的一个特殊类,井支持随机访问,由此可以从流的任意位置读取数据。

package org.apache.hadoop.fs;

public class FSDatalnputStream extendsDatalnputStream

implements Seekable, PositionedReadable {

// implementation elided

}

Seekable 接口支持在文件中找到指定位置,并提供一个查询当前位置相对于文件起始位置偏移量(getPos ())的查询方法:

public interface Seekable {

void seek(long pos) throws IOException;

long getPos() throws IOException;

boolean seekToNewSource (long tagetPos) throwsIOException;

}

务必牢记, seek() 方也是一个相对高开销的操作,需要慎重使用。建议用流数据来构建应用的访问模式(如使用MapReduce) ,而非执行大量的seek() 方法。

写入数据

FileSystem 类有一系列创建文件的方法。最简单的方法是给准备创建的文件指定

一个Path 对象,然后返回一个用于写入数据的输出流:

public FSDataOutputStream create(Path f)throws IOException

上述方法有多个重载版本,允许我们指定是否需要强制覆盖已有的文件、文件备份

数量、写入文件时所用缓冲区大小、文件块大小以及文件权限。

还有一个重载方法progressable ,用于传递回调接口,如此一来,可以把数据写人数据节点的进度通知到你的应用:

package org.apache.hadoop.util;

public interface Progressable {

public void progress();

}

另一种新建文件的方法,是使用append()方法在一个已有文件末尾追加数据(还存

在一些其他重载版本) :

public FSDataOutputStream append(Path f)throws IOException

该追加操作允许一个writer 打开文件后在访问该文件的最后偏移量处追加数据。有了这个API ,某些应用可以创建无边界文件,例如,日志文件可以在机器重启后在已有文件后面继续追加数据。该追加操作是可选的,井非所有Hadoop 文件系统都实现了该操作。例如, HDFS 支持追加,但S3 文件系统就不支持。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值