# 【三】读写HDFS文件 ### 3.1 实验目的 1. 会在Linux环境下编写读写HDFS文件的代码; 2. 会使用jar命令打包代码; 3. 会在client服务器上运行HDFS读写程序; 4. 会在Windows上安装Eclipse Hadoop插件; 5. 会在Eclipse环境编写读写HDFS文件的代码; 6. 会使用Eclipse打包代码; 7. 会使用Xftp工具将实验电脑上的文件上传至client服务器。 ### 3.2 实验要求 实验结束时,每位学生均已搭建HDFS开发环境;编写了HDFS写、读代码;在client机上执行了该写、读程序。通过实验了解HDFS读写文件的调用流程,理解HDFS读写文件的原理。 ### 3.3 实验原理 #### 3.3.1 Java Classpath Classpath设置的目的,在于告诉Java执行环境,在哪些目录下可以找到您所要执行的Java程序所需要的类或者包。 Java执行环境本身就是一个平台,执行于这个平台上的程序是已编译完成的Java程序(后面会介绍到Java程序编译完成之后,会以.class文件存在)。如果将Java执行环境比喻为操作系统,如果设置Path变量是为了让操作系统找到指定的工具程序(以Windows来说就是找到.exe文件),则设置Classpath的目的就是让Java执行环境找到指定的Java程序(也就是.class文件)。 有几个方法可以设置Classpath,较简单的方法是在系统变量中新增Classpath环境变量。以Windows 7操作系统为例,右键点击计算机→属性→高级系统设置→环境变量,在弹出菜单的“系统变量”下单击“新建”按钮,在“变量名”文本框中输入Classpath,在“变量值”文本框中输入Java类文件的位置。例如可以输入“.; D:\\Java\\jdk1.7.0\_79\\lib\\tools.jar; D:\\Java\\jdk1.7.0\_79\\lib\\rt.jar”,每一路径中间必须以英文;作为分隔。如图3-1所示: ![](https://box.kancloud.cn/125bfc23ade7f642c37ea1e9c61ca28b_420x442.png) 事实上JDK 7.0默认就会到当前工作目录(上面的.设置),以及JDK的lib目录(这里假设是D:\\Java\\jdk1.7.0\_796\\lib)中寻找Java程序。所以如果Java程序是在这两个目录中,则不必设置Classpath变量也可以找得到,将来如果Java程序不是放置在这两个目录时,则可以按上述设置Classpath。 如果所使用的JDK工具程序具有Classpath命令选项,则可以在执行工具程序时一并指定Classpath。例如: javac -classpath classpath1;classpath2...其中classpath1、classpath 2是实际要指定的路径。也可以在命令符模式下执行以下的命令,直接设置环境变量,包括Classpath变量(这个设置在下次重新打开命令符模式时就不再有效): set CLASSPATH=%CLASSPATH%;classpath1;classpath2...总而言之,设置Classpath的目的,在于告诉Java执行环境,在哪些目录下可以找到您所要执行的Java程序(.class文件)。 #### 3.3.2 Eclipse Hadoop插件 Eclipse 是一个跨平台的自由集成开发环境(IDE)。通过安装不同的插件,Eclipse可以支持不同的计算机语言,比如C++和Python等开发工具,亦可以通过hadoop插件来扩展开发Hadoop相关程序。 实际工作中,Eclipse Hadoop插件需要根据hadoop集群的版本号进行下载并编译,过程较为繁琐。为了节约时间,将更多的精力用于实现读写HDFS文件,在大数据实验一体机的相关下载页面中已经提供了2.7.1版本的hadoop插件和相关的hadoop包下载,实验人员可以直接下载这些插件,快速在Eclipse中进行安装,开发自己的hadoop程序。 ### 3.4 实验步骤 #### 3.4.1 配置client服务器classpath 使用ssh工具登录client服务器,执行命令vi /etc/profile,编辑该文件,将末尾的如下几行: ~~~ JAVA_HOME=/usr/local/jdk1.7.0_79/ export JRE_HOME=/usr/local/jdk1.7.0_79//jre export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib export HADOOP_HOME=/usr/cstor/hadoop export PATH=$PATH:$HADOOP_HOME/bin export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib" ~~~ 用下列行进行替换: ~~~ JAVA_HOME=/usr/local/jdk1.7.0_79/ export HADOOP_HOME=/usr/cstor/hadoop export JRE_HOME=/usr/local/jdk1.7.0_79//jre export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$HADOOP_HOME/share/hadoop/common/*:$HADOOP_HOME/share/hadoop/common/lib/* export PATH=$PATH:$HADOOP_HOME/bin export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native export HADOOP_OPTS="-Djava.library.path=$HADOOP_HOME/lib:$HADOOP_HOME/lib/native" ~~~ 执行命令source /etc/profile,使刚才的环境变量修改生效: ~~~ [root@client ~]# source /etc/profile ~~~ #### 3.4.2 在client服务器编写HDFS写程序 在client服务器上执行命令vi WriteFile.java,编写HDFS写文件程序: ~~~ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; public class WriteFile { public static void main(String[] args)throws Exception{ Configuration conf=new Configuration(); FileSystem hdfs = FileSystem.get(conf); Path dfs = new Path("/weather.txt"); FSDataOutputStream outputStream = hdfs.create(dfs); outputStream.writeUTF("nj 20161009 23\n"); outputStream.close(); } } ~~~ #### 3.4.3 编译并打包HDFS写程序 使用javac编译刚刚编写的代码,并使用jar命令打包为hdpAction.jar: ~~~ [root@client ~]# javac WriteFile.java [root@client ~]# jar -cvf hdpAction.jar WriteFile.class added manifest adding: WriteFile.class(in = 833) (out= 489)(deflated 41%) ~~~ #### 3.4.4 执行HDFS写程序 在client服务器上使用hadoop jar命令执行hdpAction.jar: ~~~ [root@client ~]# hadoop jar ~/hdpAction.jar WriteFile ~~~ 查看是否已生成weather.txt文件,若已生成,则查看文件内容是否正确: ~~~ [root@client ~]# hadoop fs -ls / Found 2 items -rw-r--r-- 3 root supergroup 29 2016-12-05 12:28 /machines -rw-r--r-- 3 root supergroup 17 2016-12-05 14:54 /weather.txt [root@client ~]# hadoop fs -cat /weather.txt nj 20161009 23 ~~~ #### 3.4.5 在client服务器编写HDFS读程序 在client服务器上执行命令vi ReadFile.java,编写HDFS读文件程序: ~~~ import java.io.IOException; import org.apache.Hadoop.conf.Configuration; import org.apache.Hadoop.fs.FSDataInputStream; import org.apache.Hadoop.fs.FileSystem; import org.apache.Hadoop.fs.Path; public class ReadFile { public static void main(String[] args) throws IOException { Configuration conf = new Configuration(); Path inFile = new Path("/weather.txt"); FileSystem hdfs = FileSystem.get(conf); FSDataInputStream inputStream = hdfs.open(inFile); System.out.println("myfile: " + inputStream.readUTF()); inputStream.close(); } } ~~~ #### 3.4.6 编译并打包HDFS读程序 使用javac编译刚刚编写的代码,并使用jar命令打包为hdpAction.jar ~~~ [root@client ~]# javac ReadFile.java [root@client ~]# jar -cvf hdpAction.jar ReadFile.class added manifest adding: ReadFile.class(in = 1093) (out= 597)(deflated 45%) ~~~ #### 3.4.7 执行HDFS读程序 在client服务器上使用hadoop jar命令执行hdpAction.jar,查看程序运行结果: ~~~ [root@client ~]# hadoop jar ~/hdpAction.jar ReadFile myfile: nj 20161009 23 [root@client ~]# ~~~ #### 3.4.8 安装与配置Eclipse Hadoop插件 关闭Eclipse软件,将hadoop-eclipse-plugin-2.7.1.jar文件拷贝至eclipse安装目录的plugins文件夹下。如图3-2和图3-3所示: ![](https://box.kancloud.cn/fe68df5d0c34e83f13a036d04c5e66fa_486x56.jpg) ![](https://box.kancloud.cn/da5f91b51f4ed078f0232482c1d0d293_162x51.jpg) 接下来,我们需要准备本地的Hadoop环境,用于加载hadoop目录中的jar包,只需解压hadoop-2.7.1.tar.gz文件,解压过程中可能会遇到如下错误,点击关闭忽略即可。 现在,我们需要验证是否可以用Eclipse新建Hadoop(HDFS)项目。打开Eclipse软件,依次点击FileàNewàOther,查看是否已经有Map/Reduce Project的选项。第一次新建Map/Reduce项目时,需要指定hadoop解压后的位置。如图3-5、图3-6和图3-7所示: ![](https://box.kancloud.cn/aed78a35248fff5c5b584bb3f31a8983_382x178.jpg) 图3-5 Eclipse新建Map/Reduce项目 ![](https://box.kancloud.cn/661fd387248bbafdf4047f613d297614_299x55.jpg) 图3-6 设置Hadoop安装目录 ![](https://box.kancloud.cn/b2d38dd1ef7d0e8aab4c7a4b128004c7_327x55.jpg) 图3-7 指定Hadoop安装目录 #### 3.4.9 使用Eclipse开发并打包HDFS写文件程序 打开Eclipse,依次点击FileàNewàMap/Reduce Project或FileàNewàOtherà Map/Reduce Project,新建项目名为WriteHDFS的Map/Reduce项目。 新建WriteFile类并编写如下代码: ~~~ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataOutputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; public class WriteFile { public static void main(String[] args)throws Exception{ Configuration conf=new Configuration(); FileSystem hdfs = FileSystem.get(conf); Path dfs = new Path("/weather.txt"); FSDataOutputStream outputStream = hdfs.create(dfs); outputStream.writeUTF("nj 20161009 23\n"); outputStream.close(); } } ~~~ 在Eclipse左侧的导航栏选中该项目,点击ExportàJavaàJAR File,填写导出文件的路径和文件名(本例中设置为hdpAction.jar),确定导出即可。如图3-8和图3-9所示: ![](https://box.kancloud.cn/daae78f41c8767a98ed4d062fbbbff9c_487x56.jpg) 图3-8 选择导出JAR包文件 ![](https://box.kancloud.cn/e71731d7bd40a63152f545b0f4a493f3_479x37.jpg) 图3-9 指定导出的JAR包文件名 #### 3.4.10 上传HDFS写文件程序jar包并执行 使用WinSCP、XManager或其它SSH工具的sftp工具上传刚刚生成的hdpAction.jar包至client服务器: ~~~ sftp> lcd C:/Users/Administrator/Desktop/ sftp> put hdpAction.jar Uploading hdpAction.jar to /root/hdpAction.jar 100% 2KB 2KB/s 00:00:00 C:/Users/Administrator/Desktop/hdpAction.jar: 2807 bytes transferred in 0 seconds (2807 bytes/s) ~~~ 在client服务器上使用hadoop jar命令执行hdpAction.jar: ~~~ [root@client ~]# hadoop jar ~/hdpAction.jar WriteFile ~~~ 查看是否已生成weather.txt文件,若已生成,则查看文件内容是否正确: ~~~ [root@client ~]# hadoop fs -ls / Found 2 items -rw-r--r-- 3 root supergroup 29 2016-12-05 12:28 /machines -rw-r--r-- 3 root supergroup 17 2016-12-05 14:54 /weather.txt [root@client ~]# Hadoop fs -cat /weather.txt nj 20161009 23 ~~~ #### 3.4.11 使用Eclipse开发并打包HDFS读文件程序 打开Eclipse,依次点击FileàNewàMap/Reduce Project或FileàNewàOtherà Map/Reduce Project,新建项目名为ReadHDFS的Map/Reduce项目。 新建ReadFile类并编写如下代码: ~~~ import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FSDataInputStream; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; public class ReadFile { public static void main(String[] args) throws IOException { Configuration conf = new Configuration(); Path inFile = new Path("/weather.txt"); FileSystem hdfs = FileSystem.get(conf); FSDataInputStream inputStream = hdfs.open(inFile); System.out.println("myfile: " + inputStream.readUTF()); inputStream.close(); } } ~~~ 在Eclipse左侧的导航栏选中该项目,点击ExportàJavaàJAR File,导出为hdpAction.jar。 3.4.12 上传HDFS读文件程序jar包并执行 使用WinSCP、XManager或其它SSH工具的sftp工具上传刚刚生成的hdpAction.jar包至client服务器,并在client服务器上使用hadoop jar命令执行hdpAction.jar,查看程序运行结果: ~~~ [root@client ~]# hadoop jar ~/hdpAction.jar ReadFile myfile: nj 20161009 23 [root@client ~]# ~~~