在 PIG 中读取带有模式的文件

Posted

技术标签:

【中文标题】在 PIG 中读取带有模式的文件【英文标题】:Read files with pattern in PIG 【发布时间】:2014-10-13 19:16:00 【问题描述】:

我有一个场景,我使用 HCatStorer 将 40 个具有不同模式的文件从目录加载到 Hive 表。

Directory : opt/inputfolder/ 
Input Files Pattern :

inp1*.log,
inp2*.log,
    .....
inp39*.log,
inp40*.log.

我写了一个pig-script,它可以读取所有具有 40 种模式的文件。

但我的问题是,这 40 个文件是强制性的,我可能不会收到一些文件。在这种情况下,我收到一个异常说明:

Caused by: org.apache.hadoop.mapreduce.lib.input.InvalidInputException:
           Input Pattern opt/ip_files/inp16*.log matches 0 files

有没有办法处理这个异常?

我想读取剩余的 39 个带有模式的文件,即使该文件不存在。

如果我的源文件是字符串(例如,banana_2014012.log,orange_2014012.log,apple_2014012.log)怎么办

以下是我使用 HCatStorer 将这些文件中的数据加载到 HIVE 表的方法。

*** Pseudo code ****
banana_src = LOAD banana_*.log' using PigStorage;
......
Store banana_src into BANANA using HCatStorer;

apple_src = LOAD banana_*.log' using PigStorage;
......
Store apple_src into APPLE using HCatStorer;

orange_src = LOAD banana_*.log' using PigStorage;
......
Store orange_src into ORANGE using HCatStorer;

如果任何 src 没有文件,则此 Pig 脚本将抛出错误,指出匹配模式为 0,并且 PIG 脚本将失败。即使一个源文件不可用,我希望我的脚本加载其他表不会让我的工作失败。

谢谢。

【问题讨论】:

【参考方案1】:
 If you load inp1*.log, it matches inp16*.log also(if file present) but why are you again
 loading inp16*.log separately?

 Based on the above input i feel the below condition is sufficient for you.
        LOAD 'opt/ip_files/inp[1-9]*.log'

Please let me know if you are trying something different?

UPDATE:
I have one more option but not sure if this works for you.
1. Split your pig script into three parts say banana.pig, apple.pig and orange.pig each script will have their own logic.
2. Write a shell script to check existence of the each file pattern
3. If the files are present, call the corresponding pig script using pig params option else dont call. 
   In this option, if the files are not present that particular pig script will not be get triggred

Shellscript: test.sh
#!/bin/bash

BANANA_FILES="opt/ip_files/banana_*.log"
APPLE_FILES="opt/ip_files/apple_*.log"
ORANGE_FILES="opt/ip_files/orange_*.log"

if ls $BANANA_FILES > /dev/null 2>&1
then
    echo "Banana File Found"
    pig -x local -param PIG_BANANA_INPUT_FILES="$BANANA_FILES" -f banana.pig
else
    echo "No Banana files found"
fi

if ls $APPLE_FILES > /dev/null 2>&1
then
    echo "Apple File Found"
    pig -x local -param PIG_APPLE_INPUT_FILES="$APPLE_FILES" -f apple.pig
else
    echo "No APPLE files found"
fi

if ls $ORANGE_FILES > /dev/null 2>&1
then
    echo "Orange File Found"
    pig -x local -param PIG_ORANGE_INPUT_FILES="$ORANGE_FILES" -f orange.pig
else
    echo "No Orange files found"
fi


PigScript:banana.pig
banana_src = LOAD '$PIG_BANANA_INPUT_FILES' using PigStorage;
DUMP banana_src;

PigScript: apple.pig
apple_src = LOAD '$PIG_APPLE_INPUT_FILES' using PigStorage;
DUMP apple_src;

PigScript:orange.pig
orange_src = LOAD '$PIG_ORANGE_INPUT_FILES' using PigStorage;
DUMP orange_src;

Output1: All the three files are present
$ ./test.sh 
Banana File Found
(1,2,3,4,5)
(a,b,c,d,e)
Apple File Found
(test1,test2)
Orange File Found
(13,4,5)

Output2: Only banana files are present
$ ./test.sh 
Banana File Found
(1,2,3,4,5)
(a,b,c,d,e)
No APPLE files found
No Orange files found

【讨论】:

嗨湿婆,感谢您的回复。我明白了你的意思。如果文件符合问题,你的方法是正确的。在我的实际场景中,文件名是像 input_apple.log ,input_orange.log,input_banana.log 这样的字符串。每个文件模式都会被加载到分别对应的表(即香蕉、苹果、橙色)。有机会说,我一天都没有得到香蕉文件。那么我该如何处理 PIG 脚本中的那个? 另一种选择是,您可以为加载函数编写一个UDF,并在UDF内部处理异常。我从来没有尝试过UDF的加载功能,但你可以试一试。 谢谢西瓦。甚至我也决定采用您提到的方法。再次感谢您的讨论。 使用 shell 脚本更新了工作解决方案。我在本地测试了它的工作正常。

以上是关于在 PIG 中读取带有模式的文件的主要内容,如果未能解决你的问题,请参考以下文章

Pig:读取多个文件并逐列追加

如何在 Pig 中读取 csv 文件中的下一行

使用 pig 从 csv 文件中读取数据

csv 在 pig 中读取,csv 文件包含带引号的逗号

无法通过在 Azure HDInsight 中运行的 piggybank.jar 使用 PIG 读取 Avro 文件

通过 Apache Pig UDF 在 javascript 中读取文件