实现一次将多个文件上传到hdfs

本文介绍如何使用Hadoop的FileStatus和PathFilter接口配合通配符进行文件过滤,并通过Java API将特定格式的文件从本地文件系统上传至HDFS。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 需求场景分析 
      在某个单一操作中处理一系列文件是很常见的。例如一个日志处理的MapReduce作业可能要分析一个月的日志量。如果一个文件一个文件或者一个目录一个目录的声明那就太麻烦了,我们可以使用通配符(wild card)来匹配多个文件(这个操作也叫做globbing)。
  2. 为了实现上面的需求,需要先掌握如下的知识点

       2.1 Hadoop提供了两种方法来处理文件组:

    public FileStatus[] globStatus(Path pathPattern) throws IOException; 
    public FileStatus[] globStatus(Path pathPattern, PathFilter filter) throws IOException;

    • PathFilter 
        使用文件模式有时候并不能有效的描述你想要的一系列文件,例如如果你想排除某个特定文件就很难。所以FileSystem的listStatus()和globStatus()方法就提供了一个可选参数:PathFilter——它允许你一些更细化的控制匹配:

      package org.apache.hadoop.fs; 
      public interface PathFilter 

      boolean accept(Path path); 
      }

        2.2   Hadoop中的文件名匹配符(与Linux 中文件名通配符相同)

      * 代表0个或者多个特殊字符 
        例子 yum.* 代表的可以使yum.也可以是yum.a、yum.ab、yum.abc 当然小数点后面可以有多个字母 
      ? 代表的是任意一个字符 
        例子 yum.? 可以是yum.a yum.b yum.c“““`但是要注意小数点后面必须有任意一个字符 
      []代表的是中括号中的任意一个 
        例子[abcdef] 可以是a b c d e f 中的任意一个字母当然也可以是数字 
      [-]代表的是一个范围 
         例子 [a-z] 表示的是字母a到z之间的所有字母 
      [^]^是反向选择符号从字面意思可以知道也就是非的意思 
        例子[^abc]表示只要不a b c 这三个字符中的任意一个就选择

3.实现思路分析 
   我们利用通配符和PathFilter 对象,将本地多种格式的文件上传至 HDFS,并过滤掉 txt文本格式以外的文件 
   文件数据如下图所示: 
   这里写图片描述.

基于上述的需求分析,我们通过以下两步完成:

  • 首先使用globStatus(Path pathPattern, PathFilter filter),完成文件格式过滤,获取所有 txt 格式的文件。
  • 然后使用 Java API 接口 copyFromLocalFile,将所有 txt 格式的文件上传至 HDFS。

4.程序代码

  • 4.1 首先定义一个类 RegexAcceptPathFilter实现 PathFilter,过滤掉 txt 文本格式以外的文件。
package com.ywendeng.hdfs;

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.PathFilter;

public class RegxAcceptPathFilter implements PathFilter{
    private  final String regex;
    public RegxAcceptPathFilter(String regex) {
        this.regex=regex;
    }
    @Override
    public boolean accept(Path path) {

        boolean flag=path.toString().matches(regex);
        return flag;
    }
}
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 4.2 在main() 中调用listFile() 上传至HDFS
package com.ywendeng.hdfs;

import java.net.URI;
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;

/*
 * 对多文本过滤上传到HDFS
 */

public class MultipleFileUpload {
    //声明两个从不同文件系统类型的静态变量
    private static FileSystem fs = null;
    private static FileSystem local = null;

      public static void main(String[] args) throws Exception {
         //指定在元数据目录的地址在linux环境下 
         String  srcPath="/home/hadoop/hadoopFile/*";
         String  dstPath="hdfs://ywendeng:9000/hadoopFile/";
         //调用上传到HDFS
         listFile(srcPath, dstPath);
      }

      public static void listFile(String srcPath,String dstPath) throws Exception{
          //读取配置文件
          Configuration conf=new Configuration();
          //指定HDFS地址
          URI uri=new URI("hdfs://ywendeng:9000");
          fs=FileSystem.get(uri,conf);
          // 获取本地文件系统
          local=FileSystem.getLocal(conf);
          //获取文件目录
          FileStatus[] listFile=local.globStatus(new Path(srcPath), new RegxAcceptPathFilter("^.*txt$"));
          //获取文件路径
          Path[]  listPath=FileUtil.stat2Paths(listFile);
          //输出文件路径
          Path outPath=new Path(dstPath);
          //循环遍历所有文件路径
          for(Path p:listPath)
              fs.copyFromLocalFile(p, outPath);

      }
}

 
  • 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
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 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
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 4.3上传文件结果如下所示: 
    这里写图片描述 
    (备注: 如果是windows 环境下开发的程序,需要在Linux 环境下运行,在需要将程序打成jar 的形式,让后拷贝到linux 目录下 使用hadoop jar 指令运行。例如:hadoop jar /home/hadoop/mul.jar com.ywendeng.hdfs.MultipleFileUpload(Main函数的所在类的全路径名) 
    )
### 将多个HDFS文件加载到Hive表的方法 在实际应用中,可以通过多种方式将多个 HDFS 文件加载到 Hive 表中。以下是两种常见的方式: #### 方法一:通过 `LOAD DATA` 命令逐个加载文件 可以使用 `LOAD DATA INPATH` 命令逐一加载 HDFS 上的文件到 Hive 表中。此命令会将指定路径下的文件移动到 Hive 表对应的数据存储位置,并覆盖或追加数据。 示例代码如下: ```sql -- 覆盖模式加载单个文件 LOAD DATA INPATH 'hdfs://hadoop01:9000/tmp/sales_info_part1.txt' OVERWRITE INTO TABLE sales_info PARTITION(dt = '20191215')[^1]; -- 追加模式加载另一个文件 LOAD DATA INPATH 'hdfs://hadoop01:9000/tmp/sales_info_part2.txt' INTO TABLE sales_info PARTITION(dt = '20191215'); ``` 如果存在大量文件,则需要编写脚本批量执行这些 SQL 语句。例如,在 Shell 中循环调用 Hive CLI 或 Beeline 工具来完成操作。 #### 方法二:直接设置 Hive 表指向 HDFS 数据目录 另一种更高效的方式是让 Hive 表直接映射整个 HDFS 目录作为其底层数据存储路径。这样无需手动加载每一个单独的文件,只需确保目标目录下包含所有待处理的文件即可。 创建外部表时可指定 HDFS 的绝对路径作为数据存储地址: ```sql CREATE EXTERNAL TABLE IF NOT EXISTS multiple_files_table ( id INT, name STRING, value DOUBLE ) PARTITIONED BY (dt STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' STORED AS TEXTFILE LOCATION 'hdfs://hadoop01:9000/user/hive/multiple_files_data/'[^2]; ``` 之后只需要向该目录添加新文件或者子目录即可自动反映至对应的 Hive 表结构之中而不需要额外的操作步骤。 对于已经存在的内部管理型(Internal Managed Table),也可以修改它的默认存储位置为所需的 HDFS 文件夹所在之处并通过 ALTER TABLE ... SET LOCATION 实现更改功能[^3]。 注意:当采用这种方式时,请确认权限配置正确无误以便于读写访问;另外还需留意元数据更新可能带来的性能影响等问题。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值