在阅读之前解压缩数据流中的文件

时间:2015-10-06 08:00:04

标签: google-cloud-dataflow

我们的客户正在将文件上传到GCS,但它们是压缩的。有没有办法,使用Java Dataflow SDK,我们可以在其中运行所有压缩文件,解压缩文件,将所有生成的.csv文件合并到一个文件中,然后只进行TextIO转换?

编辑

回答jkffs的问题,

  1. 我真的不需要将它们全部合并到一个文件中,从阅读的角度来看,它会更容易。
  2. 它们是ZIP文件,而不是GZ或BZ或其他任何内容。每个ZIP包含多个文件。文件名不是很重要,是的,我实际上更喜欢它TextIO透明地解压缩并连接所有文件,基于每个存档。
  3. 希望有所帮助!

2 个答案:

答案 0 :(得分:4)

因为我遇到了同样的问题,而且只是在这个1岁的时候才解决了这个问题。以下是有关如何在google dataflow上解压缩文件的完整示例:

public class SimpleUnzip {

private static final Logger LOG = LoggerFactory.getLogger(SimpleUnzip.class);

public static void main(String[] args){
    Pipeline p = Pipeline.create(
            PipelineOptionsFactory.fromArgs(args).withValidation().create());

    GcsUtilFactory factory = new GcsUtilFactory();
    GcsUtil util = factory.create(p.getOptions());
    try{
        List<GcsPath> gcsPaths = util.expand(GcsPath.fromUri("gs://tlogdataflow/test/*.zip"));
        List<String> paths = new ArrayList<String>();

        for(GcsPath gcsp: gcsPaths){
            paths.add(gcsp.toString());
        }
        p.apply(Create.of(paths))
            .apply(ParDo.of(new UnzipFN()));
        p.run();

        }
    catch(Exception e){
        LOG.error(e.getMessage());
        }


}

public static class UnzipFN extends DoFn<String,Long>{
    private static final long serialVersionUID = 2015166770614756341L;
    private long filesUnzipped=0;
    @Override
    public void processElement(ProcessContext c){
        String p = c.element();
        GcsUtilFactory factory = new GcsUtilFactory();
        GcsUtil u = factory.create(c.getPipelineOptions());
        byte[] buffer = new byte[100000000];
        try{
            SeekableByteChannel sek = u.open(GcsPath.fromUri(p));
            InputStream is = Channels.newInputStream(sek);
            BufferedInputStream bis = new BufferedInputStream(is);
            ZipInputStream zis = new ZipInputStream(bis);
            ZipEntry ze = zis.getNextEntry();
            while(ze!=null){
                LOG.info("Unzipping File {}",ze.getName());
                WritableByteChannel wri = u.create(GcsPath.fromUri("gs://tlogdataflow/test/" + ze.getName()), getType(ze.getName()));
                OutputStream os = Channels.newOutputStream(wri);
                int len;
                while((len=zis.read(buffer))>0){
                    os.write(buffer,0,len);
                }
                os.close();
                filesUnzipped++;
                ze=zis.getNextEntry();

            }
            zis.closeEntry();
            zis.close();

        }
        catch(Exception e){
            e.printStackTrace();
        }
    c.output(filesUnzipped);
    }

    private String getType(String fName){
        if(fName.endsWith(".zip")){
            return "application/x-zip-compressed";
        }
        else {
            return "text/plain";
        }
    }
}

}

答案 1 :(得分:1)

Dataflow / Apache Beam自动TextIO支持ZIP压缩文件:TextIO.read().from(filepattern)将根据文件扩展名自动解压缩与文件模式匹配的文件,.zip是受支持的格式之一 - 在这种情况下,它将隐式地将.zip内的所有文件连接成一个文件,并从中解析文本行。

如果文件没有扩展名,您还可以使用TextIO.read().from(filepattern).withCompressionType(...)明确指定压缩类型。