Google cloud dataflow 在读取之前解压缩数据流中的文件

Google cloud dataflow 在读取之前解压缩数据流中的文件,google-cloud-dataflow,Google Cloud Dataflow,我们的客户正在将文件上传到地面军事系统,但它们已经压缩。有没有办法,使用Java Dataflow SDK,我们可以运行所有压缩文件,解压文件,将所有生成的.csv文件合并成一个文件,然后只进行TextIO转换 编辑 为了回答jkffs的问题 我真的不需要将它们全部合并到一个文件中,从阅读的角度来看,这会容易得多 它们是ZIP文件,而不是GZ或BZ或其他任何文件。每个ZIP包含多个文件。文件名并不是很重要,是的,我更喜欢它TextIO透明地解压和连接所有文件,以每个存档为基础 希望有帮助 Dat

我们的客户正在将文件上传到地面军事系统,但它们已经压缩。有没有办法,使用Java Dataflow SDK,我们可以运行所有压缩文件,解压文件,将所有生成的.csv文件合并成一个文件,然后只进行
TextIO
转换

编辑

为了回答jkffs的问题

  • 我真的不需要将它们全部合并到一个文件中,从阅读的角度来看,这会容易得多
  • 它们是ZIP文件,而不是GZ或BZ或其他任何文件。每个ZIP包含多个文件。文件名并不是很重要,是的,我更喜欢它TextIO透明地解压和连接所有文件,以每个存档为基础
    希望有帮助

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


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

    ,因为我遇到了同样的问题,并且只找到了这个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";
            }
        }
    }
    
    公共类SimpleUnzip{
    私有静态最终记录器LOG=LoggerFactory.getLogger(SimpleUnzip.class);
    公共静态void main(字符串[]args){
    Pipeline p=Pipeline.create(
    PipelineOptionFactory.fromArgs(args).withValidation().create());
    GcsUtilFactory=新的GcsUtilFactory();
    GcsUtil util=factory.create(p.getOptions());
    试一试{
    List gcsPaths=util.expand(GcsPath.fromUri(“gs://tlogdataflow/test/*.zip”);
    列表路径=新的ArrayList();
    用于(GcsPath gcsp:gcsPaths){
    add(gcsp.toString());
    }
    p、 应用(创建路径)
    .应用(新的UnzipFN()的第1部分);
    p、 run();
    }
    捕获(例外e){
    LOG.error(例如getMessage());
    }
    }
    公共静态类UnzipFN扩展了DoFn{
    私有静态最终长serialVersionUID=2015166770614756341L;
    私有长文件解压缩=0;
    @凌驾
    公共void processElement(ProcessContext c){
    字符串p=c.element();
    GcsUtilFactory=新的GcsUtilFactory();
    GcsUtil u=factory.create(c.getPipelineOptions());
    字节[]缓冲区=新字节[100000000];
    试一试{
    seekablebytechnel sek=u.open(GcsPath.fromUri(p));
    InputStream is=通道。newInputStream(sek);
    BufferedInputStream bis=新的BufferedInputStream(is);
    ZipInputStream zis=新的ZipInputStream(bis);
    ZipEntry ze=zis.getNextEntry();
    while(ze!=null){
    info(“解压缩文件{}”,ze.getName());
    WritableByteChannel wri=u.create(GcsPath.fromUri(“gs://tlogdataflow/test/”+ze.getName()),getType(ze.getName());
    OutputStream os=Channels.newOutputStream(wri);
    内伦;
    而((len=zis.read(buffer))>0){
    写操作(缓冲区,0,len);
    }
    os.close();
    文件解压缩++;
    ze=zis.getnextery();
    }
    zis.closeEntry();
    zis.close();
    }
    捕获(例外e){
    e、 printStackTrace();
    }
    c、 输出(文件解压缩);
    }
    私有字符串getType(字符串fName){
    if(fName.endsWith(“.zip”)){
    返回“application/x-zip-compressed”;
    }
    否则{
    返回“文本/纯文本”;
    }
    }
    }
    

    }

    您能解释一下为什么要在进一步处理之前将所有.csv文件合并为一个文件吗?您需要按顺序而不是并行处理文件吗?在那之后有没有并行处理?另外,你能告诉我更多关于你的zip文件吗?它们真的是.zip还是.gz/.bz2?(TextIO目前支持gzip和bzip2压缩,但不支持.zip文件)如果是.zip文件,每个.zip文件中是有很多文件,还是只有一个?归档文件中的文件名是否重要?例如,如果TextIO透明地解压并连接zip存档中的所有文件,这对你有用吗?@jkff我用一些答案更新了这个问题!值得注意的是,这仅适用于Java库。到目前为止,Python库仍然只支持BZIP和GZIP2(),我在github上找不到任何与添加支持相关的pull请求。