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中的主機地址一定要配置好。

 

 

發佈了99 篇原創文章 · 獲贊 6 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章