1.HDFS的java访问接口
1)org.apache.hadoop.conf.Configuration
读取、解析配置文件(如core-site.xml/hdfs-default.xml/hdfs-site.xml等),或添加配置的工具类。
2)org.apache.hadoop.fs.FileSystem
代表分布式文件系统的一个实例,是一个通用的文件系统API,提供了不同文件系统的统一访问方式。
3)org.apache.hadoop.fs.Path
是Hadoop文件系统中统一的文件或目录描述,类似于java.io.File对本地文件系统的文件或目录描述。
4)org.apache.hadoop.fs.FSDataInputStream
对Hadoop中数据输入流的统一封装
5)org.apache.hadoop.fs.FSDataInputStream
对Hadoop中数据输出流的统一封装
2.java访问HDFS主要编程步骤
1)构建Configuration对象,读取并解析相关配置文件
Configuration conf = new Configuration();
2)设置相关属性
conf.set("fs.defaultFS","hdfs://192.168.1.113:8020");
3)获取特定文件系统实例fs(以HDFS文件系统实例)
FileSystem fs=FileSystem.get(URI.create("hdfs://192.168.1.113:8020/user/root/input/words"), conf);
4)通过文件系统实例fs进行文件操作(以删除文件实例)
fs.delete(new Path("/user/root/someWords.txt"));
3.操作实例
1)查询HDFS集群文件系统中一个文件,并打印文件内容
首先在文件系统中确保所要读取的文件存在
java编码读取
package com.jf.hdfs;import java.io.IOException;import java.net.URI;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 CatHdfsFile { private static String file = "hdfs://192.168.1.113:8020/user/root/input/words"; public static void main(String[] args) throws IOException { //Configuration是读取、解析配置文件(如core-site.xml/hdfs-default.xml/hdfs-site.xml等),或添加配置的工具类 Configuration conf = new Configuration(); //FileSystem是一个通用的文件系统API,提供了不同文件系统的统一访问方式 FileSystem fs = FileSystem.get(URI.create(file), conf); //Path是Hadoop文件系统中统一的文件或目录描述,类似于java.io.File对本地文件系统的文件或目录描述 Path path = new Path(file); //FSDataInputStream对Hadoop中数据输入流的统一封装 FSDataInputStream is = fs.open(path); byte[] buff = new byte[1024]; int length = 0; while ((length = is.read(buff)) != -1) { System.out.println(new String(buff, 0, length)); } }}
执行输出结果
hello aworld bhello cjiafeng bsean a这是测试文件,只是一个测试
4.java访问HDFS中数据块
1.相关java类介绍
Configured类:Configured类中实现了Configurable接口,实现了getConf和setConf方法可以获取Configuration对象。Configuration对象可以获取Hadoop的所有配置文件中的数据,还可以通过使用命令行中使用-D(-D是一个标识)使用的变量以及值
// inherit javadoc @Override public void setConf(Configuration conf) { this.conf = conf; } // inherit javadoc @Override public Configuration getConf() { return conf; }
Tool接口:里面有一个run方法,可以通过ToolRunner来执行,Tool里面的run方法。
public static int run(Configuration conf, Tool tool, String[] args) throws Exception{ if(conf == null) { conf = new Configuration(); } GenericOptionsParser parser = new GenericOptionsParser(conf, args); //set the configuration back, so that Tool can configure itself tool.setConf(conf); //get the args w/o generic hadoop args String[] toolArgs = parser.getRemainingArgs(); return tool.run(toolArgs); }
LocatedBlock类:存储文件的数据块对象,可以获取存储文件的所有datanode。
ExtendedBlock类:通过LocatedBlock的getBlock()来获取,该类主要可以获取数据块的id和name。
2.java代码访问程序
package com.jf.hdfs;import java.net.URI;import java.util.List;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.conf.Configured;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.hdfs.client.HdfsDataInputStream;import org.apache.hadoop.hdfs.protocol.DatanodeInfo;import org.apache.hadoop.hdfs.protocol.ExtendedBlock;import org.apache.hadoop.hdfs.protocol.LocatedBlock;import org.apache.hadoop.util.Tool;import org.apache.hadoop.util.ToolRunner;public class FileBlockList extends Configured implements Tool { public int run(String[] arg0) throws Exception { // 获取Configuration对象 Configuration conf = getConf(); // 通过-Dinput获取参数 String input = conf.get("input"); // 创建文件系统对象 FileSystem fs = FileSystem.get(URI.create(input), conf); // 获取文件输入流对象 HdfsDataInputStream hdis = (HdfsDataInputStream) fs.open(new Path(input)); // 获取所有数据块列表 Listblocks = hdis.getAllBlocks(); // 遍历数据块 for (LocatedBlock locatedBlock : blocks) { // 存有该block的ID和名称 ExtendedBlock eBlock = locatedBlock.getBlock(); System.out.println("id=" + eBlock.getBlockId() + ",name=" + eBlock.getBlockName() + ",blockSize=" + locatedBlock.getBlockSize() + ",startOffset=" + locatedBlock.getStartOffset()); // 获取该数据块所在数据节点的信息 DatanodeInfo[] datanodes = locatedBlock.getLocations(); for (DatanodeInfo datanodeInfo : datanodes) { System.out.println("IPAddr=" + datanodeInfo.getIpAddr() + ",hostname=" + datanodeInfo.getHostName()); } } return 0; } public static void main(String[] args) throws Exception { System.exit(ToolRunner.run(new FileBlockList(), args)); }}
打包之后放入客户端执行该代码程序:
hadoop-2.7.1/bin/hadoop jar my_hadoop-0.0.1-SNAPSHOT.jar com.jf.hdfs.FileBlockList -Dinput=/user/root/input/words
结果:
id=1073741855,name=blk_1073741855,blockSize=82,startOffset=0IPAddr=192.168.1.113,hostname=hadoop
数据块的偏移量是指一个数据块距离一个文件开始的偏移位置。
5.java访问HDFS集群文件系统
1.相关类和方法
FileStatus类:封装文件和目录的文件系统元数据,包括文件长度,块大小,复制,修改时间,所有权和许可信息。
FileSystem上的getFileStatus()方法提供了一种获取FileStatus的方法对象为单个文件或目录。
getAccessTime() //上次访问的时间getOwner() //文件的所有者getGroup() //文件的所属者getPath() //得到文件的路径getPermission() //文件的权限getReplication() //文件的备份数
2.java代码编程
package com.jf.hdfs;import java.net.URI;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.conf.Configured;import org.apache.hadoop.fs.FileStatus;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.util.Tool;import org.apache.hadoop.util.ToolRunner;public class ListFileStatus extends Configured implements Tool { private FileSystem fs; public int run(String[] args) throws Exception { Configuration conf = getConf(); String input = conf.get("input"); fs = FileSystem.get(URI.create(input), conf); // 封装文件和目录的文件系统元数据,包括文件长度,块大小,复制,修改时间,所有权和许可信息 FileStatus[] fileStatuses = fs.listStatus(new Path(input)); for (FileStatus fileStatus : fileStatuses) { process(fileStatus); } return 0; } private void process(FileStatus status) throws Exception { if (status.isFile()) {// 为文件时 System.out.println("------------------"); System.out.println("上次访问时间=" + status.getAccessTime()); System.out.println("文件所有者=" + status.getOwner()); System.out.println("文件所属者=" + status.getGroup()); System.out.println("文件路径=" + status.getPath()); System.out.println("文件权限=" + status.getPermission()); System.out.println("文件备份数=" + status.getReplication()); System.out.println("------------------"); } else if (status.isDirectory()) {// 判断是文件夹时进行递归调用 // 在HDFS中,当FileStatus对象代表一个目录的时候没有相应的方法来获取该目录下的所有文件要通过FileSystem类来获取该目录下的文件 FileStatus[] fileStatus = fs.listStatus(status.getPath()); for (FileStatus fileStatus2 : fileStatus) { process(fileStatus2); } } } public static void main(String[] args) throws Exception { System.exit(ToolRunner.run(new ListFileStatus(), args)); }}
3.执行结果
执行命令
hadoop-2.7.1/bin/hadoop jar my_hadoop-0.0.1-SNAPSHOT.jar com.jf.hdfs.ListFileStatus -Dinput=/user/root/input
输出结果