HDFS文件操做java
你能够把一个大数据集(100TB)在HDFS中存储为单个文件,而大多数其余的文件系统无力实现这一点。虽然该文件存在多个副本分布在多台机器上来支持并行处理,你也没必要考虑这些细节。apache
HDFS (Hadoop Distribution File System)文件系统究竟是一个怎样的文件系统?编程
并非一个Unix文件系统,不支持像ls和cp这种标准的Unix文件命令,也不支持如fopen()和fread()这样的标准文件读写操做。可是Hadoop提供了一套与Linux文件命令相似的命令行工具。数组
一个典型的Hadoop工做流是指?服务器
1、在别的地方生成数据文件(如日志文件)再将其复制到HDFS中。架构
2、由MapReduce程序处理这个数据,读取HDFS文件并将之解析为独立的记录(键/值对)分布式
3、除非要定制数据的导入与导出,不然你几乎没必要编程来读写HDFS文件。工具
Hadoop文件命令采起的形式是?oop
hadoop fs -cmd <args>学习
cmd是具体的文件命令,而<args>是一组数目可变的参数。cmd的命名一般与UNIX对应的命令名相同。如,文件列表的命令为:hadoop fs -ls
Hadoop最经常使用的文件管理任务包括?
1、添加文件和目录
2、获取文件
3、删除文件
Hadoop文件命令能够和本地文件系统交互吗?
Hadoop的文件命令既能够与HDFS文件系统交互,也能够和本地文件系统交互。
URI定位是指?完整的URL格式是?
URL精确地定位一个特定文件或目录的位置。
完整的URL格式为scheme://authority/path. Scheme相似于一个协议它能够是hdfs或file、来分别指定HDFS文件系统或本地文件系统。
对于HDFS,authority是NameNode的主机名,而path是文件或者目录的路径。
对于在本地机器的9000端口上,以标准伪分布式模型运行的HDFS,访问用户目录user/chuck中文件example.txt的URI是什么?
hdfs://localhost:9000/user/chuck/example.txt
hadoop fs -cat hdfs://localhost:9000/user/chuck/example.txt
可是一般咱们在使用Hadoop文件命令时没有指定URI中的scheme://authority部分
是怎么回事?
是的,大多数设置不须要指定URI中的scheme://authority部分
例如,当在本地文件系统和HDFS之间复制文件时
1、put命令将本地文件复制到HDFS中,源是本地文件,目的是HDFS文件
2、get命令将HDFS中文件复制到本地,源是HDFS文件,目的是本地文件。
若是未设置URI中的scheme://authority部分,就会采用Hadoop的默认配置fs.default.name属性的配置。
例如:conf/core-site.xml文件配置是:
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
在此配置下,URI hdfs://localhost:9000/user/chuck/example.txt缩短为/user/chuck/example.txt
注:有些更早的文档以hadoop dfs -cmd <args>的形式表示文件工具。dfs和fs是等价的,但如今都是用fs
HDFS默认当前工做目录是?
HDFS默认当前工做目录为/user/$USER,其中$USER是你的登陆用户名。
例:若是你做为chuck登陆,则URI hdfs://localhost:9000/user/chuck/example.txt就缩短为example.txt。显示文件内容的Hadoop cat命令可写为:
hadoop fs -cat example.txt
如何在HDFS上添加文件和目录?
首先必须确保几点:
1、必须先进行格式化
2、出于学习目的,建议使用伪分布式
3、默认工做目录是/user/$USER,但这个目录不会自动建立,须要手动建立先
手动建立默认工做目录
hadoop fs -mkdir /user/chuck
Hadoop的mkdir命令会自动建立父目录,相似于UNIX中使用-p选项的mkdir命令,所以上述命令还会建立/user目录。
hadoop fs -ls / 该命令列出根目录下的全部文件和目录
hadoop fs -lsr / 该命令列出根目录下全部文件和子目录
hadoop fs -put example.txt . 将本地文件example.txt放入HDFS中。
后面的(.),意味着把文件放入默认的工做目录,等价于
hadoop fs -put example.txt /user/chuck
hadoop fs -ls 列出工做目录下的全部文件和目录
使用hadoop fs -ls命令列出内容和复制因子
一般状况下会列出以下面这样的view
Found 1 items
-rw-r--r-- 1 chuck supergroup 264 2009-01-14 11:02 /user/chuck/example.txt
显示属性信息,其余的不解释和UNIX的概念相似。主要说一下"1"列出文件的复制因子。伪分布式下它永远为1,对于生产环境中的集群,复制因子一般为3,也能够是任何正整数,复制因子不适用于目录,因此该列会显示一个(-)
如何检索文件?
Hadoop的get命令与put命令相反,从HDFS中复制文件到本地文件系统。
好比hadoop fs -get example.txt 将它复制带本地的当前工做目录中。
hadoop fs -cat example.txt 也可使用cat命令显示数据。
也可使用管道命令 hadoop fs -cat example.txt | head
可使用tail命令来查看最后的一千字节:
hadoop fs -tail example.txt
如何删除文件?
删除文件和空目录使用rm命令
hadoop fs -rm example.txt
如何查阅帮助?
hadoop fs (无参数) 来获取所用版本Hadoop的一个完整命令列表。
hadoop fs -help ls 显示每一个命令的用法及简短描述。
HDFS的Java API?
虽然,命令行工具足以知足大多数与HDFS文件系统交互的需求,可是有些需求只能用Java API去访问,好比开发一个PutMerge程序,用于合并文件后放入HDFS中,命令行工具并不支持这个操做。
合并文件后放入HDFS中,何时会这样作呢?
考虑这样一个场景,须要分析来自许多Web服务器的Apache日志文件时,就有了创建这个例程的动机,虽然咱们能够把每一个日志文件都复制到HDFS中,但一般而言,Hadoop处理单个大文件会比处理许多个小文件更有效率。
为何会日志数据会分散在多个文件?
这是因为Web服务器采用分布式架构所形成的。
一种解决办法是?为何不直接合并?
一种解决办法是先将全部的文件合并,而后再复制到HDFS。但是,文件合并须要占用本地计算机的大量磁盘空间。若是咱们可以在向HDFS复制的过程当中合并它们就行了。
Hadoop命令行工具getmerge命令。
getmerge命令,用于把一组HDFS文件在复制到本地计算机以前进行合并,但咱们想要的截然相反。咱们是要putmerge命令。
Hadoop文件操做API是?
Hadoop中用做文件操做的主类位于org.apache.hadoop.fs软件包中,Hadoop的基本文件操做包括open、read、write和close,Hadoop的文件API也能够用于HDFS之外的其余文件系统。
Hadoop文件API的起点是FileSystem类,这是一个与文件系统交互的抽象类,存在不一样的具体实现子类用于处理HDFS和本地文件系统。你能够经过调用factory方法FileSystem.get(Configuration conf)来获得所需的FileSystem实例。Configuration类是用于保留键/值配置参数的特殊类。它的默认实例化方法是以HDFS系统的资源配置为基础的。
如何获得一个FileSystem对象?
Configuration conf = new Configuration();
FileSystem hdfs = FileSystem.get(conf);
要获得一个专用于本地文件系统的FileSystem对象,可使用factory方法的FileSystem.getLocal(Configuration conf);
FileSystem local = FileSystem.getLocal(conf);
其余说明:
Hadoop文件API使用Path对象来编制文件和目录名,使用FileStatus对象来存储文件和目录的元数据。PutMerge程序将合并一个本地目录中的全部文件。咱们使用FileSystem的listStatus()方法来获得一个目录中的文件列表:
Path inputDir = new Path(args[0]);
FileStatus[] inputFiles = local.listStatus(inputDir);
数组inputFiles的长度等于指定目录中的文件个数。在inputFiles中每个FileStatus对象均有元数据信息,如文件长度、权限、修改时间等。PutMerge程序所关心的是每一个文件的Path,即inputFiles[i].getPath()。咱们能够经过FSDataInputStream对象访问这个Path来读取文件。
FSDataInputStream in = local.open(inputFiles[i].getPath());
byte buffer[] = new byte[256];
int bytesRead = 0;
while ( (bytesRead = in.read(buffer)) > 0) {
...
}
in.close();
FSDataInputStream是Java标准类java.io.DataInputStream的一个子类,增长了对随机访问的支持。相似地有一个FSDataOutputStream对象用于将数据写入HDFS文件:
Path hdfsFile = new Path(args[1]);
FSDataOutputStream out = hdfs.create(hdfsFile);
out.write(buffer, 0, bytesRead);
out.close();