011_Eclipse中使用HDFSFileSystemAPI事例介绍

需求

1.文件操作

1)上传本地文件到HDFS

2)读取文件

3)在hadoopfs中新建文件,并写入

4)重命名文件

5)删除hadoopfs上的文件

2.目录操作

1)读取某个目录下的所有文件

2)在hadoopfs上创建目录

3)删除目录

3. HDFS信息

1)查找某个文件在HDFS集群的位置

2)获取HDFS集群上所有节点名称信息

准备工作:

1、新建一个project项目,添加lib文件夹,将图示的jar文件添加到文件夹中,并将其add to built path。如图示。

2、添加conf文件夹,将core-site.xml和hdfs-site.xml两个文件拷贝到conf下面。刷新。主要作用是配置主机地址。

3、编译环境和运行环境都是用1.7版本,即jdk1.7和jre1.7。本实验使用的是Eclipse indigo-windows-32bit和jdk1.7-32bit。

4、此处暂时不需要hadoop-plugin插件,有的话也不影响,但是主机hosts文件要配置好,就是在主机cmd命令中可以通过域名访问CentOS端NameNode主机。

HDFS  文件读取流程

1.Client调用FileSystem.open()方法:
  1)FileSystem通过RPC与NN通信,NN返回该文件的部分或全部block列表(含有block拷贝的DN地址)。
  2)选取距离客户端最近的DN建立连接,读取block,返回FSDataInputStream。
2.Client调用输入流的read()方法:
  1)当读到block结尾时,FSDataInputStream关闭与当前DN的连接,并为读取下一个block寻找最近DN。
  2)读取完一个block都会进行checksum验证,如果读取DN时出现错误,客户端会通知NN,然后再从下一个拥有该block拷贝的DN继续读。
  3)如果block列表读完后,文件还未结束,FileSystem会继续从NN获取下一批block列表。
3.关闭FSDataInputStream

HDFS  文件写入流程

1.Client调用FileSystem的create()方法:
  1)FileSystem向NN发出请求,在NN的namespace里面创建一 新文件,但是并不关联任何块。
  2)NN检查文件是否已存在、操作权限。如果检查通过,NN记录新文件信息,并在某一个DN上创建数据块。
  3)返回FSDataOutputStream,将Client引导至该数据块执行写入操作。
2.Client调用输出流的write()方法:HDFS默认将每个数据块放置3份。
FSDataOutputStream将数据首先写到第一节点,第一节点将数据包传送并写入第二节点,第二节点=》第三节点。

3.Client调用流的close()方法:flush缓冲区的数据包,block完成复制份数后,
NN返回成功消息。

代码如下:

1、添加一个包(packet),org.dragon.hadoop.hdfs.utils,添加一个HDFSUtils.java文件,文件里面内容如下

package org.dragon.hadoop.hdfs.utils;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;

/**
 * @author ZhuXY
 * @time 2016-3-6 下午8:17:10
 */
public class HDFSUtils {
    public static FileSystem getFileSystem() throws IOException, Exception {
        
        // 获取配置
        Configuration conf = new Configuration();

        // 获取文件系统
        FileSystem hdfs = FileSystem.get(conf);
        return hdfs;

    }
}

 

2、下面就是文件操作的正式内容,其中就行Junit 4进行测试,Junit添加直接可以,网上教程很多,将此库文件包含到项目中就可以了。

代码中算法列表:

package org.dragon.hadoop.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.BlockLocation;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.io.IOUtils;
import org.dragon.hadoop.hdfs.utils.HDFSUtils;
import org.junit.Test;

/**
 * @author ZhuXY
 * @time 2016-3-6 下午5:57:53 通过FileSystem API 操作HDFS
 */
/**
 * 步骤:1、将5个jar包考到lib目录下
 * 2、新建一个conf文件夹,然后将core-site.xml和hdfs-site.xml两个文件考到其下
 *     原因:添加配置文件信息识别文件系统
 * 3、创建一个文件系统
 * 4、 打开输出流
 * 5、read
 * 6、close 
 * @author ZhuXY
 *
 */
public class HDFSFsTest {

    //读取当前系统中的文件
    @Test
    public void testRead() throws Exception {

        // 获取配置
        Configuration conf = new Configuration();

        // 获取文件系统
        FileSystem hdfs = FileSystem.get(conf);

        // 文件名称
        Path path = new Path("/opt/input/touch3.data");
        // 打开文件输入流----------open
        FSDataInputStream instream = hdfs.open(path);

        // 读取文件到控制台显示--------read
        IOUtils.copyBytes(instream, System.out, 4096, false);

        // 关闭流---------------close
        IOUtils.closeStream(instream);
    }

    //列出当前文件和目录
    @Test
    public void testList() throws Exception {
        // 获取配置
        Configuration conf = new Configuration();

        // 获取文件系统
        FileSystem hdfs = FileSystem.get(conf);

        Path path = new Path("/wc");

        FileStatus[] fileStatus = hdfs.listStatus(path);

        for (FileStatus fs : fileStatus) {
            
            Path p = fs.getPath();

            String info = fs.isDir() ? "目录" : "文件";

            // System.out.println("5");
            System.out.println(info + ":" + p);
        }
    }
    
    //对上传的文件重命名
    @Test
    public void testRename() throws Exception{
        
        FileSystem fsFileSystem=HDFSUtils.getFileSystem();
        
        //HDFS 文件上传路径
        Path srcPath=new Path("/opt/input/touch3.data");
        Path destPath=new Path("/opt/input/rename.data");
        
        boolean flag=fsFileSystem.rename(srcPath, destPath);
        
        System.out.println(flag);
        
    }
    
    //创建文件,连同目录一起创建
    @Test
    public void testCreate() throws Exception{
        FileSystem hdfsFileSystem=HDFSUtils.getFileSystem();
        
        //HDFS文件上传路径
        Path path=new Path("/wc/test/touch.data");
        
        //创建文件,并获取输出流
        FSDataOutputStream fsDataOutputStream=hdfsFileSystem.create(path);
        
        //通过输出流写入数据
//        fsDataOutputStream.writeUTF("你好,hadoop!");
        fsDataOutputStream.write("你好".getBytes());
        fsDataOutputStream.writeUTF("hadoop!");
        
        
        IOUtils.closeStream(fsDataOutputStream);                
    }
    
    //删除文件
    @Test
    public void testRemove() throws Exception{
        FileSystem fsFileSystem=HDFSUtils.getFileSystem();
        Path path=new Path("/opt/input/touch3.data");
        
        boolean flag=fsFileSystem.deleteOnExit(path);
        System.out.println(flag);
    }
    
    //删除目录
    @Test
    public void testRemoveDir() throws Exception {
        FileSystem fsFileSystem=HDFSUtils.getFileSystem();
        
        Path path=new Path("/opt/input/");
        
        boolean flag=fsFileSystem.delete(path,true);
        
        System.out.println(flag);
        
    }
    
    
    
    
    //上传文件---put copyFromLocal
    @Test
    public void testPut() throws Exception {
        FileSystem fsFileSystem=HDFSUtils.getFileSystem();
        
        Path srcPath=new Path("C:/jdk-8u73-linux-x64.tar.gz");
        
        //HDFS上传文件路径
        Path destPath=new Path("/wc/123/"); //此处目录如果不存在会保存在/wc目录下,取名123
        
        fsFileSystem.copyFromLocalFile(srcPath, destPath);
        
    }
    //查看某个文件在HDFS集群中的位置
    @Test
    public void testLocation() throws Exception {
        
        FileSystem fsFileSystem=HDFSUtils.getFileSystem();
        
        //HDFS上传文件路径
        Path path=new Path("/wc/123/"); 
        
        FileStatus fsFileStatus=fsFileSystem.getFileStatus(path);
        
        //获得所有的块所在的位置信息包括:主机名,块名称、块大小etc
        BlockLocation[] blockLocations=fsFileSystem.getFileBlockLocations(fsFileStatus,0,fsFileStatus.getLen());
        
        for(BlockLocation blockLocation:blockLocations){
            
            String[] hostStrings=blockLocation.getHosts();//获取所在的主机
            //System.out.println(hostStrings);//这样写不行
            //System.out.println(hostStrings[0]);//这样写可以
            for(String host:hostStrings)
                System.out.println(host);
        }
        
        
    }
    
    //获取集群中所有的节点的名称信息
    @Test
    public void testCluster() throws Exception {
        
        FileSystem fsFileSystem=HDFSUtils.getFileSystem();
        
        //将文件系统强制转换为分布式文件系统
        DistributedFileSystem distributedFileSystem=(DistributedFileSystem)fsFileSystem;
        
        //获取文件系统中数据状态信息
        DatanodeInfo[] datanodeInfos=distributedFileSystem.getDataNodeStats();
        
        //循环遍历  
        for(DatanodeInfo datanodeInfo:datanodeInfos){
            String hostnameString=datanodeInfo.getHostName();
            System.out.println(hostnameString);
        }
    }
}

 

学习内容

1、学习使用代码追踪工具,光标移动到类名,然后按住Ctril键出现小手的时候,单击,然后Attach Source就可以了,可以使源码文件,还是不如行的话重启一下Eclipse就行了,实验中遇到这种情况。

2、学习快捷键的使用,注释alt+/,将一行代码上移一行alt+|(向上箭头),复制上移ctril+alt+|(向上箭头),删除一行Ctrl+d,快速对齐Ctrl+shift+F,打开源码搜素open type Ctrl+shift+T,打开outline是ctrl+o等。

3、特别注意的是core-site.xml中的主机地址一定要配置好。

 

 

posted @ 2016-03-08 11:12  YouxiBug  阅读(329)  评论(0编辑  收藏  举报