ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

HDFS编程实践

HDFS编程实践

系列文章目录


文章目录

  • 系列文章目录
  • 前言
  • Shell命令与HDFS进行交互
  • 目录操作
  • 文件操作
  • 在云服务器中安装Eclipse
  • 安装图形界面。
  • 图形界面设置为中文
  • 图形界面的取消
  • eclipse调试java程序
    • 1. 新建 Java 项目
    • 2. 导入 Hadoop 相关 jar 包
    • 3. 编写读取 HDFS 文件的 Java 示例
    • 4. 运行结果说明
    • 5. 常见报错与排查方法
      • 5.1 缺少依赖:ClassNotFoundException / NoClassDefFoundError
      • 5.2 连接被拒绝:Connection refused
      • 5.3 权限不足:Permission denied
      • 5.4 文件不存在:FileNotFoundException
      • 5.5 Windows 下运行报错:Could not locate executable null\bin\winutils.exe
  • 总结

前言

上篇文章介绍了如何在云服务器上部署hadoop,本篇将介绍如何使用HDFS进行操作。


Shell命令与HDFS进行交互

首先要先启动hadoop.

cd/usr/local/hadoop./sbin/start-dfs.sh


j进行命令的查看

./bin/hadoop fs

./bin/hadoop fs-help put

目录操作

在Hadoop系统安装好以后,第一次使用HDFS时,需要首先在HDFS中创建用户目录。本教程全部采用hadoop用户登录Linux系统,因此,需要在HDFS中为hadoop用户创建一个用户目录,命令如下。

cd/usr/local/hadoop./bin/hdfs dfs-mkdir-p/user/hadoop


可用如下两个命令进行显示HDFS中与当前用户hadoop对应的用户目录下的内容。

./bin/hdfs dfs-ls.

./bin/hdfs dfs-ls/user/hadoop

列出HDFS上的所有目录。

./bin/hdfs dfs-ls


可以使用如下命令创建一个input目录(如果存在就不用再建了,输入命令也会给出提示信息)。

./bin/hdfs dfs-mkdir input

要在HDFS的根目录下创建一个名称为input的目录,则需要使用如下命令。

./bin/hdfs dfs-mkdir/input


可以使用rm命令删除一个目录,比如,可以使用如下命令删除刚才在HDFS中创建的“/input”目录(不是“/user/hadoop/input”目录)。

./bin/hdfs dfs-rm-r/input

文件操作

在实际应用中,经常需要从本地文件系统向HDFS中上传文件,或者把HDFS中的文件下载到本地文件系统中。
首先,使用vim编辑器,在本地Linux文件系统的“/home/hadoop/”目录下创建一个文件myLocalFile.txt,里面可以随意输入一些单词,比如,输入如下三行。

cd/home/hadoop

vim myLocalFile.txt

输入以下内容

Hadoop Spark XMU DBLAB


然后,可以使用如下命令把本地文件系统的“/home/hadoop/myLocalFile.txt”上传到HDFS中的当前用户目录的input目录下,也就是上传到HDFS的“/user/hadoop/input/”目录下。
首先要切换至hadoop下

cd/usr/local/hadoop
./bin/hdfs dfs-put/home/hadoop/myLocalFile.txt input


可用下面命令进行查看。

./bin/hdfs dfs-lsinput

下面使用如下命令查看HDFS中的myLocalFile.txt这个文件的内容。

./bin/hdfs dfs-catinput/myLocalFile.txt


切换至/home/hadoop下建立download文件夹。

cd ~ mkdir download

下面把HDFS中的myLocalFile.txt文件下载到本地文件系统中的“/home/hadoop/download/”这个目录下,命令如下。

cd/usr/local/hadoop./bin/hdfs dfs-get input/myLocalFile.txt/home/hadoop/download

可以使用如下命令,到本地文件系统查看下载下来的文件myLocalFile.txt。

cd ~ cd download llcatmyLocalFile.txt


最后,了解一下如何把文件从HDFS中的一个目录拷贝到HDFS中的另外一个目录。比如,如果要把HDFS的“/user/hadoop/input/myLocalFile.txt”文件,拷贝到HDFS的另外一个目录“/input”中(注意,这个input目录位于HDFS根目录下),可以使用如下命令。

cd/usr/local/hadoop./bin/hdfs dfs-cpinput/myLocalFile.txt/input

可进行查看文件内容。

./bin/hdfs dfs-ls
./bin/hdfs dfs-cat/input

在云服务器中安装Eclipse

下载Eclipse 2021-03版本,可以使用以下命令。

wget https://mirrors.tuna.tsinghua.edu.cn/eclipse/technology/epp/downloads/release/2023-09/R/eclipseeclipse-cpp-2023-09-R-linux-gtk-x86_64.tar.gz

sudo tar-zxvf./eclipse-cpp-2023-09-R-linux-gtk-x86_64.tar.gz-C/usr/local

找到/usr/local,并查看下面的内容。

安装图形界面。

以下的代码命令会出现提示,输入y即可。
如果所在的用户是root用户:

apt-get update apt-get install-y ubuntu-desktop systemctlset-defaultgraphical.target reboot

如果所在的用户是普通用户:

sudo apt-get update sudo apt-get install-y ubuntu-desktop sudo systemctlset-defaultgraphical.target sudo reboot

输入完rebboot后重启云服务器,会进入下面的界面。

选择hadoop用户,输入密码进入。

图形界面设置为中文

如果是第一次安装会进入英文的界面,在英文界面找到终端。
虚拟机桌面右键,找到该位置打开终端。

在hadoop用户下安装中文语言包

sudo apt-get install language-pack-zh-hans


还需将系统的默认语言设置为中文

sudoupdate-localeLANG=zh_CN.UTF-8


重新启动云服务器

reboot

再重启后点击下图红框位置

下滑找到区域与语言,如果上述设置无效,在英文界面找到该选项。


点击语言


进行选择

如果在上述选项中未看见中文选项,则点击已安装的语言。

在这窗口中可以点击添加或删除语言,在里面找到chinese安装简体语言,之后点再选择中文,点击应用到整个系统即可,或者再次重启云服务器即可。


完成了云服务器的中文设定。

图形界面的取消

在桌面上右键,之后打开终端

sudo systemctlset-defaultmulti-user.target sudo reboot

进行图形话的取消。

彻底删除:

sudo apt-get purge ubuntu-desktop unity gnome-shell lightdm sudo apt-get autoremove sudo reboot

eclipse调试java程序

前面已经完成了 Hadoop 的安装、HDFS 的 Shell 操作以及 Eclipse 的安装与图形界面配置。本节将在 Eclipse 中编写一个 Java 程序,直接通过 HDFS Java API 读取 HDFS 上的文件并输出内容,同时说明运行结果与常见报错的排查方法。

1. 新建 Java 项目

打开 Eclipse,依次点击File -> New -> Java Project,在弹出的窗口中填写项目名称,例如HDFSDemo,JRE 选择本机已安装的 JDK(建议 JDK 8 及以上),点击Finish完成创建。

如果 Eclipse 提示需要配置 JRE,可在Window -> Preferences -> Java -> Installed JREs中添加本机的 JDK 路径(例如/usr/lib/jvm/java-8-openjdk-amd64)。

项目创建完成后,在src目录上右键,选择New -> Class,填写包名com.hadoop.demo、类名HDFSReadDemo,勾选public static void main(String[] args),点击Finish。

2. 导入 Hadoop 相关 jar 包

Hadoop 的 Java 依赖都在 Hadoop 安装目录的share/hadoop下。最省事的做法是把相关目录下的 jar 包全部导入项目:

在项目名HDFSDemo上右键,选择Build Path -> Configure Build Path,切换到Libraries标签页,点击Add External JARs,然后依次进入 Hadoop 安装目录(本教程为/usr/local/hadoop),把以下目录中的 jar 包全部选中导入:

  • /usr/local/hadoop/share/hadoop/common及其lib子目录
  • /usr/local/hadoop/share/hadoop/hdfs及其lib子目录
  • /usr/local/hadoop/share/hadoop/yarn及其lib子目录
  • /usr/local/hadoop/share/hadoop/mapreduce及其lib子目录

也可以在终端中用一条命令把所需 jar 包复制到一个统一目录,再整体导入:

mkdir-p/home/hadoop/hadoop-libs find/usr/local/hadoop/share/hadoop-name"*.jar"-execcp{}/home/hadoop/hadoop-libs/ \;

然后在Add External JARs中一次性选中/home/hadoop/hadoop-libs下的所有 jar 包即可。

3. 编写读取 HDFS 文件的 Java 示例

在HDFSReadDemo.java中写入如下代码,实现读取 HDFS 上/user/hadoop/input/myLocalFile.txt文件并打印内容:

packagecom.hadoop.demo;importjava.io.BufferedReader;importjava.io.InputStreamReader;importjava.net.URI;importorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.fs.FSDataInputStream;importorg.apache.hadoop.fs.FileSystem;importorg.apache.hadoop.fs.Path;publicclassHDFSReadDemo{publicstaticvoidmain(String[]args){StringhdfsUri="hdfs://localhost:9000";StringfilePath="/user/hadoop/input/myLocalFile.txt";Configurationconf=newConfiguration();conf.set("fs.defaultFS",hdfsUri);FileSystemfs=null;FSDataInputStreamin=null;BufferedReaderreader=null;try{// 获取 HDFS 文件系统实例fs=FileSystem.get(newURI(hdfsUri),conf,"hadoop");Pathpath=newPath(filePath);if(!fs.exists(path)){System.out.println("文件不存在:"+filePath);return;}in=fs.open(path);reader=newBufferedReader(newInputStreamReader(in,"UTF-8"));System.out.println("===== 开始读取 "+filePath+" =====");Stringline;while((line=reader.readLine())!=null){System.out.println(line);}System.out.println("===== 读取结束 =====");}catch(Exceptione){e.printStackTrace();}finally{try{if(reader!=null)reader.close();if(in!=null)in.close();if(fs!=null)fs.close();}catch(Exceptione){e.printStackTrace();}}}}

说明几点:

  • hdfs://localhost:9000中的端口要与core-site.xml中fs.defaultFS的配置保持一致,若配置的是hdfs://localhost:8020,这里也要改成8020。
  • FileSystem.get(new URI(hdfsUri), conf, "hadoop")中的"hadoop"是运行 HDFS 的用户名,避免出现权限不足的问题。
  • 读取的文件路径要与前面通过 Shell 上传的文件路径一致,即/user/hadoop/input/myLocalFile.txt。

4. 运行结果说明

在 Eclipse 中右键HDFSReadDemo.java,选择Run As -> Java Application,控制台输出如下:

===== 开始读取/user/hadoop/input/myLocalFile.txt ===== Hadoop Spark XMU DBLAB ===== 读取结束 =====

输出的内容与前面通过./bin/hdfs dfs -cat input/myLocalFile.txt查看到的内容完全一致,说明 Java 程序已经成功通过 HDFS API 读取到了 HDFS 上的文件。

5. 常见报错与排查方法

5.1 缺少依赖:ClassNotFoundException / NoClassDefFoundError

报错信息类似:

java.lang.ClassNotFoundException: org.apache.hadoop.conf.Configuration

或

java.lang.NoClassDefFoundError: org/apache/hadoop/fs/FileSystem

原因:Hadoop 的 jar 包没有正确加入项目的 Build Path。

排查方法:

  • 检查Build Path -> Configure Build Path -> Libraries中是否已经包含hadoop-common、hadoop-hdfs等 jar 包。
  • 确认导入的是share/hadoop下各子目录及其lib目录中的 jar 包,只导入主 jar 而漏掉lib下的依赖同样会报错。
  • 修改后重新Clean项目(Project -> Clean)再运行。

5.2 连接被拒绝:Connection refused

报错信息类似:

java.net.ConnectException: CallFromxxx to localhost:9000 failed on connection exception: java.net.ConnectException: Connection refused

原因:HDFS 没有启动,或者程序中的地址、端口与实际配置不一致。

排查方法:

  • 在终端执行jps,确认NameNode、DataNode进程存在;若没有,执行./sbin/start-dfs.sh启动 Hadoop。
  • 查看core-site.xml中fs.defaultFS的值,确认代码中的hdfsUri与之完全一致(端口 9000 与 8020 是最常见的差异)。
  • 如果 Eclipse 运行在云服务器上,确认 HDFS 相关端口(如 9000、9870)在安全组中已放行;如果 Eclipse 运行在本地而 HDFS 在云服务器上,需要把localhost换成云服务器的公网 IP,并确保端口可访问。

5.3 权限不足:Permission denied

报错信息类似:

org.apache.hadoop.security.AccessControlException: Permission denied: user=xxx,access=READ,inode="/user/hadoop/input/myLocalFile.txt"

原因:运行程序的用户与 HDFS 文件所属用户不一致。

排查方法:

  • 在FileSystem.get中显式指定用户名,如FileSystem.get(new URI(hdfsUri), conf, "hadoop")。
  • 或者在运行配置的VM arguments中加入-DHADOOP_USER_NAME=hadoop。
  • 也可以对目标文件执行./bin/hdfs dfs -chmod -R 777 /user/hadoop/input放开权限(仅建议在测试环境使用)。

5.4 文件不存在:FileNotFoundException

报错信息类似:

java.io.FileNotFoundException: File/user/hadoop/input/myLocalFile.txt does not exist

原因:读取的路径写错,或文件尚未上传到 HDFS。

排查方法:

  • 执行./bin/hdfs dfs -ls /user/hadoop/input确认文件确实存在。
  • 注意 HDFS 路径是绝对路径,不要写成相对路径或本地路径。
  • 若文件不存在,先按前面「文件操作」一节的命令重新上传。

5.5 Windows 下运行报错:Could not locate executable null\bin\winutils.exe

原因:Hadoop 原生库在 Windows 下需要winutils.exe支持。

排查方法:

  • 下载与 Hadoop 版本对应的winutils.exe和hadoop.dll,放到本地 Hadoop 目录的bin下。
  • 配置环境变量HADOOP_HOME指向该目录,并把%HADOOP_HOME%\bin加入Path。
  • 更推荐直接在 Linux 云服务器的图形界面中使用 Eclipse,可避免此类平台差异问题。

总结

本文围绕 HDFS 的实践操作展开,形成了一条从命令行到编程接口的完整链路。首先通过 Shell 命令与 HDFS 交互,熟悉hadoop fs的用法与帮助信息;接着在目录操作中创建用户目录、查看与删除目录,掌握 HDFS 的路径体系;随后在文件操作中完成本地文件的上传、查看、下载与 HDFS 内部拷贝,理解本地文件系统与 HDFS 之间的数据流转。在此基础上,安装 Eclipse 并配置图形界面与中文环境,为编写 Java 程序提供可视化开发环境;最后通过 HDFS Java API 读取 HDFS 文件并输出内容,把前面的 Shell 操作对应到代码实现上。学习时应重点把握「先 Shell 验证、再代码实现」的思路,并注意端口配置、依赖导入与权限设置这几个关键衔接点。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进