2. Hadoop:编程操作 HDFS 文件系统

一、Maven 安装配置

我使用 Eclipse 及 Maven 作为编程环境,Eclipse 的安装比较简单,只需要下载解压即可,现在来安装 Maven。

1. 下载解压:

我在这里选择3.3.9版本,解压到 /opt/maven 目录下,此时 Maven 的主目录就是 /opt/maven/apache-maven-3.3.9

2. Maven 下载配置

Maven 默认下载库使用的是国外的镜像,速度比较慢,因此需要选择在配置文件中改为国内的镜像。
打开 /opt/maven/apache-maven-3.3.9/conf 目录下的 settings.xml 文件,在 <mirrors> 标签中添加如下镜像:

        <!-- 阿里云仓库 -->
        <mirror>
            <id>alimaven</id>
            <mirrorOf>central</mirrorOf>
            <name>aliyun maven</name>
            <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
        </mirror>
    
        <!-- 中央仓库1 -->
        <mirror>
            <id>repo1</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo1.maven.org/maven2/</url>
        </mirror>
    
        <!-- 中央仓库2 -->
        <mirror>
            <id>repo2</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo2.maven.org/maven2/</url>
        </mirror>
3. 系统配置

使用 vi 或者 gedit 修改系统的配置文件,我这里使用 gedit:

$ sudo gedit /etc/profile

在该文件最后添加:

# Maven
export MAVEN_HOME=/opt/maven/apache-maven-3.3.9
export PATH=$PATH:$MAVEN_HOME/bin

使用 source 命令使配置文件的修改生效:

$ source /etc/profile

此时可以使用 Maven 命令检查是否安装成功:

$ mvn -v

安装成功结果如下:


Maven 安装成功.png
4. Eclipse 中配置 Maven

Eclipse 中选择 Window->Preferences 中的 Maven
首先在 Installations 中将 Maven 的目录改为刚刚手动安装的 Maven3.3.9:

Installations.png

之后在 User Settings 中修改配置文件的目录为我们自己安装的 Maven 的配置文件,将两处的配置文件目录都修改为 /opt/maven/apache-maven-3.3.9/conf/settings.xml, Loacl Repository 为 Maven 下载的库的目录,这里使用默认目录。

User Settings.png
5. 新建 Maven 项目并添加 Hadoop 依赖

在 Eclipse 中 File->new->Maven Project,点击两次 next,填写包名及项目名:

新建 Maven 项目.png

选择项目中的 pom.xml,在 <dependencies> 中添加如下标签,此时 Maven 会自动去下载标签中的库,也就是 Hadoop2.5.0 对应的 Java 库。

<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-client -->
     <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>2.5.0</version>
        <scope>compile</scope>
     </dependency>

二、Java 操作 HDFS

简介

本地访问 HDFS 最主要的方式是 HDFS 提供的 Java 应用程序接口,其他的访问方式都是建立在这些应用程序接口之上。为了访问 HDFS,HDFS 客户端必须拥有一份 HDFS 的配置文件 hfds-site.xml 来获取 NameNode 的相关信息。

Java程序

1. 读取 HDFS 中的文件

创建类 HDFSCat 用于读取 HDFS 文件系统中的文件内容并打印在控制台。

代码中使用 static 静态代码块执行 URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()),该段代码的作用是让 Java 程序可以识别 Hadoop 的 HDFS url。静态代码块会随着类的加载而执行并只执行一次,它的执行优于主函数。
在主函数中,代码使用 InputStream 读取文件流,并使用 IOUtils 中的 copyBytes 函数将文件内容打印到控制台,false 表示操作结束后不关闭文件流。
完整代码如下:

public class HDFSCat {

    static {
        URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
    }
    
    public static void main(String[] args) {
        InputStream inputStream = null;
        try {
            String url = "hdfs://localhost:9000/datas/test/mapred/example1/test_input";
            inputStream = new URL(url).openStream();
            IOUtils.copyBytes(inputStream, System.out, 4096, false);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeStream(inputStream);
        }
    }

}
2. 使用 FileSystem 读取文件内容

Hadoop 库中的 Configuration 和 FileSystem 这两个类可以用来操作 HDFS 文件系统,Configuration 会从项目的 Resources 文件中读取 HDFS 的配置。因此我们需要将 Hadoop 的配置文件放入到项目中。

在项目上右击 new->source folder,在 src/main 下新建一个存放配置文件的文件夹 resources,如下所示:

新建 resources 文件夹.png

之后将 core-site.xml 以及 hdfs-site.xml 拷贝到该文件夹内,最后的项目结构如下:

Maven 项目结构.png

配置完成之后就可以使用 FileSystem 来读取文件了,只不过这次是通过 FileSystem 的对象来获取文件流,该类的 open() 方法返回 Hadoop 独有的 FSDataInputStream 对象。

public class FSCat {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        InputStream in = null;
        try {
            String uri = "hdfs://localhost:9000/datas/test/mapred/example1/test_input";
            in = fs.open(new Path(uri));
            IOUtils.copyBytes(in, System.out, 4096, false);
        } finally {
            IOUtils.closeStream(in);
        }
    }

}
3. 使用 FileSystem 向 HDFS 中写入文件

这里使用 InputStream 读取 Linux 文件流并输出到 HDFS 文件中,在读取文件的时候使用 BufferedInputStream 而不是 FileInputStream,因为使用 FileInputStream 时会频繁地访问磁盘,读取时效率较低。而是用 BufferedInputStream 时,该类会创建一个内部缓冲数组,在读取流中的字节时,可以根据需要从包含的输入流中填充内部缓冲区,一次填充多个字节。

public class CopyFileToHDFS {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        String source = "/opt/source";
        String destination = "hdfs://localhost:9000/user/destination";
        InputStream inputStream = new BufferedInputStream(
                new FileInputStream(source));
        OutputStream outputStream = fs.create(new Path(destination));
        // 将 Linux 中的 source 文件拷贝到 HDFS 的 destination
        // true 表示操作结束后自动关闭文件流,因此不需要手动关闭
        IOUtils.copyBytes(inputStream, outputStream, 4096, true);
    }

}

运行成功后去 HDFS 下查看 /user 目录,会发现多了 destination 文件。

4. 创建目录
public class CreateFolder {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path path = new Path("hdfs://localhost:9000/datas/new_folder");
        fs.mkdirs(path);
    }

}
5. 删除文件或目录

delete() 方法中如果传入 false 表示删除一个文件,如果传入 true 表示递归删除文件夹及文件。

public class DeleteFile {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        Path deletePath = new Path("/user/destination");
        boolean isDeleted = fs.delete(deletePath, false);
        System.out.println("result: " + isDeleted);
    }

}
6. 列出目录下的文件或目录名
public class ListeFiles {

    public static void main(String[] args) throws IOException {
        Configuration conf = new Configuration();
        FileSystem fs = FileSystem.get(conf);
        String uri = "hdfs://localhost:9000/datas/test/mapred";
        Path path = new Path(uri);
        FileStatus[] status = fs.listStatus(path);
        for (FileStatus fileStatus : status) {
            System.out.println(fileStatus.getPath().toString());
        }
        fs.close();
    }

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • 当数据量增大到超出了单个物理计算机存储容量时,有必要把它分开存储在多个不同的计算机中。那些管理存储在多个网络互连的...
    单行线的旋律阅读 1,852评论 0 7
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • hadoop是什么?HDFS与MapReduceHive:数据仓库,在HDFS之上,后台执行,帮你执行。faceb...
    Babus阅读 2,273评论 0 5
  • 首先,我们在使用前先看看HDFS是什麽?这将有助于我们是以后的运维使用和故障排除思路的获得。 HDFS采用mast...
    W_Bousquet阅读 4,067评论 0 2
  • 这个世界上有无数个你 在眼泪里 在叹息里 在深夜的咖啡里 在肆意妄为的岁月里 鲜花是你 世界是你 拥抱是你 抓不住...
    偌星阅读 395评论 4 6