Как распаковать.файлы gz в новом каталоге в hadoop?

У меня куча .GZ файлы в папке в hdfs. Я хочу расстегнуть все это .GZ файлы в новую папку в hdfs. Как мне это сделать?

5 ответов


я могу думать о достижении этого через 3 разных способа.

  1. использование командной строки Linux

    следующая команда работала на меня.

    hadoop fs -cat /tmp/Links.txt.gz | gzip -d | hadoop fs -put - /tmp/unzipped/Links.txt
    

    мой gzipped файл Links.txt.gz
    Вывод сохраняется в /tmp/unzipped/Links.txt

  2. использование программы Java

    на Hadoop The Definitve Guide книги, там есть раздел Codecs. В этом разделе есть программа для Распакуйте вывод с помощью CompressionCodecFactory. Я воссоздаю этот код как есть:

    package com.myorg.hadooptests;
    
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.FileSystem;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.io.IOUtils;
    import org.apache.hadoop.io.compress.CompressionCodec;
    import org.apache.hadoop.io.compress.CompressionCodecFactory;
    
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.net.URI;
    
    public class FileDecompressor {
        public static void main(String[] args) throws Exception {
            String uri = args[0];
            Configuration conf = new Configuration();
            FileSystem fs = FileSystem.get(URI.create(uri), conf);
            Path inputPath = new Path(uri);
            CompressionCodecFactory factory = new CompressionCodecFactory(conf);
            CompressionCodec codec = factory.getCodec(inputPath);
            if (codec == null) {
                System.err.println("No codec found for " + uri);
                System.exit(1);
            }
            String outputUri =
            CompressionCodecFactory.removeSuffix(uri, codec.getDefaultExtension());
            InputStream in = null;
            OutputStream out = null;
            try {
                in = codec.createInputStream(fs.open(inputPath));
                out = fs.create(new Path(outputUri));
                IOUtils.copyBytes(in, out, conf);
            } finally {
                IOUtils.closeStream(in);
                IOUtils.closeStream(out);
            }
        }
    }
    

    этот код принимает путь файла gz в качестве входных данных.
    Вы можете выполнить это:

    FileDecompressor <gzipped file name>
    

    например, когда я выполнял для своего файла gzipped:

    FileDecompressor /tmp/Links.txt.gz
    

    я получил распакованный файл в месте:/tmp/Links.txt

    он хранит распакованный файл в той же папке. Поэтому вам нужно изменить этот код, чтобы принять 2 входных параметра:<input file path> and <output folder>.

    после того, как вы чтобы эта программа работала, вы можете написать сценарий Shell/Perl/Python для вызова этой программы для каждого из ваших входов.

  3. использование сценария свиньи

    вы можете написать простой скрипт Свиньи для достижения этого.

    я написал следующий скрипт, который работает:

    A = LOAD '/tmp/Links.txt.gz' USING PigStorage();
    Store A into '/tmp/tmp_unzipped/' USING PigStorage();
    mv /tmp/tmp_unzipped/part-m-00000 /tmp/unzipped/Links.txt
    rm /tmp/tmp_unzipped/
    

    при запуске этого скрипта распакованное содержимое сохраняется во временной папке:/tmp/tmp_unzipped. Эта папка будет contain

    /tmp/tmp_unzipped/_SUCCESS
    /tmp/tmp_unzipped/part-m-00000
    

    на part-m-00000 содержит распакованный файл.

    следовательно, нам надо явно переименовать его, используя следующую команду и, наконец, удалить :

    mv /tmp/tmp_unzipped/part-m-00000 /tmp/unzipped/Links.txt
    rm /tmp/tmp_unzipped/
    

    Итак, если вы используете этот скрипт Pig, вам просто нужно позаботиться о параметризации имени файла (ссылки.формат txt.gz и ссылки.формат txt.)

    опять же, как только вы получите этот скрипт, вы можете написать сценарий оболочки/Perl/Python, чтобы вызвать этот скрипт Свиньи для каждого из входы у вас есть.


Bash решение

в моем случае я не хотел распаковывать файлы, так как я не был уверен в их содержимом. Вместо этого я хотел убедиться, что все файлы в zip-файлах будут извлечены на HDFS.

Я создал простой скрипт на bash. Комментарии должны дать вам ключ к пониманию того, что происходит. Ниже приводится краткое описание.

#!/bin/bash

workdir=/tmp/unziphdfs/
cd $workdir

# get all zip files in a folder
zips=$(hadoop fs -ls /yourpath/*.zip | awk '{print }')
for hdfsfile in $zips
do
    echo $hdfsfile

    # copy to temp folder to unpack
    hdfs dfs -copyToLocal $hdfsfile $workdir

    hdfsdir=$(dirname "$hdfsfile")
    zipname=$(basename "$hdfsfile")

    # unpack locally and remove
    unzip $zipname
    rm -rf $zipname

    # copy files back to hdfs
    files=$(ls $workdir)
    for file in $files; do
       hdfs dfs -copyFromLocal $file $hdfsdir
       rm -rf $file
    done

    # optionally remove the zip file from hdfs?
    # hadoop fs -rm -skipTrash $hdfsfile
done

описание

  1. показать все *.zip файлы hdfs реж.--16-->
  2. один-на-один: скопировать zip в temp dir (в файловой системе)
  3. распакуйте
  4. скопировать все извлеченные файлы в каталог zip-архив
  5. очистка

мне удалось заставить его работать со структурой sub-dir для многих zip-файлов в каждом, используя /mypath/*/*.zip.

удачи :)


если у вас есть сжатые текстовые файлы, hadoop fs-text поддерживает gzip наряду с другими распространенными форматами сжатия (snappy, lzo).

hadoop fs -text /tmp/a.gz | hadoop fs -put - /tmp/uncompressed_a

вы можете сделать это с помощью hive (предполагая, что это текстовые данные).

create external table source (t str) location '<directory_with_gz_files>';
create external table target (t str) location '<target_dir>';
insert into table target select * from source;

данные будут распакованы в новый набор файлов.

Если вы не хотите изменять имена и если у вас достаточно памяти на узле, где вы работаете, вы можете сделать это.

hadoop fs -get <your_source_directory> <directory_name>
It will create a directory where you run hadoop command. cd to it and gunzip all the files
cd ..
hadoop fs -moveFromLocal <directory_name> <target_hdfs_path>

Hadoop на базе FileUtil класс unTar() и unZip() методы для достижения этого. The unTar() метод будет работать на .tar.gz и .tgz файлов, а также. К сожалению, они работают только с файлами в локальной файловой системе. Вам придется использовать один из того же класса copy() методы копирования В и из любых распределенных файловых систем, которые необходимо использовать.