J'ai un tas de fichiers .gz dans un dossier en hdfs. Je veux décompresser tous ces fichiers .gz dans un nouveau dossier en hdfs. Comment dois-je procéder?
Je peux penser à y parvenir de 3 manières différentes.
en utilisant la ligne de commande Linux
La commande suivante a fonctionné pour moi.
hadoop fs -cat /tmp/Links.txt.gz | gzip -d | hadoop fs -put - /tmp/unzipped/Links.txt
Mon fichier compressé est Links.txt.gz
La sortie est stockée dans /tmp/unzipped/Links.txt
en utilisant Java
Dans Hadoop The Definitve Guide
book, il y a une section sur Codecs
. Dans cette section, il existe un programme pour décompresser la sortie à l'aide de CompressionCodecFactory
. Je reproduis ce code tel quel:
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);
}
}
}
Ce code prend le chemin du fichier gz en entrée.
Vous pouvez exécuter ceci comme:
FileDecompressor <gzipped file name>
Par exemple quand j'ai exécuté pour mon fichier compressé:
FileDecompressor /tmp/Links.txt.gz
J'ai obtenu le fichier décompressé à l'emplacement: /tmp/Links.txt
Il stocke le fichier décompressé dans le même dossier. Vous devez donc modifier ce code pour prendre 2 paramètres d'entrée: <input file path> and <output folder>
.
Une fois que ce programme fonctionne, vous pouvez écrire un script Shell/Perl/Python pour appeler ce programme pour chacune des entrées que vous avez.
en utilisant le script Pig
Vous pouvez écrire un simple script Pig pour y parvenir.
J'ai écrit le script suivant, qui fonctionne:
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/
Lorsque vous exécutez ce script, le contenu décompressé est stocké dans un dossier temporaire: /tmp/tmp_unzipped
. Ce dossier contiendra
/tmp/tmp_unzipped/_SUCCESS
/tmp/tmp_unzipped/part-m-00000
Le part-m-00000
contient le fichier décompressé.
Par conséquent, nous devons le renommer explicitement à l'aide de la commande suivante et enfin supprimer le /tmp/tmp_unzipped
dossier:
mv /tmp/tmp_unzipped/part-m-00000 /tmp/unzipped/Links.txt
rm /tmp/tmp_unzipped/
Donc, si vous utilisez ce script Pig, il vous suffit de prendre soin de paramétrer le nom du fichier (Links.txt.gz et Links.txt).
Encore une fois, une fois que ce script fonctionne, vous pouvez écrire un script Shell/Perl/Python pour appeler ce script Pig pour chacune des entrées que vous avez.
Dans mon cas, je ne voulais pas décompresser les fichiers car je n'étais pas sûr de leur contenu. Au lieu de cela, je voulais m'assurer que tous les fichiers dans les fichiers Zip seront placés extraits sur HDFS.
J'ai créé un simple script bash. Les commentaires devraient vous donner une idée de ce qui se passe. Il y a une courte description ci-dessous.
#!/bin/bash
workdir=/tmp/unziphdfs/
cd $workdir
# get all Zip files in a folder
zips=$(hadoop fs -ls /yourpath/*.Zip | awk '{print $8}')
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
*.Zip
fichiers dans un répertoire hdfs
Zip
dans un répertoire temporaire (sur le système de fichiers)J'ai réussi à le faire fonctionner avec une structure de sous-répertoires pour de nombreux fichiers Zip dans chacun, en utilisant /mypath/*/*.Zip
.
Bonne chance:)
Si vous avez des fichiers texte compressés, hadoop fs -text prend en charge gzip ainsi que d'autres formats de compression courants (snappy, lzo).
hadoop fs -text /tmp/a.gz | hadoop fs -put - /tmp/uncompressed_a
Vous pouvez le faire en utilisant Hive (en supposant qu'il s'agit de données texte).
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;
Les données seront décompressées dans un nouvel ensemble de fichiers.
si vous ne souhaitez pas modifier les noms et si vous disposez de suffisamment d'espace de stockage sur le nœud sur lequel vous exécutez, vous pouvez le faire.
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>