• java 从 HDFS 读取数据到本地文件


    最近很烦,准确来说是有点慌了,很清楚原因是什么,同时也很清楚短期内解决不了,还是先调整心态吧。废话了。

    最近在搞大数据的东东,也边学边弄,一些小细节,整理下。


    场景描述

    算法模型是 java 代码使用 spark-submit yarn cluster 运行的,输出结果存储在了 HDFS 上,可能因为数据结构比较复杂吧,所以没有选择将结果存储在 hive 表中。这样的话,当后期在从 HDFS 读取结果时就会遇到数据合并的问题。

    比如:模型输出就是三行 json 数据。如下:

    {"description":"desc-1","id":"1","name":"name-1"}
    {"description":"desc-2","id":"2","name":"name-2"}
    {"description":"desc-3","id":"3","name":"name-3"}
    
    • 1
    • 2
    • 3

    同时在代码中设定存储文件为/user/deployer/people-result ,但实际存储在 HDFS 上时的目录结构是这样的:

    (base) [deployer@sh01 ~]$ hadoop fs -ls /user/deployer/people-result
    Found 3 items
    -rw-r--r--   3 deployer supergroup          0 2022-07-05 18:44 /user/deployer/people-result/_SUCCESS
    -rw-r--r--   3 deployer supergroup         50 2022-07-05 18:44 /user/deployer/people-result/part-00000-3d314ceb-5fd4-4a13-9d16-da3c838aa13f-c000.json
    -rw-r--r--   3 deployer supergroup        100 2022-07-05 18:44 /user/deployer/people-result/part-00001-3d314ceb-5fd4-4a13-9d16-da3c838aa13f-c000.json
    
    • 1
    • 2
    • 3
    • 4
    • 5

    给定的存储文件会被创建成目录,数据被分散存储在该目录下的若干个 .json 文件中。

    后期读取肯定需要合并数据。若手写代码合并不仅工作量大,而且也容易出错。


    解决办法

    java 已经提供了读取且合并的 API: FileUtil.copyMerge。先上代码:

    import java.io.IOException;
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.fs.FileUtil;
    import org.apache.hadoop.fs.Path;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest()
    public class DownloadFileFromHdfs {
    
      @Test
      public void test_download_and_merge() throws IOException {
        String src = "/user/deployer/people-result";
        String dst = "/Users/mac/Downloads/people-result.json";
        boolean result = copyMerge(src, dst);
        System.out.println(result);
      }
    
      private boolean copyMerge(String src, String dst)
          throws IOException {
        Configuration conf = new Configuration();
        FileSystem hdfs = FileSystem.get(conf);
        FileSystem local = FileSystem.getLocal(conf);
        final boolean result;
    
        try {
          Path srcPath = new Path(src);
          Path dstPath = new Path(dst);
          boolean deleteSource = false;
          String addString = null;
          result = FileUtil.copyMerge(hdfs, srcPath, local, dstPath, deleteSource, conf,
              addString);
        } finally {
          hdfs.close();
        }
        return result;
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    上面的代码很简单,需要说明两点:

    1. Configuration 类中保存了大数据集群的配置,所以需要将 core-site.xmlhdfs-site.xml 提前存放到 classpath 目录下,等程序启动时 xml 文件中的信息会被自动读取到配置类中。

    2. 使用时需要分清楚是从哪里读取到哪里。在上述场景中 src 是目录,dst 是文件。


    结果展示

    (base) ➜  Downloads cat /Users/mac/Downloads/people-result.json
    {"description":"desc-1","id":"1","name":"name-1"}
    {"description":"desc-2","id":"2","name":"name-2"}
    {"description":"desc-3","id":"3","name":"name-3"}
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    分类预测 | Matlab实现GA-XGBoost遗传算法优化XGBoost的多特征分类预测
    Spring 中更加简单的存储 (五大类注解 + @bean 注解) 和读取 (属性注入 + Setter 注入 + 构造方法注入) 对象
    【ubuntu noble】docker 容器无法使用 nvidia gpu
    【Redis知识点总结】(二)——Redis高性能IO模型剖析
    消息中间件——RabbitMQ(三)理解RabbitMQ核心概念和AMQP协议!
    arm安装pycryptodome失败
    网络流行简笔画图片大全,网络的简笔画图片
    关于MATLAB中双精度值的解释,以及Inf,NaN的值具体是多少,为什么是这个值
    day24-服务器端渲染技术02
    Hive安装配置笔记
  • 原文地址:https://blog.csdn.net/yy_diego/article/details/126209291