HDFS操作

Posted 糟老头修炼记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDFS操作相关的知识,希望对你有一定的参考价值。

Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。

HDFS是一个高度容错性的系统,适合部署在廉价的机器上。HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用。

HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的。

HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的。HDFS是Apache Hadoop Core项目的一部分。

 HDFS有着高容错性(fault-tolerant)的特点,并且设计用来部署在低廉的(low-cost)硬件上。而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(largedata set)的应用程序。

HDFS放宽了(relax)POSIX的要求(requirements)这样可以实现流的形式访问(streaming access)文件系统中的数据。

1.登录Hadoop用户,启动Hadoop:


su hadoop #切换成hadoop用户,密码:hadoopcd /usr/local/hadoop #进入hadoop目录./sbin/start-dfs.sh #启动hadoop,中间遇到选择,输入"yes"

2.利用shell命令和Hadoop进行交互:

fs是HDFS常用的命令,利用fs可以查看HDFS文件系统的目录结构、上传和下载数据、创建文件等。

 hadoop fs:适用于任何不同的文件系统,比如本地文件系统和HDFS文件系统

 hadoop dfs:只能适用于HDFS文件系统

 hdfs dfs:与hadoop dfs的命令作用一样,也只能适用于HDFS文件系统

(1)查看fs共支持了哪些命令:


./bin/hadoop fs

(2)查看具体某个命令的作用:查看put命令如何使用


./bin/hadoop fs -help put


(3)创建用户目录:

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

该命令表示在HDFS中创建一个“/user/hadoop”目录,“-mkdir”是创建目录的操作,“-p”表示如果是多级目录,则父目录和子目录一起创建, “/user/hadoop”就是一个多级目录,因此必须使用参数“-p”,否则会出错。
“/user/hadoop”目录就成为hadoop用户对应的用户目录

(4)显示HDFS中与当前用户hadoop对应的用户目录下的内容:


./bin/hdfs dfs -ls .

  “-ls”表示列出HDFS某个目录下的所有内容,“.”表示HDFS中的当前用户目录,也就是“/user/hadoop”目录,等价于:


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

HDFS操作


(5)列出HDFS根目录上的所有目录:


./bin/hdfs dfs -ls /

HDFS操作

(6)创建一个test目录和input目录:


./bin/hdfs dfs -mkdir test

 在创建test目录时,采用了相对路径形式,实际上,这个test目录创建成功以后,它在HDFS中的完整路径是“/user/hadoop/test”

在HDFS的根目录下创建一个名称为input的目录:


./bin/hdfs dfs -mkdir /input

 

(7)删除一个目录:使用rm命令,

删除刚才在HDFS中/user/hadoop目录下创建的“test”目录:


./bin/hdfs dfs -rm -r test

 “-r”参数表示如果删除“/user/hadoop/test”目录及其子目录下的所有内容,如果要删除的一个目录包含了子目录,则必须使用“-r”参数,否则会执行失败。

HDFS操作


(8)创建文件:

在本地Linux文件系统的“/home/hadoop/”目录下创建一个文件myLocalFile.txt


cd /home/hadoopvim myLocalFile.txt

随意输入一些单词然后保存:

hadoopSparkXMU BLAB


把本地文件系统的“/home/hadoop/myLocalFile.txt”上传到HDFS中的当前用户目录的input目录下,即上传到HDFS的“/user/hadoop/input/”目录下:


cd /usr/local/hadoop #进入hadoop目录,因为所有以./bin开头的命令都要在 /usr/local/hadoop路径下执行./bin/hdfs dfs -put /home/hadoop/myLocalFile.txt input #复制文件


使用ls命令查看一下文件是否成功上传到HDFS中:


./bin/hdfs dfs -ls input

查看HDFS中的myLocalFile.txt这个文件的内容:


./bin/hdfs dfs -cat input/myLocalFile.txt

HDFS操作

(9)下载文件:把HDFS中的myLocalFile.txt文件下载到本地文件系统中的“/home/hadoop/down/”这个目录下

在本地创建down目录:


cd /home/hadoopmkdir down #创建本地目录cd /usr/local/hadoop #注:所有以./bin开头的命令都要在 /usr/local/hadoop路径下执行./bin/hdfs dfs -get input/myLocalFile.txt /home/hadoop/down

到本地文件系统查看下载下来的文件myLocalFile.txt:


cd /home/hadoop/downlscat myLocalFile.txt 

HDFS操作


    (10)复制:把HDFS的“/user/hadoop/input/myLocalFile.txt”文件,拷贝到HDFS的另外一个目录“/input”中:


cd /usr/local/hadoop #注:所有以./bin开头的命令都要在 /usr/local/hadoop路径下执行./bin/hdfs dfs -mkdir /input #该目录如果已经删掉,则重新创建一下
./bin/hdfs dfs -cp input/myLocalFile.txt /input

HDFS操作


(11)网址:http://localhost:50070,可看到HDFS的web管理界面:


 

HDFS操作


 

3、利用Java API与HDFS进行交互

(1)在Ubuntu中安装eclipse

切换hadoop用户,启动Hadoop:


su hadoop #切换成hadoop用户cd /usr/local/hadoop #进入hadoop目录./sbin/start-dfs.sh #如果hadoop已经启动,则略过此命令;如未启动,则执行此命令,中间遇到选择,输入"yes"

将Eclipse安装在/usr/local/目录下:


cd /usr/local/

下载 Eclipse压缩包到当前目录(/usr/local/)下,对Eclipse解压缩:


sudo tar -zxf eclipse-jee-luna-SR2-linux-gtk-x86_64.tar.gz #hadoop用户密码是'hadoop'sudo chown -R hadoop ./eclipse # 修改文件权限

 

(2).创建eclipse桌面快捷图标


cd /usr/share/applicationssudo vim eclipse.desktop #执行此命令时可能会让输入密码

将下列代码复制到eclipse.desktop文件里面:


[DesktopEntry]Encoding=UTF-8Name=EclipseComment=EclipseExec=/usr/local/eclipse/eclipseIcon=/usr/local/eclipse/icon.xpmTerminal=falseStartupNotify=trueType=ApplicationCategories=Application;Development;

 “Exec=”后面为eclipse安装目录下的eclipse程序的位置路径

 “Icon=”后面为eclipse安装目录下的图标图片的路径;

 将其变为可执行文件:


sudo chmod u+x eclipse.desktop

找到/usr/share/applications目录,将Eclipse图标右键发送或复制到桌面即可:

(3)在eclipse里创建项目:

第一次打开Eclipse,默认工作空间目录位于“/root/workspace”下面,

  选择“File->New->Other->Java Project”菜单,开始创建一个Java工程:


HDFS操作


     在“Project name”后面输入工程名称“HDFSExample”,选中“Use default location”,让这个Java工程的所有文件都保存到默认的“/root/workspace/HDFSExample”目录下即可。

在“JRE”这个选项卡中,可以选择当前的Linux系统中已经安装好的JDK,比如java-8-openjdk-amd64。然后,点击界面底部的“Next>”按钮,进入下一步的设置。

(4).为项目添加需要用到的JAR包

HDFS操作



       需要在这个界面中加载该Java工程所需要用到的JAR包,这些JAR包中包含了可以访问HDFS的Java API。这些JAR包都位于Linux系统的Hadoop安装目录下,就是在“/usr/local/hadoop/share/hadoop”目录下。

点击界面中的“Libraries”选项卡,然后,点击界面右侧的“Add External JARs…”按钮,界面如图:

HDFS操作


在该窗口中,选择“FileSystem(文件系统)”,找到“/usr/local/hadoop/share/hadoop”,向Java工程中添加以下JAR包:

(1)”/usr/local/hadoop/share/hadoop/common”目录下的hadoop-common-2.7.1.jar和haoop-nfs-2.7.1.jar;

(2)“/usr/local/hadoop/share/hadoop/common/lib”目录下的所有JAR包;

(3)“/usr/local/hadoop/share/hadoop/hdfs”目录下的haoop-hdfs-2.7.1.jar和haoop-hdfs-nfs-2.7.1.jar;

(4)“/usr/local/hadoop/share/hadoop/hdfs/lib”目录下的所有JAR包。

 

(5)编写程序:

检测HDFS中是否存在一个文件:

  、“HDFSExample”右击,“New->Class”


在“Name”后面输入新建的Java类文件的名称,如“HDFSFileIfExist”;另外特别注意将package的值清空;其他都可以采用默认设置。然后,点击界面右下角“Finish”

HDFS操作

测试文件是否存在:

import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;publicclassHDFSFileIfExist{ publicstaticvoid main(String[] args){          try{              String fileName ="test.txt";              Configuration conf =newConfiguration();              conf.set("fs.defaultFS","hdfs://localhost:9000");            conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");            FileSystem fs =FileSystem.get(conf); if(fs.exists(newPath(fileName))){ System.out.println("文件存在"); }else{                System.out.println("文件不存在"); } }catch(Exception e){ e.printStackTrace();        }    }}

 

运行程序时 “Console”面板中还会显示一些类似“log4j:WARN…”的警告信息,不用理会。
(7)应用程序的部署
把Java应用程序生成JAR包,部署到Hadoop平台上运行。

在Hadoop安装目录下新建一个名称为myapp的目录,用来存放自己编写的Hadoop应用程序:


cd /usr/local/hadoopmkdir myapp

在Eclipse工作界面中,在工程名称“HDFSExample”上点击鼠标右键,在弹出的菜单中选择“Export”,在弹出界面中选择"java"--"Runnable JAR file",点击“Next>”按钮,弹出如图所示界面。

HDFS操作

       在该界面中,“Launch configuration”用于设置生成的JAR包被部署启动时运行的主类,需要在下拉列表中选择刚才配置的类“HDFSFileIfExist-HDFSExample”。在“Exportdestination”中需要设置JAR包要输出保存到哪个目录,比如,这里设置为“/usr/local/hadoop/myapp/HDFSExample.jar”。在“Libraryhandling”下面选择“Extract required libraries into generatedJAR”。然后,点击“Finish”按钮,会出现如下图所示界面。

HDFS操作

       可以忽略该界面的信息,直接点击界面右下角的“OK”按钮,启动打包过程。打包过程结束后,会出现一个警告信息界面,如下图所示。

       可以忽略该界面的信息,直接点击界面右下角的“OK”按钮。至此,已经顺利把HDFSExample工程打包生成了HDFSExample.jar。

在Linux系统中查看生成的HDFSExample.jar文件:


cd /usr/local/hadoop/myappls

使用hadoop jar命令运行程序:


cd /usr/local/hadoop./bin/hadoop jar./myapp/HDFSExample.jar

 或者也可以使用如下命令运行程序:


cd /usr/local/hadoopjava -jar ./myapp/HDFSExample.jar

 命令执行结束后,会在屏幕上显示执行结果“文件不存在”

至此程序部署完成

(8)向java项目中导入源文件

在Eclipse中的hdfsExamples项目的src文件夹上单击鼠标右键,选择 “import”--“General”--“File System”,点击“Next”按钮。然后点击“Browse”按钮,在左侧列表中选择“File System”,在右侧列表中依次双击“home”--“hadoop”文件夹,然后点击“OK”按钮。然后在接下来的窗口中上方的右侧列表中,找到刚才新建的test.java文件,选中其复选框,点击“Finish”按钮。这样就把test.java文件导入到Eclipse中的hdfsExamples项目中了。

 

4.代码

(1)写入文件

1. 

import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.FSDataOutputStream;import org.apache.hadoop.fs.Path;public classWriteFile{ public staticvoid main(String[] args){                     try{                                  Configuration conf =newConfiguration();                                conf.set("fs.defaultFS","hdfs://localhost:9000");                                conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");                                FileSystem fs =FileSystem.get(conf);                                byte[] buff ="Hello world".getBytes();// 要写入的内容                                String filename ="test";//要写入的文件名                                FSDataOutputStream os = fs.create(newPath(filename));                                os.write(buff,0,buff.length);                                System.out.println("Create:"+ filename); os.close(); fs.close(); }catch(Exception e){ e.printStackTrace(); }           } }

(2)判断文件是否存在

import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;
public classFileIsExist{ public staticvoid main(String[] args){ try{ String filename ="test";
                                    Configuration conf =newConfiguration();                                    conf.set("fs.defaultFS","hdfs://localhost:9000");                                    conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");                                    FileSystem fs =FileSystem.get(conf); if(fs.exists(newPath(filename))){                                            System.out.println("文件存在");                                    }else{                                            System.out.println("文件不存在");                                    }                                    fs.close();                        }catch(Exception e){                                e.printStackTrace();                        }                }        }


(3)读取文件

import java.io.BufferedReader;import java.io.InputStreamReader;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.fs.FSDataInputStream; public classReadFile{ public taticvoid main(String[] args){ try{ Configuration conf =newConfiguration();                                conf.set("fs.defaultFS","hdfs://localhost:9000");                                conf.set("fs.hdfs.impl","org.apache.hadoop.hdfs.DistributedFileSystem");                                FileSystem fs =FileSystem.get(conf); Path file =newPath("test"); FSDataInputStream getIt = fs.open(file); BufferedReader d =newBufferedReader(newInputStreamReader(getIt)); String content = d.readLine();//读取文件一行                                System.out.println(content);                                d.close();//关闭文件                                fs.close();//关闭hdfs                        }catch(Exception e){                                e.printStackTrace();                        } } }


用命令行进行实验环境练习

1.上传文件至HDFS      

如果指定的文件在HDFS中已经存在,由用户指定是追加到原有文件末尾还是覆盖原有的文件。

(1)配置环境变量

配置一下PATH变量,将Hadoop的安装目录加入到PATH变量中,这样就可以在任意目录下直接使用hadoop fs、hdfs等命令了。

切换成Hadoop用户:

su hadoop #切换到hadoop

执行vim ~/.bashrc,在JAVA环境变量之后加入下面这行代码:

export PATH=$PATH:/usr/local/hadoop/bin:/usr/local/hadoop/sbin

 保存后执行source ~/.bashrc使配置生效。

source ~/.bashrc

启动Hadoop

start-dfs.sh

(2)创建本地测试文件     

#text.txt:“hello,this is text.txt”,#local.txt:“hello,this is local.txt”:

cd /home/hadoopvim text.txtvim local.txt

(3)检查文件是否存在

hdfs dfs -test -e text.txt#检查文件是否存在。返回值为1,表示不存在,返回值为0,表示存在#执行完这一句不会输出结果,需要继续输入命令"echo $?")查看结果echo $?


(4)将本地的local.txt文件上传到hdfs,并命名为text.txt

(hdfs中目标文件不存在)

 #将本地的local.txt文件上传到hdfs,并命名为text.txt hdfs dfs -appendToFile local.txt text.txt  #再次检查text.txt文件是否存在,echo返回值为0  hdfs dfs -test -e text.txt  echo $?

查看文件内容

#查看hdfstext.txt文件的内容,结果显示的是本地文件local.txt的内容“hello,this is local.txthdfs dfs -cat text.txt

(5)追加文件(hdfs中目标文件存在)

hdfs dfs -appendToFile local.txt text.txthdfs dfs -cat text.txt

hdfsdfs -appendToFile命令,如果hdfs中目标文件不存在,则相当于将本地文件上传到hdfs中,新建目标文件;如果hdfs中目标文件存在,则将本地文件中的内容追加到hdfs的目标文件中。

(6)覆盖文件

#用本地的text.txt文件覆盖hdfs中的text.txt文件hdfs dfs -copyFromLocal -f text.txt text.txt#查看hdfstext.txt文件的内容,结果显示的是本地文件text.txt的内容“hello,this is text.txthdfs dfs -cat text.txt

“如果text.txt文件存在则将local.txt文件的内容追加至text.txt,如果不存在则将local.txt文件的内容覆盖掉text.txt”(如下代码可视为一行代码,在终端中输入第一行代码后,直到输入 fi 才会真正执行): 

if $(hdfs dfs -test -e text.txt);then $(hdfs dfs -appendToFile local.txt text.txt);else $(hdfs dfs -copyFromLocal -f local.txt text.txt);fi

 

(7)源文件:    

1.  

import org.apache.hadoop.conf.Configuration;2. import org.apache.hadoop.fs.*;3. import java.io.*;4. publicclassHDFSApi{5. /**6. * 判断路径是否存在7. */8. publicstaticboolean test(Configuration conf,String path)throwsIOException{9. FileSystem fs =FileSystem.get(conf);10. return fs.exists(newPath(path));11. }12. /**13. * 复制文件到指定路径14. * 若路径已存在,则进行覆盖15. */16. publicstaticvoid copyFromLocalFile(Configuration conf,String localFilePath,String remoteFilePath)throwsIOException{17. FileSystem fs =FileSystem.get(conf);18. Path localPath =newPath(localFilePath);19. Path remotePath =newPath(remoteFilePath);20. /*fs.copyFromLocalFile 第一个参数表示是否删除源文件,第二个参数表示是否覆盖 */21. fs.copyFromLocalFile(false,true, localPath, remotePath);22. fs.close();23. }24. /**25. * 追加文件内容26. */27. publicstaticvoid appendToFile(Configuration conf,String localFilePath,String remoteFilePath)throwsIOException{28. FileSystem fs =FileSystem.get(conf);29. Path remotePath =newPath(remoteFilePath);30. /*创建一个文件读入流 */31. FileInputStreamin=newFileInputStream(localFilePath);32. /*创建一个文件输出流,输出的内容将追加到文件末尾 */33. FSDataOutputStreamout= fs.append(remotePath);34. /*读写文件内容 */35. byte[] data =newbyte[1024];36. int read =-1;37. while((read =in.read(data))>0){38. out.write(data,0, read);39. }40. out.close();41. in.close();42. fs.close();43. } 44./**45. * 主函数46. */47.publicstaticvoid main(String[] args){48.Configuration conf =newConfiguration();49.conf.set("fs.default.name","hdfs://localhost:9000");50.conf.set("dfs.support.append","true");51.conf.set("dfs.client.block.write.replace-datanode-on-failure.enable","true");52.conf.set("dfs.client.block.write.replace-datanode-on-failure.policy","NEVER");53. 54.String localFilePath ="/home/hadoop/text.txt"; // 本地路径55.String remoteFilePath ="/user/hadoop/text.txt"; // HDFS路径56.String choice ="append"; // 若文件存在则追加到文件末尾57.// String choice ="overwrite"; // 若文件存在则覆盖58.try{59./* 判断文件是否存在 */60.Boolean fileExists =false;61.if(HDFSApi.test(conf, remoteFilePath)){62.fileExists =true;63.System.out.println(remoteFilePath +"已存在.");64.}else{65.System.out.println(remoteFilePath +"不存在.");66.}67./* 进行处理 */68.if(!fileExists){// 文件不存在,则上传69.HDFSApi.copyFromLocalFile(conf, localFilePath, remoteFilePath);70.System.out.println(localFilePath +"已上传至 "+remoteFilePath);71.}elseif( choice.equals("overwrite")){ // 选择覆盖72.HDFSApi.copyFromLocalFile(conf, localFilePath, remoteFilePath);73.System.out.println(localFilePath +"已覆盖 "+remoteFilePath);74.}elseif( choice.equals("append")){ // 选择追加75.HDFSApi.appendToFile(conf, localFilePath, remoteFilePath);76.System.out.println(localFilePath +"已追加至 "+remoteFilePath);77.}78.}catch(Exception e){79.e.printStackTrace();80.}81.}82.}


查看控制台的输出结果




以上是关于HDFS操作的主要内容,如果未能解决你的问题,请参考以下文章

大数据学习——java代码实现对HDFS文件的readappendwrite操作

VSCode自定义代码片段15——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程

Java操作HDFS代码样例

大数据学习——hdfs客户端流式操作代码的实现

hdfs深入:10hdfs的javaAPI操作