hadoop之hdfs api操作
hadoop只有shell操作吗?那么我在程序中如何使用呢?
当然不是,肯定又api呀,有接口呀,不能傻乎乎的开发呀,你能想到的,hadoop的开发者也能想到,那么下面我就来介绍一下,api的使用吧。根据语言的不同又分为几种,在此,我仅以编程语言排行的第一-----JAVA 语言来输出demo,当然也可以用python,怎么开心,怎么来?
首先搞过java的人都知道,写代码的第一件事儿就是找依赖的jar包,如果不想找,你也可以把hadoop安装目录下面所以的jar包都搞进去,没问题的。刚开始学习的我,就是这样搞的。
Hadoop API被分成(divide into)如下几种主要的包(package)
org.apache.hadoop.conf 定义了系统参数的配置文件处理API。
org.apache.hadoop.fs 定义了抽象的文件系统API。
org.apache.hadoop.io 定义了通用的I/O API,用于针对网络,数据库,文件等数据对象做读写操作。
org.apache.hadoop.ipc 用于网络服务端和客户端的工具,封装了网络异步I/O的基础模块。
org.apache.hadoop.mapred Hadoop分布式计算系统(MapReduce)模块的实现,包括任务的分发调度等。
org.apache.hadoop.metrics 定义了用于性能统计信息的API,主要用于mapred和dfs模块。
org.apache.hadoop.record 定义了针对记录的I/O API类以及一个记录描述语言翻译器,用于简化将记录序列化成语言中性的格式(language-neutral manner)。
org.apache.hadoop.tools 定义了一些通用的工具。
org.apache.hadoop.util 定义了一些公用的API。
hadoop中关于文件操作类基本上全部是在"org.apache.hadoop.fs"包中,
这些API能够支持的操作包含:打开文件,读写文件,删除文件等。
Hadoop类库中最终面向用户提供的接口类是FileSystem,该类是个抽象类,只能通过来类的get方法得到具体类。
get方法存在几个重载版本,常用的是这个:static FileSystem get(Configuration conf);
package hdfs.test;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
// 测试hdfs api连接
public class HdfsTest {
// 创建新文件
public static void createFile(String dst, byte[] contents) throws IOException{
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://localhost:9000");
FileSystem fs = FileSystem.get(conf);
Path dstPath = new Path(dst); // 目标路径
// 打开一个输出流
FSDataOutputStream outputStream = fs.create(dstPath);
outputStream.write(contents);
outputStream.close();
fs.close();
System.out.println("文件创建成功!");
}
// 上传本地文件
public static void uploadFile(String src, String dst) throws IOException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path srcPath = new Path(src); // 原路径
Path dstPath = new Path(dst); // 目标路径
// 调用文件系统的文件复制函数,前面参数是指是否删除原文件,true为删除,默认为false
fs.copyFromLocalFile(false, srcPath, dstPath);
// 打印文件路径
System.out.println("Upload to " + conf.get("fs.default.name"));
System.out.println("------------list files------------" + "\n");
FileStatus[] fileStatus = fs.listStatus(dstPath);
for (FileStatus file : fileStatus) {
System.out.println(file.getPath());
}
fs.close();
}
// 删除文件
public static void delete(String filePath) throws IOException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path path = new Path(filePath);
boolean isok = fs.deleteOnExit(path);
if (isok) {
System.out.println("delete ok!");
} else {
System.out.println("delete failure");
}
fs.close();
}
// 创建目录
public static void mkdir(String path) throws IOException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path srcPath = new Path(path);
boolean isok = fs.mkdirs(srcPath);
if (isok) {
System.out.println("create dir ok!");
} else {
System.out.println("create dir failure");
}
fs.close();
}
// 读取文件的内容
public static void readFile(String filePath) throws IOException {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path srcPath = new Path(filePath);
InputStream in = null;
try {
in = fs.open(srcPath);
IOUtils.copyBytes(in, System.out, 4096, false); // 复制到标准输出流
} finally {
IOUtils.closeStream(in);
}
}
public static void main(String[] args) throws IOException {
// 测试上传文件
uploadFile("C:\\test\\c.txt", "/test");
// 测试创建文件
byte[] contents = "hello world 世界你好\n".getBytes();
createFile("test/test.txt",contents);
// 测试删除文件
// delete("test/test.txt"); //使用相对路径
// 测试新建目录
// mkdir("test1");
// delete("test1"); //删除目录
// 测试读取文件
readFile("/input/d.txt");
}
}
HDFS API 的核心就是实例化构建filesystem对象来操作hdfs文件系统的。
HDFS javaAPI 核心就是构建filesystem对象,这个类似于文件系统,怎么构建呢?就是通过下面这种方式。
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://localhost:9000");
FileSystem fileSystem = FileSystem.get(conf);
下面介绍一下他的操作呦,和shell有一些雷同哦,就是把参数当成了方法名。
实例:
hdfs dfs -mkdir aa == fileSystem.mkdir(new Path("aa"));
你学会了么?
下面介绍几个例子:
1.创建文件夹
判断是否存在,不存在再创建。
if (!fileSystem.exists(new Path("/test"))) {
fileSystem.mkdirs(new Path("/test"));
}
2.创建文件
in - InputStream to read from 原文件路径
out - OutputStream to write to hdfs 目录
the size of the buffer 缓冲大小
close - whether or not close the InputStream and OutputStream at the end. The streams are closed in the finally clause. 是否关闭流
FSDataOutputStream out = fileSystem.create(new Path("/out"));
FileInputStream in = new FileInputStream("c:/test/test.zip");
IOUtils.copyBytes(in, out, 1024, true);
3.上传本地文件
delSrc - whether to delete the src是否删除源文件
overwrite - whether to overwrite an existing file是否覆盖已存在的文件
srcs - array of paths which are source 可以上传多个文件数组方式
dst – path 目标路径
fileSystem.copyFromLocalFile(src, dst);
fileSystem.copyFromLocalFile(delSrc, src, dst);
fileSystem.copyFromLocalFile(delSrc, overwrite, src, dst);
fileSystem.copyFromLocalFile(delSrc, overwrite, srcs, dst);
4 重命名HDFS文件
fileSystem.rename(src, dst);
5.删除文件
# True 表示递归删除
fileSystem.delete(new Path("/test"), true);
6.查看目录及文件信息
FileStatus[] fs = fileSystem.listStatus(new Path("/"));
for (FileStatus f : fs) {
String dir = f.isDirectory() ? "目录":"文件";
String name = f.getPath().getName();
String path = f.getPath().toString();
System.out.println(dir+"----"+name+" path:"+path);
System.out.println(f.getAccessTime());
System.out.println(f.getBlockSize());
System.out.println(f.getGroup());
System.out.println(f.getLen());
System.out.println(f.getModificationTime());
System.out.println(f.getOwner());
System.out.println(f.getPermission());
System.out.println(f.getReplication());
System.out.println(f.getSymlink());
}
7.查找某个文件在HDFS集群的位置
FileStatus fs = fileSystem.getFileStatus(new Path("/data"));
BlockLocation[] bls=fileSystem.getFileBlockLocations(fs, 0, fs.getLen());
for (int i = 0,h=bls.length; i < h; i++) {
String[] hosts= bls[i].getHosts();
System.out.println("block_"+i+"_location: "+hosts[0]);
}
8.获取HDFS集群上所有节点名称信息
DistributedFileSystem hdfs = (DistributedFileSystem) fileSystem;
DatanodeInfo[] dns=hdfs.getDataNodeStats();
for (int i = 0,h=dns.length; i < h; i++) {
System.out.println("datanode_"+i+"_name: "+dns[i].getHostName());
}
你学会了么?
下面再介绍一下,jar包的引入方式,才用maven的方式进行管理jar包,麻麻再也不用担心我的jar包找不到了....
maven安装配置参考:https://www.jianshu.com/p/adc0c92db600
很详细很详细哦!这年头我已经不想再装这种东东了,新人请参考上面链接。
maven依赖
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.8.3</version>
</dependency>
试一下???
public void test() throws Exception{
FileStatus[] listStatus = fs.listStatus(new Path("/"));
for(FileStatus status:listStatus){
System.out.println("文件全路径:"+status.getPath());
System.out.println(status.isDirectory()?"这是文件夹":"这是文件");
System.out.println("块大小:"+status.getBlockSize());
System.out.println("文件长度:"+status.getLen());
System.out.println("副本数量:"+status.getReplication());
System.out.println("--------------------------------");
}
fs.close();
}
搞定!!! 欧了
忽然想起来一个组件,使用测试学习,挺好用的哦,那就是单元测试,Junit
嘻嘻....
有兴趣的小伙伴可以搞一波哦...
参考链接:
https://www.w3cschool.cn/junit/
bingo... 到此结束咯....