我在hdfs的文件夹中有一堆.gz文件。我想将所有这些.gz文件解压缩到hdfs中的新文件夹。我该怎么做?
答案 0 :(得分:27)
我可以想到通过三种不同的方式实现它。
使用Linux命令行
以下命令对我有用。
hadoop fs -cat /tmp/Links.txt.gz | gzip -d | hadoop fs -put - /tmp/unzipped/Links.txt
我的gzip压缩文件是Links.txt.gz
输出存储在/tmp/unzipped/Links.txt
使用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>
例如当我执行我的gzip压缩文件时:
FileDecompressor /tmp/Links.txt.gz
我在位置/tmp/Links.txt
它将解压缩的文件存储在同一文件夹中。因此,您需要修改此代码以获取2个输入参数:<input file path> and <output folder>
。
一旦你使这个程序工作,你可以编写一个Shell / Perl / Python脚本来为你拥有的每个输入调用这个程序。
使用Pig脚本
您可以编写一个简单的Pig脚本来实现此目的。
我编写了以下脚本,该脚本有效:
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
。该文件夹将包含
/tmp/tmp_unzipped/_SUCCESS
/tmp/tmp_unzipped/part-m-00000
part-m-00000
包含解压缩文件。
因此,我们需要使用以下命令显式重命名它,最后删除/tmp/tmp_unzipped
文件夹:
mv /tmp/tmp_unzipped/part-m-00000 /tmp/unzipped/Links.txt
rm /tmp/tmp_unzipped/
因此,如果您使用此Pig脚本,则只需要注意参数化文件名(Links.txt.gz和Links.txt)。
同样,一旦你使这个脚本工作,你可以编写一个Shell / Perl / Python脚本来为你拥有的每个输入调用这个Pig脚本。
答案 1 :(得分:5)
在我的情况下,我不想管道解压缩文件,因为我不确定它们的内容。相反,我想确保将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 $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
目录hdfs
个文件
zip
复制到临时目录(在文件系统上)我设法使用/mypath/*/*.zip
使用sub-dir结构处理每个zip文件。
祝你好运:)
答案 2 :(得分:3)
如果您有压缩文本文件,hadoop fs -text支持gzip以及其他常见压缩格式(snappy,lzo)。
hadoop fs -text /tmp/a.gz | hadoop fs -put - /tmp/uncompressed_a
答案 3 :(得分:2)
您可以使用配置单元(假设它是文本数据)来执行此操作。
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>
答案 4 :(得分:0)
提供Scala代码
import org.apache.hadoop.fs.{FSDataOutputStream, FileSystem, FileUtil, Path}
import org.apache.hadoop.io.compress.{CompressionCodecFactory, CompressionInputStream}
import org.apache.spark.sql.SparkSession
import org.apache.hadoop.io.IOUtils
val conf = new org.apache.hadoop.conf.Configuration()
def extractFile (sparkSession: SparkSession, compath : String, uncompPath :String): String = {
val fs = FileSystem.get(sparkSession.sparkContext.hadoopConfiguration)
val inputPath = new Path(compath)
val factory = new CompressionCodecFactory(sparkSession.sparkContext.hadoopConfiguration);
val codec = factory.getCodec(inputPath)
if (codec == null){
throw new RuntimeException(s"Not a valid codex $codec")
}
var in : CompressionInputStream = null;
var out : FSDataOutputStream = null;
try {
in = codec.createInputStream(fs.open(inputPath));
out = fs.create(new Path(uncompPath));
IOUtils.copyBytes(in, out, conf);
} finally {
IOUtils.closeStream(in);
IOUtils.closeStream(out);
}
uncompPath
}
答案 5 :(得分:-1)