(四)DFS文件操作的原理及代码实现

1、文件操作原理

1.1、下载过程

  • Client向namenode发起Open file 请求。目的是获取指定文件的输入流
  • namenode收到请求之后,会检查路径的合法性,客户端的操作权限。如果检测未通过,则直接报错返回
  • Client也会向namenode发起Getblockloaction请求,获取指定文件的元数据信息。如果上一步检测通过,则namenode会将元数据信息封装到输入流里,返回给客户端
  • 客户端根据元数据信息,直接去对应的datanode读取文件块,然后下载到本地(创建本地的输出流,然后做流的对接)
  • 关闭流

1.2、上传过程

  • Client向namenode发送Create file请求,目的是获取HDFS文件的输出流
  • namenode收到请求之后,会检查路径的合法性,客户端的操作权限。如果检测未通过,则直接报错返回
  • 如果通过检测,namenode会将文件的切块信息(文件被切成几块,保存位置,以及副本位置),然后把这些信息封装到输出流里,返回给客户端。
  • clinet通过输出流发送文件块。会把文件快打散成一个个的package,每个package最大为64KB,再传输一个个的package。这种机制叫做数据流管道机制,目的是充分利用每台机器的带宽,避免网络瓶颈和高延时的连接,最小化推送所有数据的延时
  • 通过数据流管道机制,实现数据的发送和副本的复制。datanode之间会进行package传输,保存副本。每台datanode服务器收到数据之后,会向上游反馈,直到最终反馈给Client,这一轮传输才算完成。

1.3、删除文件过程

  • 客户端向namenode发现删除文件指令,比如:hadoop fs -rm /park01/1.txt
  • namenode收到请求之后,会检查路径的合法性,客户端的操作权限。如果检测未通过,则直接报错返回
  • 如果检测通过,会将对应的文件从元数据中删除。(注意,此时这个文件并没有真正从集群上被删除
  • 每台datanode会定期向namenode发送心跳,会领取删除的指令,找到对应的文件块,进行文件块的删除。

2、编写代码操作文件

2.1、准备环境

  • eclipse版本: Version: Mars.2 Release (4.5.2)
  • eclipse操作hadoop插件下载:链接:https://pan.baidu.com/s/1Hiw50aG2s-PTNEzD1LHcDw   提取码:r3ac 
  • 注意,插件的版本要和hadoop版本保持一致。并将插件放在eclipse的plugins目录下
  • 将hadoop安装包解压到无中文路径的目录
  • 启动eclipse,Window | Preferences | Hadoop Map/Reduce,配置好hadoop的安装目录

  • 新建hadoop工程 File | New | Others,搜索Map/Reduce Project。创建后可以发现hadoop依赖的jar包都自动引用过来了。现在就可以开始写代码操作hdfs了。

2.2、编写代码

  • 连接HDFS
  • 下载
  • 上传
  • 删除
  • 创建目录
  • 重命名
  • 查询目录下文件
  • 递归查询目录下文件
  • 获取文件块信息
package hadoop;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BlockLocation;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.io.IOUtils;
import org.junit.Test;

public class DfsOperation {
	//连接HDFS
	@Test
	public void testConnectNamenode() throws Exception {
		//创建hadoop环境参数对象,通过对象的set方法设置参数
		//通过对象配置的参数优先级>配置文件的配置
		//对象配置的生效范围是当前工作线程。配置文件的生效范围是全局
		Configuration conf = new Configuration();
		//连接HDFS文件系统
		//Hadoop中有多种文件系统(FileSystem有很多实现类),其中最重要的事分布式文件系统
		FileSystem fs = FileSystem.get(new URI("hdfs://192.168.80.100:9000"), conf);

	}
	
	//下载
	@Test
	public void getFile() throws Exception {
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://192.168.80.100:9000"), conf);
		
		//获取HDFS上指定文件的输入流
		InputStream in = fs.open(new Path("/park/test.txt"));
		OutputStream out = new FileOutputStream(new File("test.txt"));
		//通过hadoop提供的数据流工具,完成数据流的传输
		IOUtils.copyBytes(in, out, conf);
		
		in.close();
		out.close();
		fs.close();
	}
	
	//上传
	@Test
	public void putFile() throws Exception {
		Configuration conf = new Configuration();
		conf.set("dfs.replication", "1"); //设置副本数量
		FileSystem fs = FileSystem.get(new URI("hdfs://192.168.80.100:9000"), conf);
		
		ByteArrayInputStream in = new ByteArrayInputStream("testPutFile!".getBytes());
		OutputStream out = fs.create(new Path("/park/putFile.txt"));
		IOUtils.copyBytes(in, out, conf);
		
		in.close();
		out.close();
		fs.close();
	}
	
	//删除
	@Test
	public void deleteFile() throws Exception {
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://192.168.80.100:9000"), conf);
		
		//false只能删除不为空的目录;true不为空的目录也可以删除
		//也可以指定文件去删除
		fs.delete(new Path("/park"), true);
		
		fs.close();
	}
	
	//创建目录  
	//fs.mkdirs(new Path("/park02"));
	
	//重命名
	//fs.rename(new Path("/park"), new Path("/park01"));
	
	//查询目录下文件
	@Test
	public void searchFile() throws Exception {
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://192.168.80.100:9000"), conf);
		
		FileStatus[] ls = fs.listStatus(new Path("/result"));
		for(FileStatus status : ls) {
			System.out.println(status);
		}
		
		fs.close();
	}
	
	//递归查询目录下文件
	@Test
	public void searchFileByR() throws Exception {
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://192.168.80.100:9000"), conf);
		//true表示递归查看
		RemoteIterator<LocatedFileStatus> rt = fs.listFiles(new Path("/result"), true);
		
		while(rt.hasNext()) {
			System.out.println(rt.next());
		}
		
		fs.close();
	}
	
	//获取文件块信息
	@Test
	public void getFileBlocksInfo() throws Exception {
		Configuration conf = new Configuration();
		FileSystem fs = FileSystem.get(new URI("hdfs://192.168.80.100:9000"), conf);
		//0 查看块的起始范围  ;Integer.MAX_VALUE 查看块的结束范围
		//通过这两个参数控制查看的块的范围
		BlockLocation[] data = fs.getFileBlockLocations(new Path("/park/putFile.txt"), 0, Integer.MAX_VALUE);
		for(BlockLocation bl : data) {
			System.out.println(bl);
			//输出结果如下: 0,12,hadoop1
			//0 表示第一块的起始位置; 12表示块的实际大小;hadoop01表示存储的datanode服务器
		}
		
		fs.close();
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值