HDFS JAVA API

本文详细介绍了如何使用Hadoop的Java API进行文件系统操作,包括读取、创建、删除文件和目录,追加内容,以及查询文件元数据。示例代码展示了如何初始化Configuration对象,获取FileSystem实例,以及使用FSDataInputStream和FSDataOutputStream进行文件读写。此外,还涵盖了文件上传、下载、目录遍历和文件存在性检查等常见操作。
摘要由CSDN通过智能技术生成

Hadoop主要使用JAVA语言编写实现的,Hadoop不同的文件系统之间通过调用JAVA API进行交互。HDFS的命令行本质上就是JAVA API的应用。

常用 JAVA API 介绍

org.apache.hadoop.fs.FileSystem:一个通用文件系统的抽象基类,可以被分布式文件系统继承。所有可能使用Hadoop文件系统的代码都要使用到这个类。

org.apache.hadoop.fs.FileStatus:一个接口,用于向客户端展示系统中文件和目录的元数据,具体包括文件大小、块大小、副本信息、所有者、修改时间等,可通过FileSystem.listStatus()方法获得具体的实例对象。

org.apache.hadoop.fs.FSDataInputStream:文件输入流,用于读取Hadoop文件。

org.apache.hadoop.fs.FSDataOutputStream:文件输出流,用于写Hadoop文件。

org.apache.hadoop.conf.Configuration:访问配置项。所有的配置项的值,如果在core-site.xml中有对应的配置,则以core-site.xml为准。

org.apache.hadoop.fs.Path:用于表示Hadoop文件系统中的一个文件或者一个目录的路径。

org.apache.hadoop.fs.PathFilter:一个接口,通过实现PathFilter.accept(Path path)来判定是否接收路径path表示的文件或目录。

常用 JAVA API 操作

首先需要导入相关的依赖

<dependency>
 <groupId>org.apache.hadoop</groupId>
 <artifactId>hadoop-client</artifactId>
 <version>3.1.3</version> # hadoop版本
</dependency>

查询HDFS文件内容并输出

public static void FileSystemcat(String path) throws Exception {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");  //设置HDFS访问地址
		FileSystem fs = FileSystem.get(conf);  //取得FileSystem文件系统实例
		InputStream in = fs.open(new Path(path));  //打开文件输入流
		IOUtils.copyBytes(in, System.out, 4096, false);  //输出文件内容
		IOUtils.closeStream(in);  //关闭输入流
        fs.close();
	}

说明:

在运行HDFS程序之前,需要先初始化Configuration对象,该对象的主要作用是读取HDFS 系统配置信息,也就是安装Hadoop时候的配置文件,例如core-site.xml,hdfs-site.xml等文件。FileSystem是一个普通的文件系统API,可以使用静态工厂方法取得FileSystem实例,并传入Configuration对象参数。通过调用FileSystem对象的open()方法,取得文件的输入流。该方法实际上返回的是一个FSDataInputStream对象,而不是标准的java.io类对象。FSDataInputStream类是继承了java.io.DataInputStream类的一个特殊类,支持随机访问,因此可以从流的任意位置读取数据。FSDataInputStream类的主要作用是使用DataInputStream包装一个输入流,并且使用BufferedInputStream实现对输入的缓冲。

创建目录

public static void createDir(String path) throws IOException {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");
		FileSystem fs = FileSystem.get(conf);
		boolean isok = hdfs.mkdirs(new Path(path));  //创建目录
		if (isok) {
			System.out.println("创建目录成功!");
		} else {
			System.out.println("创建目录失败!");
		}
		fs.close();
	}

说明:

使用FileSystem的创建目录方法mkdirs(),可以创建未存在的父目录,就像java.io.File的mkdirs()方法一样,如果目录创建成功,则返回true,失败则返回false。

创建文件

public static void createFile(String path,String w) throws Exception {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");
		FileSystem fs = FileSystem.get(conf);
		FSDataOutputStream outputStream = fs.create(new Path(path));  //打开一个输出流
		outputStream.write(w.getBytes());  //写入文件内容
		outputStream.close();
		fs.close();
		System.out.println("文件创建成功!");
	}

说明:

FileSystem实例的create()方法返回一个文件输出流对象FSDataOutputStream,该类继承了java.io.DataOutputStream类。与FSDataOutputStream不同的是,FSDataOutputStream类不支持随机访问,因此不能从文件的任意位置写入数据,只能从文件末尾追加数据。create()方法有多个重载方法,允许指定是否强制覆盖已有文件(默认覆盖)、文件副本数量、写入文件的缓冲大小、文件块大小、文件权限许可等。在调用create()方法时,还可以传入一个Progressable对象,这是一个接口,其中定义了一个progress()回调方法,使用该方法可以得知数据被写入数据节点的进度。代码可以改为

public static void createFile(String path,String w) throws Exception {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");
		FileSystem fs = FileSystem.get(conf);
        InputStream in=new BufferedInputStream(new FileInputStream(w));
		FSDataOutputStream outputStream = fs.create(new Path(path)),
           new Progressable(){
           @Override
           public void progress(){
               System.out.println(".");
           }
        });
		IOUtils.copyBytes(in,outputStream ,4096,false);
		fs.close();
		System.out.println("文件创建成功!");
	}

则可以通过在控制台打印“.”来显示上传创建进度。

删除文件

public static void deleteFile(String path) throws Exception {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");
		FileSystem fs = FileSystem.get(conf);
		boolean isok = fs.deleteOnExit(new Path(path));  //删除文件
		if (isok) {
			System.out.println("删除成功!");
		} else {
			System.out.println("删除失败!");
		}
		fs.close();
	}

说明:

使用FileSystem的deleteOnExit()方法,可以对HDFS文件系统中已经存在的文件进行删除。

遍历文件和目录

public static void listStatus(String path) throws Exception {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");
		FileSystem hdfs;= FileSystem.get(conf);
		FileStatus[] fs = hdfs.listStatus(new Path(path));  //遍历HDFS上的文件和目录
		if (fs.length > 0) {
			for (FileStatus f : fs) {
				showDir(f, hdfs);
			}
		}
	}

	private static void showDir(FileStatus f, FileSystem hdfs) throws Exception {
		Path path = f.getPath();
		System.out.println(path);  //输出文件或目录的路径
		if (f.isDirectory()) { 
			FileStatus[] file = hdfs.listStatus(path);   //如果是目录,则递归遍历该目录下的所有子目录或文件
			if (file.length > 0) {
				for (FileStatus files : file) {
					showDir(files, hdfs);
				}
			} else {
				System.out.println("当前并未创建目录或文件");
			}
		}
	}

说明:

通过调用FileSystem的listStatus()方法获得指定路径下的一级子目录及文件,并将结果存储于FileStatus类型的数组中,然后循环遍历该数组,当遇到目录时,再次调用listStatus()方法取得该目录下的所有子目录及文件,从而能够递归取得指定路径下的所有目录及文件。

查看文件元数据

public static void fileStatusCat(String path) throws Exception {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");
		FileSystem fs = FileSystem.get(conf);
		FileStatus fileStatus = fs.getFileStatus(new Path(path));
		if (fileStatus.isDirectory()) {
			System.out.println("文件夹详细信息:");
		} else {
			System.out.println("文件详细信息:");
		}
		// 输出元数据信息
		System.out.println("文件路径:" + fileStatus.getPath());
		System.out.println("文件修改日期:" + new Timestamp(fileStatus.getModificationTime()).toString());
		System.out.println("文件上次访问日期:" + new Timestamp(fileStatus.getAccessTime()).toString());
		System.out.println("文件长度:" + fileStatus.getLen());
		System.out.println("文件路径:" + fileStatus.getPath());
		System.out.println("文件备份数:" + fileStatus.getReplication());
		System.out.println("文件块大小:" + fileStatus.getBlockSize());
		System.out.println("文件所有者:" + fileStatus.getOwner());
		System.out.println("文件所在分组:" + fileStatus.getGroup());
		System.out.println("文件的权限:" + fileStatus.getPermission().toString());
	}

说明:

使用FileSystem的getFileStatus()方法,可以获得HDFS文件系统中的文件或目录的元数据信息,包括文件路径、文件修改日期、文件上次访问日期、文件长度、文件备份数、文件大小等。getFileStatus()方法返回一个FileStatus对象,元数据信息则封装在了该对象中。

从本地上传文件

public static void copyFromLocal(String hPath, String localPath) throws Exception {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");
		FileSystem fs = FileSystem.get(conf);
		Path src = new Path(localPath);  //本地目录/文件
		Path dst = new Path(hPath);  //HDFS目录/文件
		fs.copyFromLocalFile(src, dst);  //复制上传本地文件至HDFS文件系统中
		System.out.println("文件上传成功!");
        fs.close();
	}

说明:

使用FileSystem的copyFromLocalFile()方法,可以将操作系统本地的文件上传到HDFS文件系统中,该方法需要传入两个Path类型的参数,分别代表本地目录/文件和HDFS目录/文件。

从HDFS下载文件

public static void downloadToLocal(String path, String localPath) throws Exception {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");
		FileSystem fs = FileSystem.get(conf);
		Path src = new Path(path);  //HDFS目录/文件
		Path dst = new Path(localPath);  //本地目录/文件
		fs.copyToLocalFile(false, src, dst);  //从HDFS文件系统中复制下载文件至本地
		System.out.println("文件下载成功!");
        fs.close();
	}

说明:

使用FileSystem的copyToLocalFile()方法,可以将HDFS文件系统中的文件下载到操作系统本地,该方法需要传入两个Path类型的参数,分别代表本地目录/文件和HDFS目录/文件。

检测目录是否存在

public static Boolean isExist(String path) throws Exception {
		try {
			Configuration conf = new Configuration();
			conf.set("fs.default.name", "hdfs://centos01:9000");
			FileSystem fs = FileSystem.get(conf);
			FileStatus fileStatus = fs.getFileStatus(new Path(path));
			if (fileStatus.isDirectory()) {  //判断文件是否存在
				return true;
			}
			return false;
		} catch (Exception e) {
			return false;
		}
	}

说明:

使用FileSystem的getFileStatus()方法,可以对该方法返回的类的isDirectory()方法判断文件是否存在。

追加文件内容

public static void appendFile(String w,String path) throws Exception {
		Configuration conf = new Configuration();
		conf.set("fs.default.name", "hdfs://centos01:9000");
		conf.setBoolean("dfs.support.append", true);  //配置可追加
		conf.setBoolean("dfs.client.block.write.replace-datanode-on-failure", true);
		conf.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");
		FileSystem fs = FileSystem.get(conf);
		FSDataOutputStream outputStream = fs.append(new Path(path));  //要追加的文件路径
		outputStream.write(w.getBytes(StandardCharsets.UTF_8));  //要追加的文件内容
		outputStream.close();
		fs.close();
	}

说明:

dfs.support.append:设置允许文件追加内容。

dfs.client.block.write.replace-datanode-on-failure:如果在写入管道中存在一个DataNode或者网络故障时,那么DFSClient将尝试从管道中删除失败的DataNode,然后继续尝试剩下的DataNodes进行写入。

dfs.client.block.write.replace-datanode-on-failure.policy:设置NEVER为永远不添加新的DataNode。

使用FileSystem的append()方法,提供要追加的文件路径,返回FSDataOutputStream类型,就可以使用FSDataOutputStream 追加文件内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值