zoukankan      html  css  js  c++  java
  • HDFS文件操作

    HDFS是一种文件系统,专为MapReduce这类框架下的大规模分布式数据处理而设计。你可以把一个大数据集(比如说100TB)在HDFS中存储为单个文件,而大多数其他的文件系统无力实现这一点。HDFS使你不必考虑这些细节,让你感觉就像在处理单个文件一样。

    因为HDFS并不是一个天生的Unix文件系统,不支持像ls和cp这种标准的Unix文件命令,也不支持如fopen()和fread()这样的标准文件读写操作。另一方面,Hadoop确也提供了一套与linux文件命令类似的命令行工具。
    注意 一个典型的Hadoop工作流会在别的地方生成数据库文件(如日志文件)再将其复制到HDFS中。接着由MapReduce程序处理这个数据,但它们通常不会直接读任何一个HDFS文件。相反,它们依靠MapReduce框架来读取HDFS文件,并将之解析为独立的记录(键值对),这些记录才是MapReduce程序所处理的数据单元。除非需要定制数据的导入与导出,否则你几乎不必编程来读写HDFS文件。

    基本文件命令

    Hadoop的文件命令采取的形式为

    hadoop fs -cmd <args>

    其中cmd是具体的文件命令,而是一组数目可变的命令参数cmd命令通常与UNIX对应的命令名相同。例如,文件列表命令为

    hadoop fs -ls

    让我们来看看在Hadoop中最常用文件管理任务,其中包括
    添加文件和目录
    获取文件
    删除文件

    指定文件盒目录确切位置的URI

    Hadoop的文件命令既可以与HDFS文件系统交互,也可以和本地文件系统交互。URI精确地定位到一个特定文件或目录的位置。完整的URI格式为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的cat命令来显示该文件的内容:
    hadoop fs -cat hdfs://localhost:9000/usr/chuck/example.txt
    正如我们马上就会看到的,大多数设置不需要指定URI中的scheme://authority部分。对于本地文件系统,你可能会更喜欢用标准的Unix命令,而不是hadoop文件命令。当在本地文件系统和HDFS之间复制文件时,hadoop中的命令(如put和get)会分别把本地文件系统作为源和目的,而不需要制定scheme为file。对于其他命令,如果未设置URI中scheme://authority,就会采用Hadoop的默认配置。例如,假如conf/core-site.xml文件已经更改为伪分布式配置,则文件中fs.default.name属性应为

    <property>
        <name>fs.default.name</name>
        <value>hdfs://localhost:9000</value>
    </property>

    在此配置下,URIhdfs://localhost:9000/user/chuck/example.txt缩短为/user/chuck/example.txt。显示文件内容的hadoo cat命令可以写为hadoop fs -cat example.txt

    添加文件和目录

    在运行hadoop程序处理存储在HDFS上的数据之前,你需要首先把数据放在HDFS上。让我们假设你已经完成了格式化,并启动了一个HDFS文件系统(出于学习目的,我们建议使用伪分布式模式的配置。)让我们创建一个目录并放入一个文件。
    HDFS有一个默认的工作目录/usr/USER,USER是你的登录用户名。你需要用你的用户名来替换。

    hadoop fs -mkdir /user/chuck

    hadoop的mkdir命令会自动创建父目录(如果此前不存在的话),类似于UNIX中使用-p选项的mkdir命令,因此上述命令还会创建/user目录,让我们用ls命令对目录进行检查:

    hadoop fs -ls/

    该命令返回根目录下目录/user的信息

    Found 1 items
    drwxr-xr-x -chuck supergroup 0 2009-01-14 10:23 /user

    如果你想看到所有的子目录,则可以使用Hadoop的lsr命令,它类似于Unix中打开-r选项的ls:hadoop fs -lsr /
    你会看到所有文件和子目录:

    drwxr-xr-x -chuck supergroup 0 2009-01-14 10:23 /user
    drwxr-xr-x -chuck supergroup 0 2009-01-14 10:23 /user/chuck

    既然有了一个工作目录,我们可以放一个文件进去。在本地文件系统中创建一个名为example.txt的文本文件,用hadoop的命令put将它从本地文件系统复制到HDFS中去。

    
    hadoop fs -put example.txt.

    注意上面的这个命令最后一个参数是句点(.)。这意味着我们把文件放入了默认的工作目录。该命令等价于:

    
    hadoop fs -put example.txt /user/chuck

    我们重新执行递归列出文件的命令,可以看到新的文件被添加到HDFS中。

    $hadoop fs -lsr /
    drwxr-xr-x -chuck supergroup 0 2009-01-14 10:23 /user
    drwxr-xr-x -chuck supergroup 0 2009-01-14 11:02 /user/chuck
    -rw-r--r-- 1 chuck supergroup 264 2009-01-14 11:02 /user/chuck/example.txt

    实际上,我们并不需要递归地检查所有文件,而仅限于在我们自己工作目录中的文件。我们可以通过最简单的形式来使用Hadoop的ls命令:

    $ hadoop fs -ls
    Found 1 items
    -rw-r--r-- 1 chuck supergroup 264 2009-01-14 11:02 /user/chuck/exampe.txt

    输出结果显示出属性信息,比如权限、所有者、组、文件大小,以及最后修改日期,所有这些都类似于Unix的概念。显示“1”的列给出文件的复制因子。伪分布式配置下它永远为1。对于生产环境中的集群,复制因子通常为3,但也可以是任何正整数。因为复制因子不适用于目录,故届时该列会显示一个破折号(-)。
    当你把数据放到HDFS上之后,你可以运行Hadoop程序来处理它。处理过程将输出一组新的HDFS文件,然后你可以读取或检索这些结果。

    检索文件

    hadoop的get命令与put截然相反。它从HDFS中复制文件到本地文件系统。比方说,我们在本地不再拥有文件example.txt,而想从HDFS中将它取回,我们就可以运行命令:

    hadoop fs -get example.txt.
    将它复制到我们在本地的当前工作目录中。
    另一种访问数据的方式是显示。由hadoop的cat命令来支持:
    hadoop fs -cat example.txt
    我们可以在Hadoop的文件命令中使用Unix的管道,将其结果发送给其他的Unix命令做进一步处理。例如,如果该文件非常大(正如典型的Hadoop文件那样),并且你希望快速地检查其内容,就可以把hadoop中cat命令的输出用管道传递给Unix命令head:
    hadoop fs -cat example.txt|head
    hadoop内在支持tail命令来查看最后一千字节:
    hadoop fs -tail example.txt
    文件在HDFS上的任务完成之后,可以考虑删除它们以释放空间。

    删除文件

    hadoop删除文件的命令为rm,现在你也许不会感到太惊讶了:
    hadoop fs -rm example.txt
    rm命令还可以用于删除空目录。

    编程读写HDFS

    为了体验HDFS的Java API,我们将开发一个PutMerge程序,用于合并文件后放入HDFS。命令行工具并不支持这个操作,我们将使用API来实现。
    需要分析来自许多Web服务器的Apache日志文件时,就有了建立这个历程的动机。虽然我们可以把每个日志文件都复制到HDFS中,但通常而言,Hadoop处理单个大文件会比处理许多个小文件更有效率(这里“小”是相对的,因为它仍会达到几十或几百GB)。此外,从分析目的来看,我们把日志数据视为一个大文件。日志数据被分散在多个文件是由于Web服务器采用分布式架构所带来的副作用。一种解决办法是先将所有的文件合并,然后再复制到HDFS。可是,文件合并需要占用本地计算机的大量磁盘空间。如果我们能够在向HDFS复制的过程中合并它们,事情就会简单很多。
    因此,我们需要一个PutMerge类型的操作。hadoo命令行中有一个getmerge命令,用于一组HDFS文件在复制到本地以前进行合并。但我们想要的截然相反,故无法再Hadoop的文件管理工具中获得。我们用HDFS API来自己编程实现它。
    在Hadoop中用作文件操作的主流位于org.apache.hadoop.fs软件包中。Hadoop的基本文件操作包括常见的open、read、write和close。实际上,hadoop的文件API是通用的,可以用于HDFS以外的其他文件系统。对于我们的PutMerge程序,它读取本地文件系统和写入HDFS都会使用Hadoop的文件api。

    不多说,直接上代码:

    import java.io.IOException;
    
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.FSDataInputStream;
    import org.apache.hadoop.fs.FSDataOutputStream;
    import org.apache.hadoop.fs.FileStatus;
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.fs.Path;
    import org.eclipse.jdt.internal.compiler.ConfigurableOption;
    
    public class PutMerge
    {
        public static void main(String[] args) throws IOException
        {
            Configuration conf = new Configuration();
            FileSystem hdfs = FileSystem.get(conf);
            FileSystem local = FileSystem.getLocal(conf);
            Path inputDir = new Path(args[0]);//1.设定输入目录与输出文件
            Path hdfsFile = new Path(args[1]);
            try
            {
                FileStatus[] inputFiles = local.listStatus(inputDir);//2.得到本地文件列表
                FSDataOutputStream out = hdfs.create(hdfsFile);//3.生成HDFS文件流
                for (int i = 0; i < inputFiles.length; i++)
                {
                    System.out.println(inputFiles[i].getPath().getName());
                    FSDataInputStream in = local.open(inputFiles[i].getPath());//4.打开本地输入流
                    byte buffer[] = new byte[256];
                    int bytesRead = 0;
                    while ((bytesRead = in.read(buffer)) > 0)
                    {
                        out.write(buffer, 0, bytesRead);
                    }
                    in.close();
                }
                out.close();
    
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }

    我们已经讨论了如何处理HDFS中的文件,你现在知道一些方法来读写HDFS中的数据,但是仅仅有数据还不够,还要对它进行处理分析以及其他的操作。在后续学习过程中,我们将介绍Hadoop的另一个主要组件——MapReduce框架,看看如何基于它来编程。

  • 相关阅读:
    计算机系统概述
    Qt学习--初学注意事项
    Qt实现一个简单的TextEditor
    Qt 用户登录界面
    C++ 模板
    多态与虚函数
    继承与派生
    C++ 运算符重载
    web安全-点击劫持
    web安全问题-cookie
  • 原文地址:https://www.cnblogs.com/ainima/p/6331862.html
Copyright © 2011-2022 走看看