Hdaoop HDFS 编程 Hshell

Hdaoop HDFS 编程 Hshell

记录一下大数据实验,利用Hadoop提供的Java API进行编程,实现一个简单的Hshell

实验内容

Hshell具体功能如下:

1.使用HShell -cp 本地路径 HDFS路径,将文件从Linux本地文件系统拷贝到HDFS指定路径上。
2.使用HShell -rm 路径删除文件
3.使用HShell -rm -r 路径删除目录
4.使用HShell -cp -r 本地目录路径 HDFS路径,将目录从Linux本地拷贝到HDFS指定路径上。
5.使用HShell -list 路径显示某个文件的信息或者某个目录的信息
6.使用HShell -mv 路径 路径移动文件或者重命名文件
7.使用HShell -find 文件名 目录实现在目录下递归查找某个文件名的文件。

难点

实验整体没什么难度,会Java的基本语法就能完成,稍微有难度的地方是第4个功能,需要递归拷贝目录,其他的只要调用API就行。

代码

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import java.util.Scanner;
import java.net.URI;
import java.io.File;
public class Hshell {
    public static void main(String[] args) {
        while(true){
            try {
                Scanner input=new Scanner(System.in);
                String command[]=input.nextLine().split("\\s+");
                if(command[0].equals("Hshell")){
                    switch (command[1]){
                        case "-cp":
                            if(command[2].equals("-r")){
                                copyLocalDir(command[3],command[4]);
                            }
                            else{
                                copyLocalFile(command[2], command[3]);
                            }
                            break;
                        case "-rm":
                            if(command[2].equals("-r")){
                                deletedir(command[3]);
                            }
                            else{
                                deleteFile(command[2]);
                            }
                            break;
                        case "-list":
                            disinfo(command[2]);
                            break;
                        case "-find":
                            findfile(command[2],command[3]);
                            break;
                        default:
                            System.out.println("Command Syntax Error!");
                    }
                }
                else if(command[0].equals("q")) {System.exit(0);}
                else{System.out.println("Command Syntax Error!");}
            }catch(Exception e) {
                e.printStackTrace();
            }
        }

    }
    public static boolean copyLocalFile(String lPath,String hPath){
        try{
            FileSystem hdfs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
            Path localPath = new Path(lPath);
            File localFile=new File(lPath);
            Path hdfsPath = new Path(hPath);
            if(localFile.exists())
            {
//                hdfs.mkdirs(hdfsPath);可以不用
                hdfs.copyFromLocalFile(true,localPath,hdfsPath);
                System.out.println("Copy successfully!");
            }
            else{
                System.out.println("Local file is not exist!");
                hdfs.close();
                return false;
            }
            hdfs.close();
        }catch(Exception e){
            e.printStackTrace();
        }
        return true;
    }

    public static boolean deleteFile(String deletepath){
        try{
            FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
            if(fs.exists(new Path(deletepath))) {
                if(fs.delete(new Path(deletepath),false)){
                    System.out.println("File "+ deletepath +" has been deleted successfully!");
                }
            } else {
                System.out.println("File not Exists!");
                fs.close();
                return false;
            }
            fs.close();
        }catch (Exception e){
            e.printStackTrace();
        }
        return true;
    }

    public static  boolean deletedir(String deleteDir){
        try {
            FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
            if(fs.delete(new Path(deleteDir),true)){
                System.out.println("Directory "+ deleteDir +" has been deleted successfully!");
            }
            fs.close();
        }catch(Exception e) {
            e.printStackTrace();
        }
        return true;
    }


    public static boolean copyLocalDir(String srcDir,String destDir){
        try{
            File f=new File(srcDir);
            FileSystem hdfs=FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
            if(f.exists()){
                if(f.isDirectory())
                {
                    String newdir=destDir.endsWith("/")?destDir+f.getName():destDir+"/"+f.getName();//新的路径
                    hdfs.mkdirs(new Path(newdir));
                    File[] files=f.listFiles();
                    for(File file:files)
                    {
                        if(file.isDirectory()){
                            copyLocalDir(file.getAbsolutePath(),newdir);
                        }else{
                            hdfs.copyFromLocalFile(new Path(file.getAbsolutePath()),new Path(newdir));
                        }
                    }
                }
                else{
                    System.out.println(srcDir+"is not a directory!");
                    hdfs.close();
                    return false;
                }
            }
            else{
                System.out.println("Directory is not exsists!");
                hdfs.close();
                return false;
            }
            hdfs.close();
        }catch(Exception e){e.printStackTrace();}
        return true;
    }

    public static boolean disinfo(String srcpath)
    {
        try {
            FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
            Path dirpath=new Path(srcpath);
            if(fs.getFileStatus(dirpath).isFile()){
                System.out.println(fs.getFileStatus(dirpath));
            }
            else if(fs.getFileStatus(dirpath).isDirectory())
            {
                FileStatus[] stats = fs.listStatus(dirpath);
                Path[] paths = FileUtil.stat2Paths(stats);
                for(Path p : paths)
                    if(fs.getFileStatus(p).isFile()) {
                        System.out.println(fs.getFileStatus(p));
                    }
                else System.out.println(p.getName());
            }
            else{
                System.out.println("Error path!");
                fs.close();
                return false;
            }
            fs.close();
        }catch(Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    public  static boolean mvfile(String srcpath,String destpath)
    {
        try {
            FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
            if(fs.exists(new Path(srcpath))) {
                fs.rename(new Path(srcpath),new Path(destpath));
            } else {
                System.out.println("File not Exists!");
                fs.close();
                return false;
            }
        }catch(Exception e) {
            e.printStackTrace();
        }
        return true;
    }

    public static boolean findfile(String filename,String dirpath){
        try{
            FileSystem hdfs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
            Path dpath=new Path(dirpath);
            if(hdfs.exists(dpath))
            {
                if(hdfs.getFileStatus(dpath).isDirectory()){
                    FileStatus[] stats = hdfs.listStatus(dpath);
                    for(FileStatus st:stats){
                        if(st.isFile()){
                            if(st.getPath().getName().equals(filename)){
                                System.out.println(st.getPath().toString());
                                hdfs.close();
                                return true;
                            }
                        }
                        else{
                            findfile(filename,st.getPath().toString());
                        }
                    }
                    hdfs.close();
                    return false;
                }
                else{
                    System.out.println(dirpath+" is not a directory!");
                }
            }
            else{
                System.out.println("Directory is not exist!");
                hdfs.close();
                return false;
            }
            hdfs.close();
        }catch(Exception e){
            e.printStackTrace();
        }
        return true;
    }
}

总结

常用API总结

目录相关

创建目录 public boolean mkdirs(Path f) throws IOException

目录存在性 public boolean exists(Path f) throws IOException

列出目录中的内容 public abstract FileStatus[] listStatus(Path f) throws FileNotFoundException, IOException

删除目录 public abstract boolean delete(Path f,boolean recursive) throws IOException
** recursive,是否需要递归删除。如果是删除目录的话,将该参数设置为true。否则,设置为false.**

文件相关

创建文件 public FSDataOutputStream create(Path f) throws IOException
根据参数的不同,create函数有多种重载类型

文件存在性判断 public boolean exists(Path f) throws IOException

文件写
** HDFS不支持文件的随机写,写文件的方式有两种:1)文件不存在,创建文件之后,开始对文件的内容进行写入。2)文件存在,打开文件,在文件尾部追加写。**

对于第一种方式,由于调用create方法后会返回FSDataOutputStream对象,使用该对象对文件进行写操作。第二种方式,使用FileSystem类的append接口,该接口也会返回FSDataOutputStream对象,同样使用该对象可对文件进行追加操作。

FSDataOutputStream有三个常用的方法,分别为write,flush,close函数。write将数据写入到文件中,flush将数据缓存在内存中的数据更新到磁盘,close则关闭流对象。
主函数示例

public static void main(String[] args) {
    try {
        Scanner sc = new Scanner(System.in);
        String filePath = '/'+sc.next();
        FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());

        Path srcPath = new Path(filePath);
        FSDataOutputStream os = fs.create(srcPath,true,1024,(short)1,(long)(1<<26));
        String str = "Hello, this is a sentence that should be written into the file.\n";
        os.write(str.getBytes());
        os.flush();
        os.close();

        os = fs.append(srcPath);
        str = "Hello, this is another sentence that should be written into the file.\n";
        os.write(str.getBytes());
        os.flush();
        os.close();
    }catch(Exception e) {
        e.printStackTrace();
    }
}

读文件
public FSDataInputStream open(Path f) throws IOException
public abstract FSDataInputStream open(Path f,int bufferSize) throws IOException
其中,bufferSize的含义为读取过程中所使用的缓冲区的大小。

public static void main(String[] args) {
    try {
        Scanner sc = new Scanner(System.in);
        String filePath = '/'+sc.next();
        FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), new Configuration());
        
        Path srcPath = new Path(filePath);

        FSDataInputStream is = fs.open(srcPath);
        while(true) {
            String line = is.readLine();
            if(line == null) {
                break;
            }
            System.out.println(line);
        }
        is.close();
    }catch(Exception e) {
        e.printStackTrace();
    }
}

文件重命名
public abstract boolean rename(Path src,Path dst)throws IOException

文件删除
public abstract boolean delete(Path f,boolean recursive) throws IOException
recursive,是否需要递归删除。如果是删除目录的话,将该参数设置为true。否则,设置为false.

问题总结

1.如何获取命令

利用Scanner
Scanner简介:
(1)Scanner是一个扫描器,对于键盘输入或者文件中的数据,先存到缓存区等待读取,它判断读取结束的标示是:空格,回车,tab 等;
(2)next()nextInt()方法读取到任意间隔符(如空格和回车)就结束,nextLine()读取到回车结束也就是“\r”,next()返回值为String类型,nextLine()返回值为String类型,nextInt()返回值为Int类型。
使用:
1) 利用next()方法时,不会以回车作为结束,可能导致用户的命令分为多行输入。例如Hshell+换行±rm+换行+路径文件。
2) 利用nextline读取命令行,以回车作为结束符。

2.如何分割命令

利用String类的split()
String的split方法支持正则表达式,正则表达式\s表示匹配任何空白字符,+表示匹配一次或多次。

3.java判断路径,文件,文件夹是否存在

File filename=new File(路径);
Filename.exists();判断该路径是否存在,存在返回true
filename.isDirectory():判断是否为目录,目录返回true
isfile() 判断是否为文件,文件返回true

你可能感兴趣的:(云计算,hdfs,hadoop,java)