赞
踩
认识HDFS与常用操作
介绍HDFS前,我先放一组图片,便于大家理解
上面的图是星爷鹿鼎记电影中的截图,我觉得它正好能说明HDFS的架构:
定义
优缺点
正因为它是分布式的文件管理系统,它的优缺点就比较明显
首先看一下几乎介绍HDFS都要发的架构图
优缺点以及整体的架构理解了,下面就要完整的将HDFS各个组件的功能进行说明
NameNode是一个管理者,管理整个HDFS
DataNode是小弟,它主要执行实际的操作
SecondaryNameNode就是秘书,主要更新元数据(例如目录等信息)
它是客户端,是用户,主要是上传下载数据
设置块大小的原理
这个不理解没关系,后面接触多了就懂了,我们就需要记住一句话:HDFS块的大小设置主要取决于磁盘的传输速率
hadoop jar ....
还有我们集群搭建完测试时的 hadoop fs xxx,接下来就正式学习一下HDFS的shell操作hadoop fs 具体的命令 或者 hdfs dfs 具体命令
~
家目录下进行测试-moveFromLocal
从本地剪切文件并粘贴到HDFS中
# 创建一个本地文件
touch wukong.txt
# 将本地文件剪贴到HDFS中
hadoop fs -moveFromLocal ./wukong.txt /input
# 此时源文件在本地系统中就会消失
-copyFromLocal
从本地复制文件并粘贴到HDFS中
# 创建一个本地文件
touch wukong2.txt
# 将本地文件剪贴到HDFS中
hadoop fs -copyFromLocal./wukong.txt /input
# 此时源文件在本地系统中就不会消失
-appendToFile
追加一个文件到已经存在的文件末尾,
# 创建一个本地文件
touch hello.txt
# 编写一个测试数据
hello big data!
# 将本地文件剪贴到HDFS中
hadoop fs -appendToFile./hello.txt /input/wukong2.txt
# 此时我们可以在HDFS中看到wukong2.txt中有了hello.txt的数据
-put
等同于copyFromLocal
# 将本地文件剪贴到HDFS中
hadoop fs -put./hello.txt /input
# 此时/input目录下就会有hello,txt并且本地文件也存在
了解了文件如何上传到HDFS,接下来就是如何从HDFS下载文件,我们先将本地的文件全部删除了
-copyToLocal
从HDFS拷贝到本地
# 将HDFS中的wukong.txt下载到当前位置
hadoop fs -copyToLocal /input/wukong.txt ./
-get
等同于copyToLocal,就是从HDFS下载文件到本地
# 将HDFS中的wukong.txt下载到当前位置
hadoop fs -get /input/wukong2.txt ./
-getmerge
合并下载多个文件,比如HDFS的目录/input下有多个文件hello.txt,wukon2.txt…
# 将HDFS中input中的所有文件中的数据合并到merge_txt.txt并下载到本地
hadoop fs -getmerge /input/* ./merge_txt.txt
直接操作就和我们Linux的命令操作一样,只不过它操作的是HDFS中的文件
-ls
显示目录信息
# 显示HDFS的目录信息
-mkdir
在HDFS上创建目录
# 在HDFS中创建一个文件夹
hadoop fs -mkdir test
-cat
显示文件内容
# 查看HDFS中指定文件的数据
hadoop fs -cat /input/wukong2.txt
-chmod/-chown/-chgrp
Linux文件系统中的用法一样,修改文件所属权限,我就不一 一举例了
# 修改HDFS中wukong.txt的权限
hadoop fs -chmod 666 wukong.txt
-cp
从HDFS的一个路径拷贝到HDFS的另一个路径
# 复制wukong.txt 并起名叫wukon3.txt
hadoop fs -cp wukong.txt wukong3.txt
-mv
在HDFS目录中移动文件
# 移动wukong.txt到HDFS根目录下
hadoop fs -mv wukong.txt /
-tail
显示一个文件的末尾
# 查看wukong2.txt末尾的数据
hadoop fs -tail wukong2.txt
-rm
删除文件或文件夹
# 删除wukong3.txt文件
hadoop fs -rm wukong3.txt
-rmdir
删除空目录
# 删除我们前面创建的HDFS的test目录
hadoop fs -rmdir test
-du
统计文件夹的大小信息
# 查看input文件夹的大小信息
hadoop fs -du -s -h /input
# 不加-s -h指的是显示hdfs对应路径下每个文件夹和文件的大小
# -h指的是是否换算成最大的单位,例如一个文件是100mb,它就会显示100mb
# -s指的是显示hdfs对应路径下所有文件和的大小
-setrep
设置HDFS中文件的副本数量
# 设置wukong.txt的副本数量为10
hadoop fs -setrep 10 /input/wukong.txt
注意:-setrep设置副本数量如果大于当前我们集群中节点数据,默认的副本数量还是我们当前集群数量,当我们增加新的节点后,就会自动创建副本
安装Hadoop的方式和Maven一样,我们直接下载windows版本的依赖包,然后解压,设置环境变量即可
第一步:下载windows版本的Hadoop包
大家可以自行度娘下载哈,Hadoop官方没有提供windows版本,需要自己下载源码然后编译,官网里有介绍编译的方法,或者后台私信我哈
第二步:设置环境变量, HADOOP_HOME 然后设置path %HADOOP_HOME%\bin
第三步:在windows命令行测试
注意:如果上述操作后还有问题可以将bin目录下hadoop.dll
和winutils.exe
放到 C:/windows/system32
目录下
第一步: 创建一个Maven工程HDFSDemo,并导入相应的依赖坐标+日志添加,创建Maven工程我就不演示了,创建好之后,直接在pom.xml中添加所需要的依赖
<dependencies> <!-- 单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <!-- log4j :日志管理jar包--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>2.12.0</version> </dependency> <!-- hadoop依赖的jar包--> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>3.1.3</version> </dependency> </dependencies>
第二步:日志信息配置,在main文件夹下的resources中创建一个log4j2.xml的配置文件,内容如下
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="error" strict="true" name="XMLConfig"> <Appenders> <!-- 类型名为Console,名称为必须属性 --> <Appender type="Console" name="STDOUT"> <!-- 布局为PatternLayout的方式, 输出样式为[INFO] [2018-01-22 17:34:01][org.test.Console]I'm here --> <Layout type="PatternLayout" pattern="[%p] [%d{yyyy-MM-dd HH:mm:ss}][%c{10}]%m%n" /> </Appender> </Appenders> <Loggers> <!-- 可加性为false --> <Logger name="test" level="info" additivity="false"> <AppenderRef ref="STDOUT" /> </Logger> <!-- root loggerConfig设置 --> <Root level="info"> <AppenderRef ref="STDOUT" /> </Root> </Loggers> </Configuration>
第三步: 创建包名: com.company.hdfs
第四步: 创建HDFSDemo类,最终结构如下
第五步:开始正式编写代码操作HDFS前,我们先要了解一下操作步骤:
我在这里直接使用单元测试的方法来对API进行操作,这样方便大家查看,另外,里面的异常我都主动抛出了,大家在编写的时候需要自己捕获一下异常
public class HDFSDemo { private FileSystem fs; /* 在执行单元测试方法前先执行 */ @Before public void before() throws Exception { /* get(final URI uri, final Configuration conf, final String user) uri : NameNode的地址 conf : 配置文件的内容 user : 操作HDFS的用户名 */ Configuration conf = new Configuration(); //1.获取文件系统对象 fs = FileSystem.get(new URI("hdfs://hadoop102:9820"), conf, "hadoopuser"); } /* 在执行单元测试方法后再执行 */ @After public void after(){ //3.关闭资源 try { if (fs != null) { fs.close(); } } catch (IOException e) { e.printStackTrace(); } } ... 后面的代码就是我们的API }
/* 文件上传 */ @Test public void test() throws URISyntaxException, IOException, InterruptedException { /* copyFromLocalFile(boolean delSrc, boolean overwrite, Path src, Path dst) delSrc : 是否删除源文件 overwrite : 如果目标文件已经存在,是否覆盖 如果不覆盖,那么目标文件如果已经存在则报错。 src :源文件路径(本地) dst :目标文件路径(HDFS) */ fs.copyFromLocalFile(true,true, new Path("D:\\io\\hdfs\\aa.txt"), new Path("/input2")); }
/* 文件下载 */ @Test public void test2() throws IOException { /* copyToLocalFile(boolean delSrc, Path src, Path dst, boolean useRawLocalFileSystem) delSrc : 是否删除源文件(HDFS) src : 源文件路径(HDFS) dst : 目标文件路径(本地) useRawLocalFileSystem : 是否使用RawLocalFileSystem */ fs.copyToLocalFile(false,new Path("/input2/aa.txt"), new Path("D:\\io\\hdfs"),false); }
/*
删除文件或目录
*/
@Test
public void test3() throws IOException {
/*
delete(Path f, boolean recursive)
f : 文件或目录的路径
recursive :如果删除的是文件true和false都可以。如果删除的是目录必须是true否则抛异常
注意:如果是空目录true和false也都可以
*/
fs.delete(new Path("/txt/sanguo.txt"),true);
}
/* 修改文件名或移动文件 */ @Test public void test4() throws IOException { /* rename(Path src, Path dst) src : 源文件路径 dst : 目标文件路径 */ //改名 // fs.rename(new Path("/txt/xiyouji.txt"), // new Path("/txt/xiyou.txt")); //移动文件 fs.rename(new Path("/txt/xiyou.txt"), new Path("/input")); }
/* 文件详情查看 */ @Test public void test5() throws Exception { /* listFiles(final Path f, final boolean recursive) f : 目标文件路径 recursive : 是否递归 */ RemoteIterator<LocatedFileStatus> iterator = fs.listFiles(new Path("/"), true); //遍历 while(iterator.hasNext()){ LocatedFileStatus fileStatus = iterator.next(); //获取文件的名字 System.out.println("==============文件的名字:" + fileStatus.getPath().getName() + "==================="); System.out.println("副本数量:" + fileStatus.getReplication()); //获取块信息 BlockLocation[] blockLocations = fileStatus.getBlockLocations(); System.out.println(Arrays.toString(blockLocations)); } }
/*
判断文件或目录
*/
@Test
public void test6() throws IOException {
FileStatus[] status = fs.listStatus(new Path("/input"));
for (FileStatus fileStatus : status) {
if (fileStatus.isDirectory()){
System.out.println(fileStatus.getPath().getName() + "是一个目录");
}else if(fileStatus.isFile()){
System.out.println(fileStatus.getPath().getName() + "是一个文件");
}
}
}
/* 通过流的形式实现上传和下载 上传 */ @Test public void test7() throws Exception { //读取 --- 本地读(文件输入流) FileInputStream fis = new FileInputStream("D:\\io\\hdfs\\long.txt"); //写 --- 向HDFS写数据的流 FSDataOutputStream fos = fs.create(new Path("/input2/long.txt")); //一边读一边写 /* copyBytes(InputStream in, OutputStream out, int buffSize, boolean close) in : 输入流 out : 输出流 buffSize : 缓冲区大小 close : 是否关闭流 */ IOUtils.copyBytes(fis,fos,1024,false); IOUtils.closeStream(fis); IOUtils.closeStream(fos); } /* 下载 */ @Test public void test8() throws IOException { //读 --- 从HDFS上读 FSDataInputStream fis = fs.open(new Path("/input2/long.txt")); //写 --- 向本地写(文件输出流) FileOutputStream fos = new FileOutputStream("D:\\io\\hdfs\\long.txt"); //文件对拷(一边读一边写) IOUtils.copyBytes(fis,fos,1024,true); }
package com.company.hdfs; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import java.io.IOException; /* 创建FileSystem对象 */ public class HDFSDemo2 { /* 在 EditConfigurations中 VM Options : -DHADOOP_USER_NAME=atguigu 注意:如果找不到当前类请先运行一次。 */ public static void main(String[] args) throws IOException { System.out.println("hello"); //用来设置配置内容 Configuration conf = new Configuration(); //配置NameNode的地址 conf.set("fs.defaultFS","hdfs://hadoop102:9820"); //创建文件系统对象 FileSystem fs = FileSystem.get(conf); //上传操作 fs.copyFromLocalFile(false,true, new Path("F:\\IO\\hdfs\\aa.txt"), new Path("/input")); //关闭资源 fs.close(); } }
Exception in thread "main" org.apache.hadoop.security.AccessControlException: Permission denied: user=m, access=WRITE, inode="/input":atguigu:supergroup:drwxr-xr-x
在 EditConfigurations中 VM Options : -DHADOOP_USER_NAME=atguigu 注意:如果找不到当前类请先运行一次。
建立一个HadooopDemo3,然后在hadoop102中复制一份hdfs-site.xml配置文件到Main的resources中,整体结构如下
package com.company.hdfs; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import java.io.IOException; /* 配置参数: 方式1 : xxx-default.xml (服务器 --- 默认配置文件) 方式2 : xxx-site.xml(服务器) 方式3 : 在代码中配置(客户端) 方式4 : 在工程中的配置文件(客户端) 优先级 : 在代码中配置(客户端) > 在工程中的配置文件(客户端) > xxx-site.xml(服务器) > xxx-default.xml (服务器 --- 默认配置文件) */ public class HDFSDemo3 { public static void main(String[] args) throws IOException { Configuration conf = new Configuration(); conf.set("fs.defaultFS","hdfs://hadoop102:9820"); //配置副本的数量 conf.set("dfs.replication","4"); FileSystem fs = FileSystem.get(conf); fs.copyFromLocalFile(false,true, new Path("D:\\io\\hdfs\\aa.txt"), new Path("/input2")); fs.close(); } }
我们在代码中设置副本的数量为4,然后在Main中复制的core-site.xml设置副本数量为2,hadoop102的副本数量是默认的3,执行后,在web中查看
我们会发现,执行的结果是代码中修改的配置参数,因此我们可以得出如下结论:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。