一  hdfs基本介绍

hdfs:分布式文件系统

hdfs有着文件系统共同的特征:

  1. 有目录结构,顶层目录是:  /
  2. 系统中存放的就是文件
  3. 系统可以提供对文件的:创建、删除、修改、查看、移动等功能

hdfs跟普通的单机文件系统有区别:

  1. 单机文件系统中存放的文件,是在一台机器的操作系统中
  2. hdfs的文件系统会横跨N多的机器
  3. 单机文件系统中存放的文件,是在一台机器的磁盘上
  4. hdfs文件系统中存放的文件,是落在n多机器的本地单机文件系统中(hdfs是一个基于linux本地文件系统之上的文件系统)

hdfs的工作机制:

  1. 客户把一个文件存入hdfs,其实hdfs会把这个文件切块后,分散存储在N台linux机器系统中(负责存储文件块的角色:data node)<准确来说:切块的行为是由客户端决定的>
  2. 一旦文件被切块存储,那么,hdfs中就必须有一个机制,来记录用户的每一个文件的切块信息,及每一块的具体存储机器(负责记录块信息的角色是:name node)
  3. 为了保证数据的安全性,hdfs可以将每一个文件块在集群中存放多个副本(到底存几个副本,是由当时存入该文件的客户端指定的)

综述:一个hdfs系统,由一台运行了namenode的服务器,和N台运行了datanode的服务器组成!

 

二  hdfs的配置与启动

1.配置/root/apps/hadoop安装目录/etc/hadoop/core-site.xml文件

<property>
<name>fs.defaultFS</name>   //配置NameNode URI
<value>hdfs://hdp-01:9000</value>
</property>

2.配置/root/apps/hadoop安装目录/etc/hadoop/hdfs-site.xml文件

<property>
<name>dfs.namenode.name.dir</name>     //namenode事物在本地系统的永久存储路径
<value>/root/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>       //datanode在本地文件系统中存放块的路径
<value>/root/dfs/data</value>
</property>

3.在对的机器上启动对的软件

在namenode所对应的节点上先进行初始化,使用命令"hadoop namenode -format",然后启动namenode进程"hadoop-daemon.sh start namenode". 

在datanode所在的各个节点上启动datanode程序,命令为"hadoop-daemon.sh start datanode"

4.使用脚本批量来启动HDFS

首先配置namenode节点到集群中所有机器(包括自己)的免密登陆,再修改各个节点的/etc/hadoop/slaves文件,把需要启动datanode进程的节点列入.然就可以在namenode节点上使用start-dfs.sh 来自动启动整个集群.若要关闭,则使用stop-dfs.sh.

 

三  hadoop命令行客户端的常用命令

hdfs的客户端有多种形式:

  1. 网页形式
  2. 命令行形式
  3. 客户端在哪里运行,没有约束,只要运行客户端的机器能够跟hdfs集群联

1.上传文件到hdfs中

hadoop fs -put /本地文件  /aaa

hadoop fs -moveFromLocal /本地文件  /hdfs路径  ## 跟put的区别是:从本地剪切到hdfs中

2.下载文件到客户端本地磁盘

hadoop fs -get /hdfs中的路径   /本地磁盘目录

hadoop fs -moveToLocal /hdfs路径  /本地路径  ## 从hdfs中移动到本地

除了上面的两个命令之外,另外的命令与linux命令基本相似,只要在其前面加上”hadoop fs -“即可,例如移动hdfs中的文件:hadoop fs -mv /hdfs的路径1  /hdfs的另一个路径2

 

四  在Java项目中hadoopAPI的调用

1.首先需要在java项目中导入hadoop相关的jar包,然后构造Configuration对象和FileSystem对象

Configuration conf = new Configuration();
conf.set("dfs.replication", "2");   // 指定本客户端上传文件到hdfs时需要保存的副本数为:2
conf.set("dfs.blocksize", "64m");  // 指定本客户端上传文件到hdfs时切块的规格大小:64M
FileSystem fs = FileSystem.get(new URI("hdfs://hdp-01:9000/"), conf, "root");
fs.close(); //fs对象使用完毕后需要记得关闭
/*  Configuration参数对象的机制:
 *  构造时,会加载jar包中的默认配置 xx-default.xml
 *  再加载 用户配置xx-site.xml  ,覆盖掉默认参数
 *  构造完成之后,还可以conf.set("p","v"),会再次覆盖用户配置文件中的参数值
 */

2.从本地上传一个文件到hdfs集群中

fs.copyFromLocalFile(new Path("D:/hbase-1.2.1-bin.tar.gz"), new Path("/aaa/"));

3.从hdfs集群中下载一个文件到本地指定的目录中

fs.copyToLocalFile(new Path("/hdp20-05.txt"), new Path("f:/"));

4.修改hdfs集群中文件的名字或者移动文件到指定目录(hdfs集群内部)

fs.rename(new Path("/install.log"), new Path("/aaa/in.log"));

5.在hdfs中创建目录

fs.mkdirs(new Path("/xx/yy/zz"));

6.在hdfs中删除指定的文件或者文件夹

fs.delete(new Path("/aaa"), true);  //如果aaa是一个文件,那么第二餐参数为true表示级联删除文件夹中所包含的内容

7.查询hdfs集群中指定目录下的文件信息

// 只查询文件的信息,不返回文件夹的信息
RemoteIterator<LocatedFileStatus> iter = fs.listFiles(new Path("/"), true); 
     // 将根目录下的子文件夹中的文件也一起递归显示出来,所以用true
while(iter.hasNext()){
LocatedFileStatus
System.out.println("文件全路径:"+status.getPath());
System.out.println("块大小:"+status.getBlockSize());
System.out.println("文件长度:"+status.getLen());
System.out.println("副本数量:"+status.getReplication());
System.out.println("块信息:"+Arrays.toString(status.getBlockLocations()));
}

8.查询hdfs指定目录下的文件和文件夹信息,一级,不会递归显示

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());
}

9.读取hdfs中文件的全部内容

FSDataInputStream in = fs.open(new Path("/test.txt"));
BufferedReader
String line = null;
while ((line = br.readLine()) != null) {   //一行一行的读取文件内容
System.out.println(line);
}
br.close(); //缓冲区需要关闭
in.close(); //打开的文件对象也需要关闭,勿忘

10.读取hdfs中文件的指定偏移量范围的内容

FSDataInputStream in = fs.open(new Path("/xx.dat"));
in.seek(12);   // 将读取的起始位置进行指定,从第12(下标)个字节出开始读起
// 读16个字节
byte[] buf = new byte[16];  //从文件中读取16个字节的数据
in.read(buf);
System.out.println(new String(buf));  //将字节转化为字符串
in.close();

11.往hdfs的文件中写内容

FSDataOutputStream out = fs.create(new Path("/zz.jpg"), false);  //hadoop对java中的DataputStream类进行了包装
FileInputStream
byte[] buf = new byte[1024];
int read = 0;
while ((read = in.read(buf)) != -1) {  // 确保buf中的内容不为空
out.write(buf,0,read);   //读取长度为从0到read
}
in.close();
out.close();