HDFS操作 常用的Java接口(Hadoop入门二)

HDFS的设计简介:

  • 超大文件:通常指具有几百MB,GB甚至TB大小的文件。

  • 流式数据访问:一次写入,多次读取是最高效的访问模式。每次分析都将涉及该数据集的大部分甚至

  • 全部数据,因此读取整个数据集比读取第一条记录的时间延迟更为重要。

  • 商用硬件:Hadoop部署在普通硬件的集群上,因为节点故障率比较高

  • 不支持低时间延迟的数据访问:HBase是更好的

  • 大量的小文件:文件总数受限于namenode的内存容量,每个文件,目录和数据块的存储信息大致为150个字节。

  • 不支持多用户写入,任意修改文件

  • HDFS以管理节点-工作节点模式运行,一个时NameNode(管理节点)和多个DataNode(工作节点),namenode管理文件的命名空间,维护者文件系统树及整棵树的所有文件和目录(永久保存在本地磁盘),同时记录着每个文件中各个块所在的数据节点信息(临时保存本地磁盘),因为会在系统启动时重新分配。datanode根据需要存储并检索数据块(受客户端namenode调度),并定期像namenode发送所存储的块信息。

  • SecondaryNameNode可以理解为namenode的备份,在namenode挂掉之后用于数据恢复,不过保存状态总是滞后于主节点。

  • 数据块:默认为128M,HDFS的数据块比磁盘的块大的原因是最小化寻址开销,当块足够大时,寻址的时间就远小于磁盘传输数据的时间。


更详细的HDFS内容在后续博客中细细道来~
编译器:IDEA
需要用的工具:Maven, JUnit4.11

打开IDEA创建Maven的简单工程流程我就不说了,网上都是。
需要先配置pom.xml文件,把需要的jar包,JUnit,Hadoop版本属性,依赖等信息配置好,在进行开发

首先配置pom.xml文件,为了看的舒服点,我把它放在后面

pom.xml Maven配置文件

用Java API操作Hadoop文件系统与一般工厂模式相同,首先需要Configuration类,还需要FileSystem类,里面封装了hdfs的操作方法

  • 先看看常用的命令行操作有哪些:
hadoop常用命令
hadoop fs -ls [path]
hadoop fs -put
hadoop fs -copyFromLocal
hadoop fs -moveFromLocal
hadoop fs -cat
hadoop fs -text
hadoop fs -get
hadoop fs -mkdir
hadoop fs -mv
hadoop fs -getmerge
hadoop fs -rm
hadoop fs -rmdir
hadoop fs -rm -r
hadoop fs -cp [file1/dir1] [file2/dir2] 与 hadoop distcp [file1/dir1] [file2/dir2]基本等价

我们用JUnit 测试这些API
首先将必要的,重复的连接操作封装起来:利用@Before, @After 注释分别在测试@Test前后执行

  • 整个测试类需要的固定变量放在最前面
    URL注意点: 有人可能习惯用hostname如我的hadoop000连接的,如果自己的系统是Windows的需要在文件C:\Windows\System32\drivers\etc\host 添加IP地址映射,若不进行配置,在Windows中只能使用虚拟机IP地址进行操作,不能使用hostname
	//连接的URL
    public static final String hadoopUrl = "hdfs://192.168.132.128:8020";
    //连接的用户名
    public static final String user = "hadoop";
    Configuration configuration = null;
    FileSystem fileSystem = null;
    @Before
    public void setUp() throws Exception {
        System.out.println("=========set up=========");
        configuration = new Configuration();
        configuration.set("dfs.replication", "1");
        fileSystem = FileSystem.get(new URI(hadoopUrl), configuration, user);
    }
	/**
     * 完成测试后将configuration,filesystem置空回收内存
     */
    @After
    public void tearDown() {
        configuration = null;
        fileSystem = null;
        System.out.println("=========tear down=========");
    }

创建文件夹

  • 返回值:boolean
    源码如下:
    在这里插入图片描述
    /**
     * 创建一个文件夹
     * @throws Exception
     */
    @Test
    public void mkdir() throws Exception{
        System.out.println(fileSystem.mkdirs(new Path("/hdfsapi/mkdir")));
    }
  • 测试成功,控制台输出:
    在这里插入图片描述
  • 查看根目录是否有叫mkdir的文件夹
    在这里插入图片描述
  • 还可以去游览器看
    在这里插入图片描述
    如果出现不能连接8020端口 [ java.net.ConnectException: Connection refused: connect.无法连接 ](出错的时候忘记截图了),需要检查8020端口是否打开,未打开需要打开端口,重新启动hdfs后再试一次!如果还是没解决最好看看官方文档:https://wiki.apache.org/hadoop/ConnectionRefused

创建文件

  • 返回值:FSDataOutputStream
@Test
    public void creat() throws IOException {
        Path path = new Path("/hdfsapi/test/a.txt");
        FSDataOutputStream out = fileSystem.create(path);
        out.writeUTF("This is fileSystem.create() API TEST");
        out.flush();
        out.close();
    }

注意:文件流走缓冲区,需要flush(),别忘了
在这里插入图片描述
看下里面的内容是不是上面写入的
在这里插入图片描述
去看看游览器的
在这里插入图片描述

  • 多看几眼发现有点问题,这里的副本系数是 3 ,不过我记得设置的是 1,我们再去看看配置文件hdfs-site.xml中的dfs-repelication属性
    在这里插入图片描述
  • Configuration类中复本系数是自己默认的3没有走我们设置的属性,所以这里需要单独设置副本系数的属性,因为上面的我已经改过了,这里只是强调一下:这么做的目的是因为我们只有一个DataNode,所以如果是设置3个复本的会连续出现块复本不足的警告。
configuration.set("dfs.replication", "1");

测试一下dfs.replication属性,控制台输出

@Test
	public void testReplication(){
    System.out.println(configuration.get("dfs.replication"));
}

也可以新创建一个文件试试看,这里就变成了1了
在这里插入图片描述

删除文件

  • 返回值:boolean
@Test
    public void remove() throws Exception {
        Path path = new Path("/hdfsapi/mkdir/repelication.txt");
     	fileSystem.delete(path, true);
    }

重命名文件名

  • 返回值:boolean
@Test
    public void rename() throws Exception {
        Path oldPath = new Path("/hdfsapi/test/a.txt");
        Path newPath = new Path("/hdfsapi/test/aa.txt");
        fileSystem.rename(oldPath, newPath);
    }

拷贝本地文件到HDFS文件系统

  • 返回值:void
@Test
    public void copyFromLocalFile() throws Exception {
        Path src = new Path("/Users/rocky/data/hello.txt");
        Path dst = new Path("/hdfsapi/test/");
        fileSystem.copyFromLocalFile(src,dst);
    }

在这里插入图片描述
拷贝成功!

拷贝大文件到HDFS文件系统:带进度条

需要输入流与输出流,调用org.apache.hadoop.io.copyBytes(InputStream in, OutputStream out, int buffSize) 拷贝

  @Test
    public void copyFromLocalBigFile() throws  Exception{
        InputStream input = new BufferedInputStream(new FileInputStream(new File("E:\\ComputerQQDownload\\jdk-8u192-linux-x64.tar.gz")));

        FSDataOutputStream out = fileSystem.create(new Path("/hdfsapi/test/jdk.tgz"), new Progressable() {
            @Override
            public void progress() {
                System.out.print(">");
            }
        });
        IOUtils.copyBytes(input,out,4096);
    }

'>>>…'就是我们打印出来的简单进度条
在这里插入图片描述

拷贝HDFS文件到本地

@Test
    public void copyToLocalFile() throws Exception {
        Path src = new Path("/hdfsapi/test/aa.txt");
        Path dst = new Path("D:\\");
        fileSystem.copyToLocalFile(src, dst);
    }

如果出现copyToLocalFile(Path src, Path dst)空指针异常,可能是Windows兼容性问题,换用:copyToLocalFile(boolean delSrc, Path src, Path dst, boolean useRawLocalFileSystem)

查看目标文件夹下的所有文件及状态

@Test
    public void listSatue() throws Exception{
        FileStatus[] status =  fileSystem.listStatus(new Path("/hdfsapi/test/"));
        for(FileStatus fileStatu : status){
            String isDir = fileStatu.isDirectory() ? "dir" : "file";
            String permission = fileStatu.getPermission().toString();
            short replication = fileStatu.getReplication();
            long  len = fileStatu.getLen();
            long blockSize = fileStatu.getBlockSize();
            Path path = fileStatu.getPath();

            System.out.println(isDir + "\t" + permission + "\t" + replication + "\t" + len + "\t"+ path + "\t" + blockSize);
        }
    }

    }

递归查看目标文件夹下的所有文件

 @Test
    public void recurListFile() throws Exception {
        RemoteIterator<LocatedFileStatus> iterator = fileSystem.listFiles(new Path("/hdfsapi/test/"), true);

        while (iterator.hasNext()) {
            LocatedFileStatus file = iterator.next();
            System.out.println(file.isDirectory() ? "dir" : "file" + "\t" + file.getPermission() + "\t" + file.getLen() + "\t" + file.getPath());
        }

    }

查看hdfs某一文件所在的block状态(文件元数据FileStatus)

包括:文件长度,块大小,复本,修改时间,所有者以及权限信息

@Test
    public void blockStatus() throws Exception {
        FileStatus fileStatus = fileSystem.getFileStatus(new Path("/hdfsapi/test/jdk.tgz"));
        BlockLocation[] blockLocations = fileSystem.getFileBlockLocations(fileStatus, 0, fileStatus.getLen());
        
        for (BlockLocation bk : blockLocations) {
            for (int i = 0; i < bk.getNames().length; i++)
                System.out.println(bk.getNames()[i] + "\t" + bk.getLength() + "\t" + bk.getOffset() + "\t" + bk.getHosts()[i]);
        }
    }

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.bigdata</groupId>
    <artifactId>hadoopLesson</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>hadoopLesson</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>

        <hadoop.version>2.6.0-cdh5.15.1</hadoop.version>
    </properties>


    <repositories>
        <repository>
            <id>cloudera</id>
            <url>https://repository.cloudera.com/artifactory/cloudera-repos</url>
        </repository>
    </repositories>

    <dependencies>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.7.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.0.0</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>


常用的应该就这些吧 (=。=),欢迎来补充~

猜你喜欢

转载自blog.csdn.net/qq_40311709/article/details/89055622