Apache Hadoop 使用Java API操作HDFS之代码实现文件夹遍历文件上传下载

先放maven依赖POM.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mycat</groupId>
    <artifactId>javaapihdfs</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.6</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.7.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>

测试类准备(单元测试):

每个测试方法运行前必须运行的初始化方法:(@BeforeClass注解)

private static FileSystem fs;
@BeforeClass
public static void init() throws URISyntaxException, IOException, 			    InterruptedException {
    URI uri=new URI("hdfs://192.168.183.81:9000");
    Configuration conf=new Configuration();
    fs = FileSystem.get(uri, conf, "hadoop");
}

每个测试方法运行结束后必定运行关闭资源方法:(@AfterClass注解)

@AfterClass
public static void destroy() throws IOException {
    if(null!=fs){
        fs.close();
    }
}

Part One

使用Java API如何实现对HDFS上某一个文件夹下文件信息的递归遍历?

@Test
public void testLs() throws IOException {
    Path origin=new Path("/mktest");// hdfs目录树下的/mktest目录
    RemoteIterator<LocatedFileStatus> status = fs.listFiles(origin, true);
    while(status.hasNext()){
        LocatedFileStatus fileStatus = status.next();
        System.out.println("路径:"+fileStatus.getPath());
        System.out.println("副本数:"+fileStatus.getReplication());
        System.out.println("文件大小:"+fileStatus.getLen());
        System.out.println();
    }
}

输出结果展示

路径:hdfs://192.168.183.81:9000/mktest/a.txt
副本数:3
文件大小:0

路径:hdfs://192.168.183.81:9000/mktest/hadoop-2.7.7-centos-6.7.tar.gz
副本数:3
文件大小:199076243

路径:hdfs://192.168.183.81:9000/mktest/test.md
副本数:3
文件大小:3334

Part Two

如何使用Java API实现从本地文件系统上传文件到HDFS?

方案一:(copyFromLocal方法)

@Test
public void testUpload() throws URISyntaxException, IOException, InterruptedException {
    Path origin=new Path("D:\\share\\hadoopBase/hadoop-eclipse-plugin-2.6.5.jar");
    Path goal=new Path("/mktest");
    fs.copyFromLocalFile(origin, goal);
}

方案二:(使用IOUtils包装流的copyBytes方法)

@Test
public void testIOUpload() throws IOException {
    InputStream in = new FileInputStream("D:\\share\\hadoopBase/hadoop-eclipse-plugin-2.6.5.jar");
    FSDataOutputStream out = fs.create(new Path("/mktest/hadoop-eclipse-plugin-2.6.5.jar"));
    IOUtils.copyBytes(in, out, 2048, true);
}

结果

[hadoop@mycat01 ~]$ hdfs dfs -ls /mktest
Found 4 items
-rw-r--r--   3 hadoop hadoop          0 2019-03-06 02:02 /mktest/a.txt
-rw-r--r--   3 hadoop hadoop  199076243 2019-03-06 07:12 /mktest/hadoop-2.7.7-centos-6.7.tar.gz
-rw-r--r--   3 hadoop hadoop   32188216 2019-03-07 11:40 /mktest/hadoop-eclipse-plugin-2.6.5.jar
-rw-r--r--   3 hadoop hadoop       3334 2019-03-06 09:45 /mktest/test.md

上传成功,但是需要注意的是,第二种方案,目标文件名需要指定,不能只给定文件夹。

Part Three

如何使用Java API实现从HDFS文件系统下载文件到本地文件系统?

方案一:(copyToLocal方法)

@Test
public void testDownload() throws URISyntaxException, IOException, InterruptedException {
    Path origin=new Path("/mktest/hadoop-eclipse-plugin-2.6.5.jar");
    Path goal=new Path("D:/");
    fs.copyToLocalFile(origin, goal); // 不成功的话先改用下面的四个参数的方法
    // fs.copyToLocalFile(false,origin, goal,true);  
}

方案二:(使用IOUtils包装流的copyBytes方法)

@Test
public void testIODownload() throws IOException {
    FSDataInputStream in = fs.open(new Path("/mktest/hadoop-eclipse-plugin-2.6.5.jar"));
    OutputStream out=new FileOutputStream("D:/hadoop-eclipse-plugin-2.6.5.jar");
    IOUtils.copyBytes(in, out, 2048, true);
}

下载成功,但是需要注意的是,第二种方案,目标文件名需要指定,不能只给定文件夹。

Part Four

上面下载采用方案一的话,即使用fs.copyToLocalFile(origin, goal)进行下载的话会生成crc文件。这是为什么呢?

如果你使用两个参数没有报错的话,说明你已经解决了某个问题,这里采用两个参数的copyToLocalFile方法会生成crc校验文件,用来校验从hdfs拿过来的文件是否是完整的。所以你完全可以采用四个参数的方法。不生成crc校验文件,这个对应其第四个参数,即useRawLocationFileSystem=true。默认情况下这个值为false,即下载的时候需要crc校验文件。第一个参数是delSrc,即是否删除源文件,作用,你懂的。

如果你使用两个参数报错:

(null) entry in command string: null chmod 0644 xxx

方案一:下载winutils.exe以及hadoop相关配置文件,配置到Path中去

如果日志中报hadoop.tmp.dir没有设置,或者没有找到winutils.exe,此方案也可以解决。(亲试)

下载:winutils.exe和hadoop.dll等

解压到当前目录下,然后进入hadoopwinutils,拷贝文件夹路径,新建环境变量HADOOP_HOME,并把%HADOOP_HOME%\bin配置到PATH中。

然后重启电脑,重启Hadoop集群,搞定。

方案二:CSDN上看到别人说的,自己没试过

hadoop.dll文件在上面方案一中压缩包也有

下载hadoop.dll文件

并拷贝到c:\windows\system32目录中

然后重新运行代码程序即可

猜你喜欢

转载自blog.csdn.net/qq_33713328/article/details/88320005
今日推荐