简体   繁体   中英

Strip non-printable characters using Hadoop Map-Reduce

I am trying to process a HDFS file which has non-printable chracters. I wish to strip these characters out using MapReduce.

I have tried using Pig TextLoader and MR TextInputFormat (IN MR program), and it results to split of a record into multiple from the position where it encounters a non-printable characters. Below is the sample data:

===Data==(2 records)=

 4614:2011-12-20-08.45.08.169176^2011-12-20-18.15.08.100008^597^0^57^ZUKA^Grase^^^Grase,Dr^^^N^N^N^Dr^KG^ONLY INFORMATION ENTERED^UNKNOWN^0     ^      ^^^611190362
�^0^^^^^^0^Grase,Dr^^^, ,^^^^^^597^^^<fnm>DR</fnm><lnm>GRASE</lnm>^^^^^^^^SINGLE^0^0
6063:2010-07-04-04.00.00.100001^2010-07-04-04.01.00.180144^017^0^095^WEETE    ^Wien^^^Wien,Colock^^^N^N^N^Colock^KG^ONLY INFORMATION ENTERED^UNKNOWN^0     ^      ^295111915^^������9905^0^^^^^^0^Wien,Colock^40001 KIN RD^300 CAMORE ST^500 BLACK AVE^Woesfield, HA, 43723.^John Ball^^^25719110^617^������9905^^<fnm>COLOCK</fnm><lnm>WIEN</lnm>^^^^^^^^SINGLE^0^0

[In less editor, the first record for column with special characters looks as:

611190362^M<EF><BF><BD> ]

In vi or less the first record comes in one line, but while reading in MR or pig this record gets splitted due to presence of these characters.

I want to avoid the record splitting into new line while reading data from HDFS and further wish to process these records to get rid of these special characters.

Here is what i have tried with basic UDF (snippet below). Though, the program is striping the charcters > 0x80 but performs stripping on splitted record.

Any help / pointers would be appreciated!!

        /*
     * 
     * Pig Code:
     * register '/basepath/udf/DIF.jar'
    rel1 = LOAD '/user/home/test' USING USING TextLoader();
    rel2 = FOREACH rel1 GENERATE StripNonPrintable(s) as recordline;
    dump rel2;

     * 
     */

  //Imports    

    public class StripNonPrintable extends EvalFunc<String>
    {
         public String exec(Tuple input) throws IOException {
             if (input == null || input.size() == 0)
                 return null;
             try{

                    String s = new String();
                     s = (String)input.get(0);
                    //s = "2001-12-20-08.45.08.169176^2001-12-20-08.45.08.131408^597^0^57^ZUCKA^Grase^^^Grase,Dr^^^N^N^N^Dr^KG^ONLY INFORMATION ENTERED^UNKNOWN^0     ^      ^^^6785790362�^0^^^^^^0^Grase,Dr^^^, ,^^^^^^597^^^<fnm>DR</fnm><lnm>GRASE</lnm>^^^^^^^^SINGLE^0^0";

                    int length = s.length();
                    char[] oldChars = new char[length];
                    s.getChars(0, length, oldChars, 0);
                    int newLen = 0;
                    for (int j = 0; j < length; j++) {
                        char ch = oldChars[j];
                        if (ch < 0x80  ) {
                            oldChars[newLen] = ch;
                            newLen++;
                        }
                    }
                    s = new String(oldChars, 0, newLen);

                    //System.out.println("New String = \n " + s);

                    return s;
             }catch(Exception e){
                 return null ;
             }
         }

     }

Package java.lang.Character . has a function getType which:

Returns a value indicating a character's general category

Import java.lang.Character and replace:

if (ch < 0x80  )

with following code:

int c = Character.getType(ch);
if(c != Character.CONTROL || 
            c != Character.CONNECTOR_PUNCTUATION || 
            c != Character.CURRENCY_SYMBOL || 
            c != Character.DASH_PUNCTUATION || 
            c != Character.DECIMAL_DIGIT_NUMBER || 
            c != Character.ENCLOSING_MARK || 
            c != Character.END_PUNCTUATION || 
            c != Character.FINAL_QUOTE_PUNCTUATION || 
            c != Character.INITIAL_QUOTE_PUNCTUATION || 
            c != Character.LETTER_NUMBER || 
            c != Character.LOWERCASE_LETTER || 
            c != Character.MATH_SYMBOL || 
            c != Character.MODIFIER_LETTER || 
            c != Character.MODIFIER_SYMBOL || 
            c != Character.OTHER_LETTER || 
            c != Character.OTHER_NUMBER || //remove it if you want to get rid of ½ 
            c != Character.OTHER_PUNCTUATION || 
            c != Character.OTHER_SYMBOL || 
            c != Character.START_PUNCTUATION || 
            c != Character.TITLECASE_LETTER || 
            c != Character.UPPERCASE_LETTER)

Use combinations of these, to remove characters you don't need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM