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... 到此结束咯....