前言

本文并没有打算介绍 HDFS 的读写流程,虽然这是一块比较重要的内容。如果你感兴趣,可以去搜索相关资料。如果一遍没有看懂,请看第二遍。
本文还是以代码为主,并附以简短的说明,帮助你理解代码的逻辑,以及一些注意事项。你可以将本文的代码封装成一个工具类,这样以后需要调用时候,就可以复用了。


版权说明

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
本文作者:Q-WHai
发表日期: 2016年6月21日
本文链接:https://qwhai.blog.csdn.net/article/details/51728359
来源:CSDN
更多内容:分类 >> 大数据之 Hadoop


HDFS 读写 API

上传本地文件到 HDFS

public static void uploadFileFromLocal(String localPath, String hdfsPath) throws IOException {InputStream in = new BufferedInputStream(new FileInputStream(localPath));FileSystem fileSystem = FileSystem.get(URI.create(hdfsPath), new Configuration());OutputStream out = fileSystem.create(new Path(hdfsPath));IOUtils.copyBytes(in, out, 4096, true);fileSystem.close();
}

此处使用了一个十分方便的方法 IOUtils.copyBytes()。调用这个文件,你可以很方便地将输入流写入到输出流,而且不需要你人为去控制缓冲区,也不需要人为控制循环读取输入源。IOUtils.copyBytes() 中的第 4 个参数表示是否关闭流对象,也就是输入输出流对象。一般来说打成 true 就好了。


从 HDFS 下载文件到本地

通过上面上传文件的例子,我们可以很容易地写出下载文件的代码。如下:

public static void downloadFileToLocal (String hdfsPath, String localPath) throws IOException {FileSystem fileSystem = FileSystem.get(URI.create(hdfsPath), new Configuration());FSDataInputStream in = fileSystem.open(new Path(hdfsPath));OutputStream out = new FileOutputStream(localPath);IOUtils.copyBytes(in, out, 4096, true);fileSystem.close();
}

从 HDFS 下载文件到本地

上面是的下载文件已经很好用了,现在再来看看另外一种下载文件的方法。调用的是 FileUtil.copy() 方法。

public static void downloadFileToLocalNew (String hdfsSourceFileFullName, String localFileFullName) throws IOException {Configuration config = new Configuration();FileSystem fileSystem = FileSystem.get(URI.create(hdfsSourceFileFullName), config);FileUtil.copy(fileSystem, new Path(hdfsSourceFileFullName), new File(localFileFullName), false, config);fileSystem.close();
}

按行读取 HDFS 文件内容

在 HDFS 里面应该是没有直接提供按行读取文件的 API(如果有,后面我们再更新),但是 JDK 中提供相关的 API,那就是 BufferedReader。这里你可以结合刚学 Java 时使用的用户在控制台向程序输入,当时除了 Scanner 就是 BufferedReader 了,很方便。

public static List<String> readFileHDFSByLine (Configuration config, String hdfsFileFullName) throws IOException {List<String> result = new ArrayList<>();FileSystem fileSystem = FileSystem.get(URI.create(hdfsFileFullName), config);FSDataInputStream dataInputStream = fileSystem.open(new Path(hdfsFileFullName));  BufferedReader reader = null;String line;try {reader = new BufferedReader(new InputStreamReader(dataInputStream, "UTF-8"));while ((line = reader.readLine()) != null) {result.add(line);}} finally {if (reader != null) {reader.close();}}return result;
}

向 HDFS 中的文件追加内容

public static void appendLabelToHDFS(String hdfsPath, String content) throws IOException {Configuration config = new Configuration();config.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");config.set("dfs.client.block.write.replace-datanode-on-failure.enable", "true");FileSystem fileSystem = FileSystem.get(URI.create(hdfsPath), config);FSDataOutputStream out = fileSystem.append(new Path(hdfsPath));int readLen = content.getBytes().length;if (-1 != readLen) {out.write(content.getBytes(), 0, readLen);}out.close();fileSystem.close();
}

此处,如果你不想动态设置 Configuration,那么你就需要在配置文件中配置此两项内容。
补充说明
如果你需要对文件进行追加内容操作,那么在 hdfs-site.xml 配置文件中需要设置如下属性。

<property><name>dfs.support.append</name><value>true</value>
</property>

向 HDFS 中的文件追加文件

通过上面追加字符串的操作,你可能会想到这里可以先读取文件内容到字符串,再进行追加字符串操作。这样的确是可以的。不过可以看到上的输出是一个输出流,那么这里就不需要再读取到字符串了。文件是可以直接对到文件流上的嘛。所以向 HDFS 文件中追加文件的操作如下:

public static void appendFileToHDFS(String hdfsPath, String localFilePath) throws IOException {Configuration config = new Configuration();config.set("dfs.client.block.write.replace-datanode-on-failure.policy", "NEVER");config.set("dfs.client.block.write.replace-datanode-on-failure.enable", "true");FileSystem fileSystem = FileSystem.get(URI.create(hdfsPath), config);InputStream in = new BufferedInputStream(new FileInputStream(localFilePath));FSDataOutputStream out = fileSystem.append(new Path(hdfsPath));IOUtils.copyBytes(in, out, 4096, true);fileSystem.close();
}

向 HDFS 文件中写入内容

此处对 HDFS 文件的更改是覆盖式的,也就是会把之前的内容全部删除。

public static void writeLabelToHDFS(String hdfsPath, String content) throws IOException {FileSystem fileSystem = FileSystem.get(URI.create(hdfsPath), new Configuration());FSDataOutputStream out = fileSystem.create(new Path(hdfsPath));int readLen = content.getBytes().length;if (-1 != readLen) {out.write(content.getBytes(), 0, readLen);}out.close();fileSystem.close();
}

删除 HDFS 中文件

此删除操作是删除一个已存在的文件,从代码中的方法命名就可以看出来。不过,如果 HDFS 中不存在此文件,也不会抛出异常。

public static void deleteFileFromHDFS(String hdfsPath) throws IOException {FileSystem fileSystem = FileSystem.get(URI.create(hdfsPath), new Configuration());fileSystem.deleteOnExit(new Path(hdfsPath));fileSystem.close();
}

读取 HDFS 某一目录下的所有文件

这里只是读取目录下的文件,并不包含目录。

public static void readFilesOnlyInDirectoryFromHDFS(String hdfsFolderName) throws IOException {FileSystem fileSystem = FileSystem.get(URI.create(hdfsFolderName), new Configuration());FileStatus fileList[] = fileSystem.listStatus(new Path(hdfsFolderName));for (FileStatus fileStatus : fileList) {if (fileStatus.isDirectory()) {continue;}System.out.println("FileName: " + fileStatus.getPath().getName() + "\t\tSize: " + fileStatus.getLen());}fileSystem.close();
}

读取 HDFS 某一目录下的所有文件

此方法是参考上面的 readFilesOnlyInDirectoryFromHDFS() 方法来的,只是这里也会去读取子目录下的所有文件。所以使用了一个递归,并且为了更好地封装,这里将递归的逻辑与调用分开了,这样做的目的是避免产生过多的 Configuration 对象。

public static void listHDFSFiles (String hdfsFileFullName) throws IOException {Configuration config = new Configuration();listHDFSFiles(config, hdfsFileFullName);
}private static void listHDFSFiles (Configuration config, String hdfsFileFullName) throws IOException {FileSystem fileSystem = FileSystem.get(URI.create(hdfsFileFullName), config);FileStatus[] fileStatus = fileSystem.listStatus(new Path(hdfsFileFullName));for (FileStatus statusItem : fileStatus) {if (statusItem.isDirectory()) {listHDFSFiles(config, statusItem.getPath().toString());}System.out.println("FileName: " + statusItem.getPath() + "\t\tSize: " + statusItem.getLen());}fileSystem.close();
}

获取某一文件在 HDFS 中实际保存的节点

此方法可以展示 HDFS 中的某一个文件在 HDFS 文件系统中被保存的所有 DataNode。

public static void getFileLocal(String hdfsFileFullName) throws IOException {FileSystem fileSystem = FileSystem.get(URI.create(hdfsFileFullName), new Configuration());FileStatus status = fileSystem.getFileStatus(new Path(hdfsFileFullName));BlockLocation[] locations = fileSystem.getFileBlockLocations(status, 0, status.getLen());for (int i = 0; i < locations.length; i++) {String[] hosts = locations[i].getHosts();for (String host : hosts) {System.out.println("block_" + i + "_location:" + host);}}
}

获得 HDFS 中所有的节点信息

如果你不知道 HDFS 文件系统中有哪些文件,单纯的想知道我的 HDFS 文件系统中有哪些 DataNode。那么可以把上面的 hdfsFileFullName 写成 HDFS 的根目录就可以了。比如我的设置如下:

public static void getHDFSNode() throws IOException {FileSystem fileSystem = FileSystem.get(URI.create("hdfs://master:9000/"), new Configuration());DistributedFileSystem distributedFileSystem = (DistributedFileSystem) fileSystem;DatanodeInfo[] dataNodeStats = distributedFileSystem.getDataNodeStats();for (int i = 0; i < dataNodeStats.length; i++) {System.out.println("DataNode_" + i + "_Node:" + dataNodeStats[i].getHostName());}
}

Hadoop 核心编程之 HDFS 的文件操作相关推荐

  1. Hadoop之Hadoop企业优化(HDFS小文件优化)

    Hadoop之Hadoop企业优化 目录 MapReduce 跑的慢的原因 MapReduce优化方法之数据输入 MapReduce优化方法之Map阶段 MapReduce优化方法之Reduce阶段 ...

  2. C++核心编程(四)--文件操作

    5 文件操作 程序运行时产生的数据都属于临时数据,程序一点运行结束,就会被释放 通过文件可以将数据持久化 C++中对文件操作需要包含头文件:fstream 文件类型分为两种: 文本文件:文件以文本的A ...

  3. Hadoop Pipes编程之C++实现WordCount

    2019独角兽企业重金招聘Python工程师标准>>> Hadoop虽然用java实现,但是同样可以支持其他语言的Map和Reduce.由于需要学习C++方面的Hadoop实现,所以 ...

  4. HDFS基础文件操作实验

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.HDFS的基本操作 二.完整代码 一.HDFS的基本操作 基于已经学习到的Hadoop API编程知识,自己动手实现一个 ...

  5. qt的mysql编程_界面编程之QT的数据库操作20180801

    /*******************************************************************************************/ 一.数据库连 ...

  6. JavaWeb核心编程之Tomcat安装和配置

    什么是JavaWeb 在Sun的Java Servlet规范中, 对Java Web应用做了这样的定义: "Java Web应用由一组Servlet, HTML页面, 类, 以及其他可以被绑 ...

  7. WIN32编程之.rc资源文件的使用

    引言: 首先,如果学习标C,黑窗口程序,真的没有必要非要用VC: 那么问题来了:学习WIN32是否需要用VC? 我的答案是:不是非要VC不可,其它IDE也可以用来学WIN32: 甚至我一度以为的学到时 ...

  8. Centos7.x Hadoop 3.x HDFS 写入文件

    操作目的 1.在Linux环境下 编写HDFS写文件程序的java文件 2.编译并打包HDFS的写程序 3.执行HDFS的写程序 环境.工具说明 1.先搭建一个 Hadoop 的基础集群环境 参考:H ...

  9. node中模块系统及核心模块、执行node文件

    node中模块系统: 1.模块系统:核心模块.第三方模块. 自己写的模块. 2.网页中所有的路径都是URL,而不是文件路径. 3.node偏底层开发,开启的服务器完全是一个黑盒子,所有的资源默认都是不 ...

最新文章

  1. exgcd ---- 2020牛客多校第三场:[Fraction Construction Problem:exgcd+思维题]
  2. 粘贴铜箔简易实验电路制作
  3. C++ primer学习方法
  4. python使用缩进来体现代码之间的逻辑关系-Python使用缩进来体现代码之间的逻辑关系。...
  5. nginx 源码学习笔记(十八)—— ngx_add_inherited_sockets 继承的sockets
  6. wxWidgets:wxMenuItem类用法
  7. 计算机科学英文杂志,Journal of Computer Science Technology
  8. 【java】测试dubbo业务
  9. 灌水导论——灌水法初步
  10. jdk1.8下载安装
  11. 代码整洁之道读书笔记----第五章---格式--如何让代码整体布局更清晰
  12. ZZULIOJ:1001: 整数a+b
  13. python扫雷总结与体会_扫雷项目总结
  14. windows错误代码一览表
  15. STM32开发基础知识——OLED开发基础
  16. 平板电脑:apple、中国挑大梁
  17. Nginx 反向代理,提供 http 访问,代理 https 外站内容
  18. Coremail企业邮箱,聚焦让办公更高效
  19. 构建基于openEuler2209的OpenStack云平台(十一)
  20. 早期的Twitte蠕虫

热门文章

  1. C++ Primer 5th笔记(chap 13 拷贝控制)交换操作
  2. 形式化方法、《大象:Thinking in UML》
  3. 在linux kernel中netlink的使用示例
  4. (37)0环与3环通信常规方式,PspTerminateProcess 关闭进程工具
  5. php reverseShell
  6. vbs发送邮件(win10环境下成功)
  7. [保护模式]段间跳转和跨段跳转
  8. 13.跨进程读写内存
  9. 【Prometheus 】 Blackbox_exporter 指标 probe_http_duration_seconds
  10. 1.16 static关键字(静态变量和静态方法)