【2-4】用Java接口操作HDFS

来源:互联网 发布:网络直播主持词 编辑:程序博客网 时间:2024/06/11 07:13

我们使用shell只进行一些简单的操作,还是用Java接口比较多。因此我们要使用Java接口的方式来操作HDFS

我们new一个project 叫hadoop0106,然后再创建一个文件夹(new一个folder)叫lib,把jar包导入进去


在hadoop2.2.0/share/hadoop/common 里面的三个jar包 Ctrl+c

在hadoop2.2.0/share/hadoop/common/lib下边的一大堆jar包 复制过来。

在hadoop2.2.0/share/hadoop/hdfs 里面的三个jar包

之后,我们点击jar包,之后点右键——构建路径,把这些jar包变成一个一个“奶瓶”,之后在Java构建路径中,它们变成了一个一个的小奶瓶


然后,我们创建一个包叫cn.itcast.hadoop.hdfs,在包里创建一个类,叫HDFSDemo,如图


我无需了解哪些底层信息,而是它给我一个工具类,只要我使用这些工具类,就能把这些细节隐藏起来。


HDFS里有一个工具类叫:FileSystem  来自org.apache.包

在讲课的人里面,他一输入FileSystem,就能出来这个包,还能自动import这个包,我一出来就是报错


原因:他用了快捷键Alt+/这个键 之后只要双击那个org.apache.hadoop.fs那个,就可以自动import那个包了。

上次就卡在这里了,现在,继续开工!


我发现FileSystem是一个抽象类(abstract),不能用【至于怎么发现是抽象类的,关联了源码,这个我还没看懂】PS解释:导入源码之后,点击Ctrl+你想选的类,就能看到这个类的源码,源码里面写的是abstract,说明这个是个抽象类。2016.1.22

之后用FileSystemget方法,得到了一个具体的实现类


得到了实现类,就可以“玩” 了,可以来一个下载,我已经得到一个实现类“fs”了,那么先打开

打开是fs.open,我现在要打开一个路径,把它读进来。 我要从HDFS下载,需要先把HDFS文件读入到内存,然后再把数据写入到本地文件系统,因此,我们应该打开一个HDFS上的文件,

我们可以简写“/jdk1.7”  这个文件在HDFS上,


把这个文件先读进来。读进来之后,我还要new一个outputstream,写入文件系统


后面的地址是自己在Windows上的地址 c://jkd1.7


我们使用IOUtils.copyBytes() 将in里的内容拷贝到out,buffersize=4096,拷贝完成之后穿true就关闭

完整代码如下:

package cn.itcast.hadoop.hdfs;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.net.URI;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.FileSystem;import org.apache.hadoop.fs.Path;import org.apache.hadoop.io.IOUtils;public class HDFSDemo1 {public static void main(String[] args) throws Exception{// TODO 自动生成的方法存根FileSystem fs = FileSystem.get(new URI("hdfs://itcast01:9000"),new Configuration());InputStream in =  fs.open(new Path("/in.log"));OutputStream out = new FileOutputStream("c://windowsin.log");IOUtils.copyBytes(in, out, 4096, true);}}

代码的作用,是在Windows系统的C盘下,把hdfs上的in.log编程了windowsin.log。

值得注意的是,前面的import至关重要,导入时候用Alt+/ 但是容易导错,导错的话是无法解析出结果的。

当运行成功时,控制台给出的这样的结果


然后在window系统中便能看到我们从网上“下载”的数据了。





下载之后,接下来练习一下上传

上传我要用junit试一下【org.junit.before】

上传是将本地的文件上传到HDFS上

方法:首先,读取本地文件系统的文件,读取是input,之后在HDFS上创建一个文件,读取是in,创建是out,所以,我们将in里的内容创建到out里面去就可以了。

FileInputStream的父类:InputStream in = new FileInputStream("c://");

【AK: 每次新加了一个东西之后,都显示报错,之后让我“添加抛出声明”?这是what】


添加的时候遇到一个问题,在我 InputStream in =new FileInputStream("c://123.txt");//把本地文件系统作为inputstream读进来了

时,右键testUpload时候,运行失败,显示的是FileInputStream系统找不到指定文件。这时候,是因为我当时上传的windowsin是log文件,需要加上尾缀。


先定义一个初始化方法public void init()【因为都要用到初始化方法,因此单独拎出来】

代码如下:

FileSystem fs = null;@Beforepublic void init() throws IOException,URISyntaxException, InterruptedException{
<span style="white-space:pre"></span>//首先创建FileSystem的实现类(它是一个工具类)fs = FileSystem.get(new URI("hdfs://itcast01:9000"),new Configuration(),"root");//伪装成root,为了有权限}@Testpublic void testUpload() throws Exception{//首先要读取一个本地文件系统的文件,返回输入流InputStream in =new FileInputStream("c://123.txt");//把本地文件系统作为inputstream读进来了
<span style="white-space:pre"></span>//在HDFS上创建一个文件,返回输出流OutputStream out = fs.create(new Path("/test.jar"));//这时候不能new了,要指向HDFS文件了//输入—>输出
<span style="white-space:pre"></span>IOUtils.copyBytes(in, out, 4096, true);}

这种方法并不安全,因为是个人就可以随便往HDFS上面传文件,近些年,hadoop项目组努力地增加权限,修复这个漏洞。


方法2 :更简单的方法【暂时失败了】

用的copyToLocalFile方法

@Testpublic void testDownLoad() throws IllegalArgumentException, IOException{fs.copyToLocalFile(new Path("/in.log"), new Path("c://44444"));}

删除一个HDFS上的文件:

@Testpublic void testDel() throws Exception, IOException{boolean flag = fs.delete(new Path("/in.log"), false);System.out.println(flag);}

创建一个HDFS目录:

@Testpublic void testMkdir() throws IllegalArgumentException, IOException{boolean mkdirs = fs.mkdirs(new Path("/itcast0106"));System.out.println("mkdirs");}

用删除文件的方式删除空目录,是可以的。


但是如果我在itcast0106里面上传了文件之后,再删除。报错了。需要在删除那个false换成true【递归删除成功】








0 0
原创粉丝点击