org.apache.hadoop.fs.FileSystem 是HDFS的文件系统抽象,在分布式系统中管理HDFS文件和目录。文件内容存储在由多个相同大小的块(如64M)构成的datanode节点中,namenode节点存储着这些块的信息和元信息。FileSystem按顺序访问这些块数据。FileSystem首先通过NameNode节点获取块信息,然后一个接一个地打开,读取,关闭。当FileSystem打开第一个块之后在完成读取后关闭之,然后打开第二个块。HDFS会对块数据进行多次复制以获取更高的可靠性和可扩展性。如果客户端本身就是datanode,则它会先尝试本地读取块数据,如果读取失败,则会尝试集群中的两一个datanode。FileSystem用FSDataOutputStream和FSInputStream两个类以流的方式读写内容。此外Hadoop还提供了多个FileSystem的子类。如下:
- DistributedFileSystem:访问分布式环境中的HDFS文件
- LocalFileSystem: 访问本地系统中的HDFS文件
- FTPFileSystem: To access HDFS file FTP client
- WebHdfsFileSystem: 访问整个互联上的HDFS文件
URI和Path类:
Hadoop的URI类用来锁定文件位置。它通过FileSystem以 hdfs://host:port/location 来访问文件。例如:
hdfs://localhost:9000/user/joe/TestFile.txt
URI uri = URI.creat("hdfs://host:port/path")
Host和port可以在 conf/core-site.xml文件中做如下配置:
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
Path实例由URI实例构造,可以避免URI的OS依赖性,如Windows在路径中使用\\path 然而Linxu使用//。可以避免父子依赖性。
创建过程如下:
Path path=new Path (uri); //It constitute URI
Configuration
Configuration类传递Hadoop的配置信息给FileSystem。它通过类加载器来加载core-site.xml 和core-default.xml,并且保存Hadoop的配置信息如:fs.defaultFS, fs.default.name等。
创建过程如下:
Configuration conf = new Configuration();
此外,可以通过Configuration实例来配置参数,如:
conf.set("fs.default.name","hdfs://localhost:9000");
FileSystem
创建FileSystem实例的方法如下:
public static FileSystem get(Configuration conf);
public static FileSystem get(URI uri, Configuration conf);
public static FileSystem get(URI uri, Configuration conf, String user);
FileSystem 通过NameNode来定位DataNode ,然后按照序列顺序访问DataNode中的块数据来读取整个文件内容。FileSystem 主要的使用Java IO FileSystem 接口方法有DataInputStream和DataOutputStream。此外,如果想要获得本地文件系统实例,可以直接通过getLocal方法,如下:
public static LocalFileSystem getLocal(Configuration conf);
FSDataInputStream类
FSDataInputStream包装了DataInputStream类并且实现了Seekable, PositionedReadable接口,从而提供了诸如getPos(),seek()方法来实现对HDFS文件的随机访问。
FIleSystem的open()方法可以返回一个FSDataInputStream实例,如下:
URI uri = URI.create("hdfs://host:port/file Path");
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(rui, conf);
FSDataInputStream in = fs.open(new Path(uri));
以上方法得到的FSDataInputStream是默认缓冲空间4096byte。我们可以在创建输入流的时候指定缓冲空间大小,如下:
public abstract FSDataInputStream open(Path path, int sizeBuffer)
FSDataInputStream实现了Seekable接口的seek(long pos)和getPos()方法。
public interface Seekable{
void seek(long pos) throws IOException;
long getPos() throws IOException;
boolean seekToNewSource(long targetPos) throws IOException;
}
seek()方法搜寻给定的offset偏移量的文件位置,从而使read()方法可以从给定的文件位置开始读取。getPos()方法返回输入流当前的文件位置。一个小例子:
FileSystem fs = FileSystem.get(uri, conf);
FSDataInputStream in = fs.open(new Path(uri));
byte[] buffer = new byte[5];
in.seek(5); // sent to 5th position
in.read(buffer, 0, 5);//从输入流的第5个位置开始读取5个字节到buffer
System.out.println(new String(buffer));//打印从第5个位置开始的连续5个字节。(相对与输入流而言的!)
in.read(10, buffer, 0, 5);//从第10个位置开始读取5个字节到buffer
FSDataInputStream 也实现了PositionedReadable接口,从而提供了read和readFully方法来从seek的位置开始读取部分字节数据。如下:
read(long position, byte[] buffer, int offset, int length);
FSDataOutputStream
FileSytem的create()方法返回FSDataOutputStream,此方法可以创建新的HDFS文件或者在文件末尾EOF追加内容。它没有提供seek()方法,所以只能在EOF处写入内容。它包装了Java IO的DataOutputStream方法,并且提供了getPos()方法,获取文件位置信息,write()方法,在末尾写入内容。
如下:
public FSDataOutputStream create(Path f) // 创建空文件
public FSDataOutputStream append(Path f)//在已存在文件后追加
Creat()方法还可以传递Progressable接口参数,用来追踪文件创建状态,如下:
public FSDataOutputStream create(Path f, Progressable progress);
FileStatus
FileSystem的getFileStatus()方法可以返回FileStatus,FileStatus提供了HDFS文件的元信息。
如下:
URI uri = URI.create(strURI);
FileSystem fileSystem = FileSystem.get(uri, conf);
FileStatus fileStatus = fileSystem.getFileStatus(new Path(uri));
System.out.println("AccessTime:" + fileStatus.getAccessTime());
System.out.println("Len:"+fileStatus.getLen());
System.out.println("ModificationTime:"+fileStatus.getModificationTime());
System.out.println("Path:"+fileStatus.getPath());
如果uri是一个目录而不是文件,则listStatus()会返回一个FileStatus数组。如下:
public FileStatus[] listStatus(Path f)
Directories
FileSystem提供了如下方法来创建目录:
public boolean mkdirs(Path f);
Delete file
public boolean delete(Path f, boolean recursive) throws IOException
在文件系统中永久性删除文件或目录。