我们使用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); } }
值得注意的是,前面的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; @Before public 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,为了有权限 } @Test public 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); }
方法2 :更简单的方法【暂时失败了】
用的copyToLocalFile方法
@Test public void testDownLoad() throws IllegalArgumentException, IOException{ fs.copyToLocalFile(new Path("/in.log"), new Path("c://44444")); }
@Test public void testDel() throws Exception, IOException{ boolean flag = fs.delete(new Path("/in.log"), false); System.out.println(flag); }
@Test public void testMkdir() throws IllegalArgumentException, IOException{ boolean mkdirs = fs.mkdirs(new Path("/itcast0106")); System.out.println("mkdirs"); }
但是如果我在itcast0106里面上传了文件之后,再删除。报错了。需要在删除那个false换成true【递归删除成功】