精华内容
下载资源
问答
  • 常用几种文件封装格式

    千次阅读 2016-12-30 15:33:10
    所谓文件封装格式也称多媒体容器(Multimedia Container),与DivX、MP3这类编码格式不同的是,它只是为多媒体编码提供了一个“外壳”,也就是将所有的处理好的视频、音频都包装到一个文件容器内呈现给观众,这个...

    什么是封装格式?

    所谓文件封装格式也称多媒体容器(Multimedia Container),与DivX、MP3这类编码格式不同的是,它只是为多媒体编码提供了一个“外壳”,也就是将所有的处理好的视频、音频都包装到一个文件容器内呈现给观众,这个包装的过程就叫封装。

    DVD是将标准清晰度的MPEG2视频文件封装到VOB文件内,Blu-ray是将H264等编码的高清晰度视频文件封装到M2T文件内,HDTV是将高清晰度视频文件封装到TS文件内。不同的厂家都有自己的封装文件格式,常见的封装格式有:TS、AVI、MKV、TP、MOV、M2T等等,它们与编码类型没有必然联系。不同的封装方式就好比是不同的盒子,高清视频要用它装起来才能呈现给观众。


    1.AVI——Audio Video Interleave

    即音频视频交叉存取格式。1992年初Microsoft公司推出了AVI技术及其应用软件VFW(Video forWindows)。在AVI文件中,运动图像和伴音数据是以交织的方式存储,并独立于硬件设备。这种按交替方式组织音频和视像数据的方式可使得读取视频数据流时能更有效地从存储媒介得到连续的信息。所有的AVI文件都包括两个必须的List块。这些块定义了流和数据流的格式。AVI文件可能还包括一个索引块。只要遵循这个标准,任何视频编码方案都可以使用在AVI文件中。avi封装目前仅仅能支持如下编码方式生成的文件:Videocodecs、MPEG-4 AVC、SMPTE VC-1(对其支持不够好)、Audio codecs、DTS、AC3。

        AVI的文件结构、分为头部,主体和索引三部分. 主体中图像数据和声音数据是交互存放的。从尾部的索引可以索引跳到自己想放的位置。A VI中图像和声音是分开的,所以播放时需要一个图像和声音的同步过程,AVI本身只是提供了这么一个框架,内部的图像数据和声音顺据格式可以是任意的编码形式。但是由于索引放在了文件尾部,所以在播放internet流媒体时已属力不从心。

    当前几种主流高清编码方式和文件封装格式介绍

    2.TS流

        TS流封装是随着MPEG2的流行而占据了主流的地位。全称则是TransportStream。而电视节目是你任何时候打开电视机都能解码(收看)的,所以,MPEG2-TS格式的特点就是要求从视频流的任一片段开始都是可以独立解码的。从结构上来说,TS流是由头文件和主体所组成的,扩充过的TS流还包括时间戳。这样不管是什么格式的VBR音轨,都很容易通过时间戳来同步图像。这样就不会产生AVI格式的音像同步问题,

      当然,对新的声音格式来说,需要新的分离器,解码器来实现解码。目前在不断改进开发中。

      TS流不像AVI,从诞生那天起,就考虑到了网络播放,所以很快成为了世界标准并广泛应用于电视台数字播放,手机等各个领域。

    当前几种主流高清编码方式和文件封装格式介绍

     

        用TS流封装可以无损的支持所有全部HDDVD和BD所带的视频和音频编码,包括:

        Videocodecs、MPEG-2、MPEG-4 AVC、SMPTE VC-1、Audio codecs、Linear PCM、DolbyDigital、Dolby Digital Plus、Dolby TrueHD、DTS DigitalSurround、DTS-HD


    3.MKV


        MKV是Matroska的一种媒体文件,是一种新的多媒体封装格式。Matroska最大的特点就是能容纳多种不同类型编码的视频.音频及字幕流,即使是非常封闭的RealMedia及QuickTime也被它包括进去了,并将它们的音视频进行了重新组织来达到更好的效果。Matroska它可将多种不同编码的视频及16条以上不同格式的音频和不同语言的字幕流封装到一个MatroskaMedia文件当中! 因此,MKV也称多媒体容器(MultimediaContainer),:具有良好的开放性和跨平台性,是H.264编码最重要的封装格式。Matroska定义了三种类型的文件:MKV是视频文件,它里面可能还包含有音频和字幕;MKA是单一的音频文件,但可能有多条及多种类型的音轨;MKS是字幕文件。这三种文件以MKV最为常见。

        MKV采用了可变帧率,在回放变化比较慢(比如说静物)时以比较低的FPS来代替,可以节省不少资源;MKV与AVI和TS相比还增加了错误检测以及修复,这无疑提供了纠错和容错性,更适合于网络传输;在字幕方面,还增加了软字幕功能。与DVDrip以及HDrip等,字幕是以其它文件形式存在不同的是,在MKV里字幕可以内嵌在封装里,但不会和视频混淆,也可以多字幕随意选择;这样在传输保存时更为方便。在传输上采用的是流式传输,这点和TS流的原因基本一致,可以通过时间戳来管理视频以及音频的同步问题,做到即下即看;

    plus:

    硬字幕:
    也称“内嵌字幕”,把字幕文件和视频流压制在同一组数据里,像水印一样,无法分离。特点是兼容性好,对一些播放器无需字幕插件需求;缺点是,修正难度大,一旦出错必须
    整个视频文件重新制作,因为无法分离,限制了用户对字体风格个人喜好的修改
    软字幕:
    也称“外挂字幕”,把字幕文件单独保存为ASS,SSASUB格式,只需与视频文件名相同,播放时自动调用,也可用MKV进行封装;缺点是,需要字幕插件支持,一些播放器在某
    些配置下无法渲染;优点是,修正便捷,可以随意修改字体风格等

    4.MOV

        MOV封装即QuickTime影片格式,它是Apple公司开发的一种音频、视频文件格式,用于存储常用数字媒体类型,如音频和视频。当选择QuickTime (*.mov)作为“保存类型”时,动画将保存为 .mov文件。现在MOV格式常常被用来制作高清电影预告片,可以达到1080P的所谓全高清标准。

        MOV又是一个发展很快的多媒体封装形式,它具有很多优越性。它可称为万能封装器,连多条字幕文件都可以封装进去。同时,MOV还具有良好的兼容性、跨平台性、纠错性,所要求的存储空间小等技术特点。到目前为止,它共有4 个版本,其中以 4.0 版本的压缩率最好。这种编码支持16位图像深度的帧内压缩和帧间压缩,帧率每秒10帧以上。

        但由于MOV没有什么商业背景,几乎只活跃在PC平台上,尽管其功能丰富,但在商业应用中则毫无建树。

     

    5. AVI和TS封装格式的细节对比

     

    兼容的视频编码

    兼容的音频编码

    扩充性

    Internet适应性

    AVI封装

    MPEG-2

    Linear PCM

     

    MPEG-4 H.264

    Dolby Digital

     

     

     

    VC-1

    Dolby Digital Plus

     

     

     

     

    Dolby True HD

     

     

     

     

    DTS Digital Surround

     

     

     

     

     

     

     

    TS 封装

    MPEG-4

    DTS HD DTS

     

    VC-1(支持效果不太好)

    AC3

     

     

     






    展开全文
  • 程序的几种常用格式文件

    千次阅读 2017-10-20 10:08:36
    什么函数 ,以及这些 函数的接口都是什么样子 的,lib有利于程序的模块化,另外开发者不愿公开的源代码可以用lib的形式进行一定的保护(起码反汇编是件很蛋疼的事情)。 四(附)lib文件严格意义上讲叫静态库...
    int global;
    int calculate()
     {    
        int a,b,c;    
         b=1;    
        return c;
     }
     int main()  
     {    
         calculate();    
     }

    一、编译把每个函数翻译成可以运行的机器指令,但其中调用的函数和全局变量因为还没有分配具体的物理地址,所以会先保留其符号,main函数编译后的大致内容如下:
    命令0:将内核寄存器的值压栈保存;
    命令1:把global这个全局变量的值赋1;
    命令2:程序跳转至函数calculate;
    命令3:出栈恢复main调用者的寄存器状态,并把返回值0写入指定的寄存器中;
    命令4:返回;

    calculate函数编译后大致内容如下:
    命令0:将内核寄存器的值压栈保存,为局部变量a、b、c分配三个寄存器用以存放其数值;
    命令1:变量a置1;
    命令2:变量b置1;
    命令3:计算a+b,并把计算结果赋给c;
    命令4:出栈恢复calculate调用者的寄存器状态,并把返回值c写入指定的寄存器中;
    命令5:返回;

    二、链接为所有的函数和全局变量分配一个实际的物理地址,并把编译过程中没有确定的函数和变量替换为具体的物理地址,例如可以:
    把函数main的首地址安排在0x0地址上,把calculate函数的首地址安排在0x40地址上,把全局变量global安排在0x80地址上,这样main函数编译完后的命令1和命令2可以进一步改写为:
    命令1(改):把地址0x80的存储内容置1;
    命令2(改):程序跳转至0x40继续执行;

    三、h文件头文件,
    本身是不包含程序的,它的意义在于告诉要从其他.c文件调用函数的人,他所用的函数的结构是什么样子的(当然还可以定义宏、结构体等),就是一个函数的接口声明。
    比如开发者完成main.c后,可以写一个main.h来告诉想调用main.c中函数的人,其函数结构是什么样子的。

    四、lib文件库文件,
    就是编译后,未链接的代码的集合,供其他开发者调用,通过匹配的h文件来告知开发者lib文件都有什么函数,以及这些函数的接口都是什么样子的,lib有利于程序的模块化,另外开发者不愿公开的源代码可以用lib的形式进行一定的保护(起码反汇编是件很蛋疼的事情)。

    四(附)lib文件严格意义上讲叫静态库文件,所有的代码最终会在链接完成后整合成可执行文件(如.exe、.bin),但执行文件一旦生成,就与库文件没有关系了;大家可以理解为lib是房屋设计图,执行文件就是盖好的房子,房子不会因为设计图的遗失而倒塌。

    五、dll文件动态链接库,
    是pc中用到的,它和lib类似,也是存放函数机器码的库,但不同的是调用dll内函数的执行文件本身不包含这些函数的内容,当执行到相关的函数时,必须定位对应dll文件,将相关函数内容装载到内存中再运行;就像家里要炒个青菜,锅碗调盆都准备完了,但每次烧之前要把青菜先买回来,才能开炒。

    六、o文件就是编译完后的c文件,就是一过渡文件,对编译原理不深究的人不必过多深入了解。

    作者:知乎用户
    链接:https://www.zhihu.com/question/20783462/answer/136827566
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    展开全文
  • 读写parquet格式文件几种方式

    万次阅读 2017-07-25 14:28:03
    本文将介绍常用parquet文件读写的几种方式 1.用spark的hadoopFile api读取hive中的parquet格式文件 2.用sparkSql读写hive中的parquet格式 3.用新旧MapReduce读写parquet格式文件 读parquet文件 首先创建hive表...

    摘要

    本文将介绍常用parquet文件读写的几种方式

    1.用spark的hadoopFile api读取hive中的parquet格式文件

    2.用sparkSql读写hive中的parquet格式

    3.用新旧MapReduce读写parquet格式文件

    读parquet文件

    首先创建hive表,数据用tab分隔

     

    create table test(name string,age int) 
     row format delimited
     fields terminated by '\t';


    加载数据

     

     

    load data local inpath '/home/work/test/ddd.txt' into table test;

     

    数据样例格式:

    hive> select * from test limit 5; 
    OK
    leo 27
    jim 38
    leo 15
    jack    22
    jay 7
    Time taken: 0.101 seconds, Fetched: 5 row(s)
    创建parquet格式表
    create table test_parquet(name string,age int) stored as parquet

    查看表结构
    hive> show create table test_parquet;
    OK
    CREATE TABLE `test_parquet`(
      `name` string, 
      `age` int)
    ROW FORMAT SERDE 
      'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
    STORED AS INPUTFORMAT 
      'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
    OUTPUTFORMAT 
      'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
    LOCATION
      'hdfs://localhost:9000/user/hive/warehouse/test_parquet'
    TBLPROPERTIES (
      'transient_lastDdlTime'='1495038003')
    可以看到数据的inputFormat是MapredParquetInputFormat,之后我们将用这个类来解析数据文件

    往parquet格式表中插入数据

     

    insert into table test_parquet select * from test;

     

    a.用spark中hadoopFile api解析hive中parquet格式文件

    如果是用spark-shell中方式读取文件一定要将hive-exec-0.14.0.jar加入到启动命令行中(MapredParquetInputFormat在这个jar中),还有就是要指定序列化的类,启动命令行如下

     

    spark-shell --master spark://xiaobin:7077 --jars /home/xiaobin/soft/apache-hive-0.14.0-bin/lib/hive-exec-0.14.0.jar
       --conf spark.serializer=org.apache.spark.serializer.KryoSerializer


    具体读取代码如下

     

     

    scala> import org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat
    import org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat
     
    scala> import org.apache.hadoop.io.{ArrayWritable, NullWritable, Text}
    import org.apache.hadoop.io.{ArrayWritable, NullWritable, Text}
     
    scala>     val file =sc.hadoopFile("hdfs://localhost:9000/user/hive/warehouse/test_parquet/000000_0",
         |       classOf[MapredParquetInputFormat],classOf[Void],classOf[ArrayWritable])
    file: org.apache.spark.rdd.RDD[(Void, org.apache.hadoop.io.ArrayWritable)] =
          hdfs://localhost:9000/user/hive/warehouse/test_parquet/000000_0 HadoopRDD[0] at hadoopFile at <console>:29
    
    scala> file.take(10).foreach{case(k,v)=>
         |       val writables = v.get()
         |       val name = writables(0)
         |       val age = writables(1)
         |       println(writables.length+"    "+name+"   "+age)
         |     }

     

     

    用MapredParquetInputFormat解析hive中parquet格式文件,每行数据将会解析成一个key和value,这里的key是空值,value是一个ArrayWritable,value的长度和表的列个数一样,value各个元素对应hive表中行各个字段的值

    b.用spark DataFrame 解析parquet文件

     

    val conf = new SparkConf().setAppName("test").setMaster("local")
    val sc = new SparkContext(conf)
    val sqlContext = new org.apache.spark.sql.SQLContext(sc)
    val parquet: DataFrame =
         sqlContext.read.parquet("hdfs://192.168.1.115:9000/user/hive/warehouse/test_parquet")
    parquet.printSchema()
    parquet.select(parquet("name"), parquet("age") + 1).show()
     
    root
     |-- name: string (nullable = true)
     |-- age: integer (nullable = true)
     
    +----+---------+
    |name|(age + 1)|
    +----+---------+
    | leo|       28|
    | jim|       39|
    | leo|       16|
    |jack|       23|
    | jay|        8|
    | jim|       38|
    |jack|       37|
    | jay|       12|


    c.用hivesql直接读取hive表

     

    在local模式下没有测试成功,打包用spark-submit测试,代码如下

     

    val conf = new SparkConf().setAppName("test")
    val sc = new SparkContext(conf)
    val hiveContext = new HiveContext(sc)
    val sql: DataFrame = hiveContext.sql("select * from test_parquet limit 10")
    sql.take(10).foreach(println)
     
    [leo,27]                                                                        
    [jim,38]
    [leo,15]
    [jack,22]
    [jay,7]
    [jim,37]
    [jack,36]
    [jay,11]
    [leo,35]
    [leo,33]


    提交任务命令行

     

     

    spark-submit --class quickspark.QuickSpark02 --master spark://192.168.1.115:7077 sparkcore-1.0-SNAPSHOT.jar

     

    写parquet文件

    a.用spark写parquet文件

     

    val conf = new SparkConf().setAppName("test").setMaster("local")
    val sc = new SparkContext(conf)
    val sqlContext = new org.apache.spark.sql.SQLContext(sc)
     
    //    读取文件生成RDD
    val file = sc.textFile("hdfs://192.168.1.115:9000/test/user.txt")
     
     //定义parquet的schema,数据字段和数据类型需要和hive表中的字段和数据类型相同,否则hive表无法解析
    val schema = (new StructType)
          .add("name", StringType, true)
          .add("age", IntegerType, false)
     
    val rowRDD = file.map(_.split("\t")).map(p => Row(p(0), Integer.valueOf(p(1).trim)))
    //    将RDD装换成DataFrame
    val peopleDataFrame = sqlContext.createDataFrame(rowRDD, schema)
    peopleDataFrame.registerTempTable("people")
        peopleDataFrame.write.parquet("hdfs://192.168.1.115:9000/user/hive/warehouse/test_parquet/")

     

    用hivesql读取用spark DataFrame生成的parquet文件

     

    hive> select * from test_parquet limit 10;
    OK
    SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
    SLF4J: Defaulting to no-operation (NOP) logger implementation
    SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
    leo 27
    jim 38
    leo 15
    jack    22
    jay 7
    jim 37
    jack    36
    jay 11
    leo 35
    leo 33

     

     

    b.用MapReduce写parquet文件

    用MR读写parquet文件,刚开始打算使用hive中指定的org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat这个类,但是这个类的getRecordWriter方法没实现,直接抛出异常

     

    @Override
    public RecordWriter<Void, ArrayWritable> getRecordWriter(
        final FileSystem ignored,
        final JobConf job,
        final String name,
        final Progressable progress
        ) throws IOException {
      throw new RuntimeException("Should never be used");
    }

     

    所以使用官方提供的parquet解析方式,github地址:https://github.com/apache/parquet-mr/,导入依赖

     

    <dependency>
                    <groupId>org.apache.parquet</groupId>
                    <artifactId>parquet-common</artifactId>
                    <version>1.8.1</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.parquet</groupId>
                    <artifactId>parquet-encoding</artifactId>
                    <version>1.8.1</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.parquet</groupId>
                    <artifactId>parquet-column</artifactId>
                    <version>1.8.1</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.parquet</groupId>
                    <artifactId>parquet-hadoop</artifactId>
                    <version>1.8.1</version>
                </dependency>

     

     

    Parquet读写有新旧两个版本,主要是新旧MR api之分,我们用新旧老版本的MR实现下parquet文件的读写

    旧版本如下

     

    package com.fan.hadoop.parquet;
     
    import java.io.IOException;
    import java.util.*;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.io.*;
    import org.apache.hadoop.mapred.*;
    import org.apache.parquet.hadoop.example.GroupWriteSupport;
    import org.apache.parquet.example.data.Group;
    import org.apache.parquet.example.data.simple.SimpleGroupFactory;
    import org.apache.parquet.hadoop.mapred.DeprecatedParquetOutputFormat;
    import org.apache.parquet.schema.MessageTypeParser;
    /**
     * Created by fanlegefan.com on 17-7-17.
     */
    public class ParquetMR {
     
        public static class Map extends MapReduceBase implements
                Mapper<LongWritable, Text, Text, IntWritable> {
     
            private final static IntWritable one = new IntWritable(1);
            private Text word = new Text();
     
            public void map(LongWritable key, Text value,
                            OutputCollector<Text, IntWritable> output,
                                Reporter reporter) throws IOException {
                String line = value.toString();
                StringTokenizer tokenizer = new StringTokenizer(line);
                while (tokenizer.hasMoreTokens()) {
                    word.set(tokenizer.nextToken());
                    output.collect(word, one);
                }
            }
        }
     
        public static class Reduce extends MapReduceBase implements
                Reducer<Text, IntWritable, Void, Group> {
            private SimpleGroupFactory factory;
            public void reduce(Text key, Iterator<IntWritable> values,
                               OutputCollector<Void, Group> output,
                               Reporter reporter) throws IOException {
                int sum = 0;
                while (values.hasNext()) {
                    sum += values.next().get();
                }
     
                Group group = factory.newGroup()
                        .append("name",  key.toString())
                        .append("age", sum);
                output.collect(null,group);
            }
     
            @Override
            public void configure(JobConf job) {
                factory = new SimpleGroupFactory(GroupWriteSupport.getSchema(job));
            }
        }
     
        public static void main(String[] args) throws Exception {
            JobConf conf = new JobConf(ParquetMR.class);
            conf.setJobName("wordcount");
     
            String in = "hdfs://localhost:9000/test/wordcount.txt";
            String out = "hdfs://localhost:9000/test/wd";
     
     
            String writeSchema = "message example {\n" +
                    "required binary name;\n" +
                    "required int32 age;\n" +
                    "}";
     
            conf.setMapOutputKeyClass(Text.class);
            conf.setMapOutputValueClass(IntWritable.class);
     
            conf.setOutputKeyClass(NullWritable.class);
            conf.setOutputValueClass(Group.class);
     
            conf.setMapperClass(Map.class);
            conf.setReducerClass(Reduce.class);
     
            conf.setInputFormat(TextInputFormat.class);
            conf.setOutputFormat(DeprecatedParquetOutputFormat.class);
     
            FileInputFormat.setInputPaths(conf, new Path(in));
            DeprecatedParquetOutputFormat.setWriteSupportClass(conf, GroupWriteSupport.class);
            GroupWriteSupport.setSchema(MessageTypeParser.parseMessageType(writeSchema), conf);
     
            DeprecatedParquetOutputFormat.setOutputPath(conf, new Path(out));
     
            JobClient.runJob(conf);
        }
     
    }


    生成的文件:

     

     

    hadoop dfs -ls /test/wd
    Found 2 items
    -rw-r--r--   3 work supergroup          0 2017-07-18 17:41 /test/wd/_SUCCESS
    -rw-r--r--   3 work supergroup        392 2017-07-18 17:41 /test/wd/part-00000-r-00000.parquet

     

    将生成的文件复制到hive表test_parquet的路径下:

     

    hadoop dfs -cp /test/wd/part-00000-r-00000.parquet /user/work/warehouse/test_parquet/

     

    测试hive表读取parquet文件

     

    hive> select * from test_parquet limit 10;
    OK
    action  2
    hadoop  2
    hello   3
    in  2
    presto  1
    spark   1
    world   1
    Time taken: 0.056 seconds, Fetched: 7 row(s)

     

    新版本如下

    新版本的MR读写Parquet和老版本有点区别,schema必须用在conf中设置,其他的区别不大

     

    conf.set("parquet.example.schema",writeSchema);

     

     

    还是贴下完整的代码

     

    package com.fan.hadoop.parquet;
     
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.io.IntWritable;
    import org.apache.hadoop.io.LongWritable;
    import org.apache.hadoop.io.Text;
    import org.apache.hadoop.mapreduce.Job;
    import org.apache.hadoop.mapreduce.Mapper;
    import org.apache.hadoop.mapreduce.Reducer;
    import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
    import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
    import org.apache.parquet.example.data.Group;
    import org.apache.parquet.example.data.simple.SimpleGroupFactory;
    import org.apache.parquet.hadoop.ParquetOutputFormat;
    import org.apache.parquet.hadoop.example.GroupWriteSupport;
    import java.io.IOException;
    import java.util.StringTokenizer;
     
    /**
     * Created by fanglegefan.com on 17-7-18.
     */
    public class ParquetNewMR {
     
        public static class WordCountMap extends
                Mapper<LongWritable, Text, Text, IntWritable> {
     
            private final IntWritable one = new IntWritable(1);
            private Text word = new Text();
     
            public void map(LongWritable key, Text value, Context context)
                    throws IOException, InterruptedException {
                String line = value.toString();
                StringTokenizer token = new StringTokenizer(line);
                while (token.hasMoreTokens()) {
                    word.set(token.nextToken());
                    context.write(word, one);
                }
            }
        }
     
        public static class WordCountReduce extends
                Reducer<Text, IntWritable, Void, Group> {
            private SimpleGroupFactory factory;
     
            public void reduce(Text key, Iterable<IntWritable> values,
                               Context context) throws IOException, InterruptedException {
                int sum = 0;
                for (IntWritable val : values) {
                    sum += val.get();
                }
                Group group = factory.newGroup()
                        .append("name",  key.toString())
                        .append("age", sum);
                context.write(null,group);
            }
     
            @Override
            protected void setup(Context context) throws IOException, InterruptedException {
                super.setup(context);
                factory = new SimpleGroupFactory(GroupWriteSupport.getSchema(context.getConfiguration()));
     
            }
        }
     
        public static void main(String[] args) throws Exception {
            Configuration conf = new Configuration();
            String writeSchema = "message example {\n" +
                    "required binary name;\n" +
                    "required int32 age;\n" +
                    "}";
            conf.set("parquet.example.schema",writeSchema);
     
            Job job = new Job(conf);
            job.setJarByClass(ParquetNewMR.class);
            job.setJobName("parquet");
     
            String in = "hdfs://localhost:9000/test/wordcount.txt";
            String out = "hdfs://localhost:9000/test/wd1";
     
            job.setMapOutputKeyClass(Text.class);
            job.setMapOutputValueClass(IntWritable.class);
     
            job.setOutputValueClass(Group.class);
     
            job.setMapperClass(WordCountMap.class);
            job.setReducerClass(WordCountReduce.class);
     
            job.setInputFormatClass(TextInputFormat.class);
            job.setOutputFormatClass(ParquetOutputFormat.class);
     
            FileInputFormat.addInputPath(job, new Path(in));
            ParquetOutputFormat.setOutputPath(job, new Path(out));
            ParquetOutputFormat.setWriteSupportClass(job, GroupWriteSupport.class);
     
            job.waitForCompletion(true);
        }
    }

     

     

    查看生成的文件

     

    hadoop dfs -ls /user/work/warehouse/test_parquet
     
    Found 4 items
    -rw-r--r--   1 work work          0 2017-07-18 18:27 /user/work/warehouse/test_parquet/_SUCCESS
    -rw-r--r--   1 work work        129 2017-07-18 18:27 /user/work/warehouse/test_parquet/_common_metadata
    -rw-r--r--   1 work work        275 2017-07-18 18:27 /user/work/warehouse/test_parquet/_metadata
    -rw-r--r--   1 work work        392 2017-07-18 18:27 /user/work/warehouse/test_parquet/part-r-00000.parquet

     

    将生成的文件复制到hive表test_parquet的路径下:

     

    hadoop dfs -cp /test/wd/part-00000-r-00000.parquet /user/work/warehouse/test_parquet/


    测试hive

     

     

    hive> select name,age from test_parquet limit 10;
    OK
    action  2
    hadoop  2
    hello   3
    in  2
    presto  1
    spark   1
    world   1
    Time taken: 0.036 seconds, Fetched: 7 row(s)

     

     

     

    用mapreduce读parquet文件

     

    package com.fan.hadoop.parquet;
     
    import org.apache.hadoop.conf.Configuration;
    import org.apache.hadoop.fs.Path;
    import org.apache.hadoop.io.LongWritable;
    import org.apache.hadoop.io.Text;
    import org.apache.hadoop.mapreduce.Job;
    import org.apache.hadoop.mapreduce.Mapper;
    import org.apache.hadoop.mapreduce.Reducer;
    import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
    import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
    import org.apache.parquet.example.data.Group;
    import org.apache.parquet.hadoop.ParquetInputFormat;
    import org.apache.parquet.hadoop.api.DelegatingReadSupport;
    import org.apache.parquet.hadoop.api.InitContext;
    import org.apache.parquet.hadoop.api.ReadSupport;
    import org.apache.parquet.hadoop.example.GroupReadSupport;
     
    import java.io.IOException;
    import java.util.*;
     
    /**
     * Created by fanglegefan.com on 17-7-18.
     */
    public class ParquetNewMRReader {
     
        public static class WordCountMap1 extends
                Mapper<Void, Group, LongWritable, Text> {
     
            protected void map(Void key, Group value,
                               Mapper<Void, Group, LongWritable, Text>.Context context)
                    throws IOException, InterruptedException {
     
                String name = value.getString("name",0);
                int  age = value.getInteger("age",0);
     
                context.write(new LongWritable(age),
                        new Text(name));
            }
        }
     
        public static class WordCountReduce1 extends
                Reducer<LongWritable, Text, LongWritable, Text> {
     
            public void reduce(LongWritable key, Iterable<Text> values,
                               Context context) throws IOException, InterruptedException {
                Iterator<Text> iterator = values.iterator();
                while(iterator.hasNext()){
                    context.write(key,iterator.next());
                }
            }
     
        }
     
        public static final class MyReadSupport extends DelegatingReadSupport<Group> {
            public MyReadSupport() {
                super(new GroupReadSupport());
            }
     
            @Override
            public org.apache.parquet.hadoop.api.ReadSupport.ReadContext init(InitContext context) {
                return super.init(context);
            }
        }
     
        public static void main(String[] args) throws Exception {
            Configuration conf = new Configuration();
            String readSchema = "message example {\n" +
                    "required binary name;\n" +
                    "required int32 age;\n" +
                    "}";
            conf.set(ReadSupport.PARQUET_READ_SCHEMA, readSchema);
     
            Job job = new Job(conf);
            job.setJarByClass(ParquetNewMRReader.class);
            job.setJobName("parquet");
     
            String in = "hdfs://localhost:9000/test/wd1";
            String  out = "hdfs://localhost:9000/test/wd2";
     
     
            job.setMapperClass(WordCountMap1.class);
            job.setReducerClass(WordCountReduce1.class);
     
            job.setInputFormatClass(ParquetInputFormat.class);
            ParquetInputFormat.setReadSupportClass(job, MyReadSupport.class);
            ParquetInputFormat.addInputPath(job, new Path(in));
     
            job.setOutputFormatClass(TextOutputFormat.class);
            FileOutputFormat.setOutputPath(job, new Path(out));
     
            job.waitForCompletion(true);
        }
    }

     

     

    查看生成的文件

     

    hadoop dfs -cat /test/wd2/part-r-00000
     
    1       world
    1       spark
    1       presto
    2       in
    2       hadoop
    2       action
    3       hello

     

     

     

     

     

     
    展开全文
  • 大数据常用文件格式介绍

    千次阅读 2019-01-13 16:36:24
    最近在做hdfs小文件合并的项目,涉及了一些文件格式的读写,比如avro、orc、parquet等。期间阅读了一些资料,因此打算写篇文章做个记录。 这篇文章不会介绍如何对这些格式的文件进行读写,只...


    最近在做hdfs小文件合并的项目,涉及了一些文件格式的读写,比如avro、orc、parquet等。期间阅读了一些资料,因此打算写篇文章做个记录。

    这篇文章不会介绍如何对这些格式的文件进行读写,只会介绍一下它们各自的特点以及底层存储的编码格式

    一、SequenceFile

    1. 相比于text格式的文件,SequenceFile可以存储key-value格式的消息,方便mapreduce引擎处理数据
    2. 支持record级别的压缩和block级别的压缩
    3. 文件是分块的,因此是可分割的。支持mapreduce的split输入

    使用sequencefile还可以将多个小文件合并到一个大文件中,通过key-value的形式组织起来,此时该sequencefile可以看做是一个小文件容器。

    二、Avro

    1. 相比SequenceFile,avro支持更丰富的数据结构
    2. 文件是分块的,因此是可分割的。支持mapreduce的split输入
    3. 目前SequenceFile只有java实现,因此没办法通过其他的语言来读写SequenceFile文件,所以avro的一个优势就是多种语言实现
    4. avro的schema是存储在文件中的,因为拿到avro文件就可以直接进行读写。并且avro的schema是可以动态增删改的,保证向前兼容和向后兼容

    三、parquet

    Parquet是一个基于列式存储的文件格式,它将数据按列划分进行存储。Parquet官网上的文件格式介绍图:

    在这里插入图片描述

    我们可以看出,parquet由几个部分构成:

    1. Magic Number
    2. 若干个 Row Group
    3. Footer 信息,即一些元数据
    4. Footer length,固定4个bytes,指出元数据的长度
    5. Magic Number

    1. Row Group 可以理解为一个个block,这个特性让parquet是可分割的,因此可以被mapreduce split来处理
    2. Row Group,还是page,都有具体的统计信息,根据这些统计信息可以做很多优化
    3. 每个 Row Group由一个个 Column chunk组成,也就是一个个列。Column chunk又细分成一个个page,每个page下就是该列的数据集合。列下面再细分page主要是为了添加索引,page容量设置的小一些可以增加索引的速度,但是设置太小也会导致过多的索引和统计数据,不仅占用空间,还会降低扫描索引的时间。
    4. parquet可以支持嵌套的数据结构,它使用了Dremel的 Striping/Assembly 算法来实现对嵌套型数据结构的打散和重构

    四、Orc

    Orc也是一个列式存储格式,产生自Apache Hive,用于降低Hadoop数据存储空间和加速Hive查询速度。

    1. 和Parquet的设计类似,也是将行分成多个组,然后组内按列存储,之后再对列进行分割。orc 的 Stripe 对应parquet的 Row Group,row Group 对应的是 parquet的 page
    2. ORC文件是自描述的,它的元数据使用Protocol Buffers序列化
    3. 除了基本类型以外,还支持更复杂的数据结构,如LIST、STRUCT、MAP和UNION类型。

    五、同为列式存储, orc和parquet的区别

    列式存储的优化点

    目前列式存储是大数据领域基本的优化项,无论是存储还是查询,列式存储能做的优化都很多,看完上面对orc和parquet的文件结构介绍后,我们列式存储的优化点做一个总结:

    在压缩方面

    1. 由于每一列的数据类型都是一样的,因此可以针对每一列的数据类型使用更高效的压缩算法。比如存储时间戳时,我们可以以时间戳偏移大小来存储,减少存储容量

    在查询方面

    1. 在查询时只要扫描需要查询的列数据,不用进行全表扫描。
    2. 由于Column chunk、page都记录了一些统计信息,就可以很方便的根据column的条件直接过滤一些row group、column chunk、或者page不扫描。举个例子,比如已知Row Group的age字段的最小值是10,那么要查询age < 10的数据时就没必要扫描该group了

    orc和parquet的一些区别和对比

    1. 由于设计理念类似,他们的文件格式有很多互通的地方。但是parquet的索引和元数据全部放在footer块,而orc则是分散在各个stripe中。目前也不能说哪种设计更好,只能看实际场景了
    2. 列编码的实现算法不同
    3. 选择的压缩算法不同

    就网上找到的一些数据来看,Orc的压缩比会比Parquet的高一些,至于查询性能,两个应该不会差距太大。本人之前做过一个测试,在多数场景,hive on mr下,orc的查询性能会更好一些。换成hive on spark后,parquet的性能更好一些

    六、一些总结

    本文介绍的4种大数据存储格式,2个是行式存储,2个是列式存储,但我们可以看到一个共同点:它们都是支持分割的。这是大数据文件结构体系中一个非常重要的特点,因为可分割使一个文件可以被多个节点并发处理,提高数据的处理速度

    另外,当前大数据的主要趋势应该是使用列式存储,目前我们公司已经逐步推进列式存储的使用,本人也在hive上做过一些测试,在多个查询场景下,无论是orc还是parquet的查询速度都完爆text格式的,差不多有4-8倍的性能提升。另外,orc和parquet的压缩比都能达到10比1的程度。因此,无论从节约资源和查询性能考虑,在大多数情况下,选择orc或者parquet作为文件存储格式是更好的选择。另外,spark sql的默认读写格式也是parquet。

    当然,并不是说列式存储已经一统天下了,大多时候我们还是要根据自己的使用场景来决定使用哪种存储格式。

    查询资料附录

    Sequencefile

    https://blog.csdn.net/en_joker/article/details/79648861

    https://stackoverflow.com/questions/11778681/advantages-of-sequence-file-over-hdfs-textfile

    Avro和Sequencefile区别

    https://stackoverflow.com/questions/24236803/difference-between-avrodata-file-and-sequence-file-with-respect-to-apache-sqoop

    parquet

    https://www.cnblogs.com/ITtangtang/p/7681019.html

    Orc

    https://www.cnblogs.com/ITtangtang/p/7677912.html

    https://www.cnblogs.com/cxzdy/p/5910760.html

    Orc和parquet的一些对比

    https://blog.csdn.net/colorant/article/details/53699822

    https://blog.csdn.net/yu616568/article/details/51188479

    展开全文
  • Linux环境下几种常用文件系统

    万次阅读 2018-05-24 11:06:15
    Linux环境下几种常用文件系统:1、ext2 ext2是为解决ext文件系统的缺陷而设计的可扩展的、高性能的文件系统,又被称为二级扩展文件系统。它是Linux文件系统中使用最多的类型,并且在速度和CPU利用率上较为突出。...
  • 几种位图文件格式

    千次阅读 2004-10-27 15:01:00
    bmp文件 bmp(bitmap的缩写)文件格式是windows本身的位图文件格式,所谓本身是指windows内部存储位图即采用这种格式。一个.bmp格式的文件通常.bmp的扩展名,但一些是以.rle为扩展名的,rle的意思是行程长度编码...
  • 这一章我们来讲怎么搜索文件,在使用widows来搜索文件相信大家都使用过,在我们linux系统当然也这个功能。在这里给大家一个小的建议,我们linux系统中使用find来搜索文件,最重要的不是文件能不能找到,而是需要...
  • 破解Zip加密文件常用几种方法

    千次阅读 2019-09-25 23:05:04
    https://www.cnblogs.com/ECJTUACM-873284962/p/9387711.html 转载于:https://www.cnblogs.com/cat47/p/11521320.html
  • C#中常用几种读取XML文件的方法

    千次阅读 2016-09-23 15:36:23
    XML文件是一种常用文件格式,例如WinForm里面的app.config以及Web程序中的web.config文件,还有许多重要的场所都它的身影。Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具...
  • .vue文件 中不解析 script标签引入js文件. import引入是必须的. 两种用法: 1.import a from ‘…/a’ 2.import ‘…/a’ 区别在于第一个你要用到export导出之后 才能用import导入. ...详解VUE中常用几种im...
  • 几种常用文件加密方法

    千次阅读 2009-11-20 10:46:00
     每个人的电脑硬盘中都会一些个人隐私或秘密文件,不想让别人打开看到,比如一些账户密码、个人档案、网银信息、客户资料之类的文件。一是防止家人或朋友使用我的电脑时无意看到;另一是在上网的时候,这些...
  • 随着高清技术的逐渐普及,越来越多的节目都采用高清设备来...目前几种主流的高清编码方式:由ITU-T和ISO/IEC联合开发的H.264/AVC/ MPEG-4标准、由苹果公司开发的ProRes 422、由JPEG组织负责制定的JPEG 2000,以及由
  • python写入csv文件几种方法总结

    万次阅读 多人点赞 2017-04-11 11:48:16
    常用的一方法,利用pandas包import pandas as pd#任意的多组列表 a = [1,2,3] b = [4,5,6] #字典中的key值即为csv中列名 dataframe = pd.DataFrame({'a_name':a,'b_name':b})#将DataFrame存储为csv,index表示...
  • Go中配置文件读取的几种方式

    万次阅读 2019-05-17 07:27:33
    日常开发中读取配置文件包含以下几种格式: json 格式字符串 K=V 键值对 xml 文件 yml 格式文件 toml 格式文件 前面两种书写简单,解析过程也比较简单。xml形式书写比较累赘,yml是树形结构,为简化配置而生,toml...
  • 一般来说矢量图表示的是几何图形,文件相对较小,并且放大缩小不会失真。 这里一点要注意的是web开发中用到的图片都不是矢量图,即使是一个三角形,只有一个边框,都是位图。 那么矢量图在哪里有用到呢? ...
  • 几种保存训练模型文件类型

    千次阅读 2017-03-02 15:39:51
    种文件格式binary的缩写。一个后缀名为".bin"的文件,只是表明它是binary格式。比如虚拟光驱文件常用".bin"作为后缀,但并不意味着所有bin文件都是虚拟光驱文件。里面存放的一般是可执行的二进制文件,所以我们通常...
  • AVI、WMV、MPEG、QuickTime、RealVideo、Flash、Mpeg-4,不同的格式有不同的特点。 AVI:文件名以“.avi”结尾。AVI是英文Audio Video Interleave的缩写,该格式由微软开发。在所有Windows系统都能运行这种格式。 ...
  • JSON文件内容加注释的几种方法

    万次阅读 2019-09-30 11:58:17
    有些文件,尤其是配置文件,加入解释说明一些数据项的含义,是必要的。 1、使用JSON5规范 JSON5规范允许在JSON文件中加入注释:单行注释,多行注释均可。 2、直接用json-schema,使用规范中的注释字段 优点...
  • yaml配置文件的使用方法总结 首先介绍使用yaml配置文件,这里使用的是github上第三方开源gopkg.in/yaml.v2 第一步:下载 go get gopkg.in/yaml.v21 第二步:新建一个yaml文件,比如conf.yaml host: ...
  • 有几个notes: The memmap object can be used anywhere an ndarray is accepted. Given a memmap fp, isinstance(fp, numpy.ndarray) returns True. Memory-mapped files cannot be larger than 2GB on 32-...
  • 1.引入第三方组件 import echarts from 'echarts' 2.引入工具类 ...第一是引入单个方法 import {axiosfetch} from './util'; 下面是写法,需要export导出 export function axiosfetch(options) { ...
  • linux的常用文件系统格式

    万次阅读 2011-07-20 16:16:35
    在Linux系统中,每个分区都是一个文件系统,都自己的目录层次结构。Linux的最重要特征之一就是支持多种文件系统,这样它更加灵活,并可以和许多其它操作系统共存。Virtual File System(虚拟文件系统)使得Linux...
  • Android中几种常见的dialog显示格式,话不多说,直接先上图首先是Java代码import android.app.Dialog; import android.content.DialogInterface; import android.support.v7.app.AlertDialog; import android....
  • python读取文件几种方式

    千次阅读 2019-01-29 14:07:06
    1.python读取文件几种方式 read_csv 从文件,url,文件型对象中加载带分隔符的数据。默认分隔符为逗号 read_table 从文件,url,文件型对象中加载带分隔符的数据。默认分隔符为制表符(“\t”) read_fwf 读取定宽...
  • Linux下几种文件传输命令

    万次阅读 2018-11-07 15:16:02
    Linux下几种文件传输命令 sz rz sftp scp    最近在部署系统时接触了一些文件传输命令,分别做一下简单记录: 1.sftp Secure Ftp 是一个基于SSH安全协议的文件传输管理工具。由于它是基于SSH的,会在传输过程...
  • 如果想用 ".jpg"文件格式,直接用下面的代码,会报“couldn't recognize data in image file "C:\Users\happy\Desktop\test.jpg"错误。 photo = tk.PhotoImage(file="C:\\Users\\happy\\Desktop\\test.jpg") Lab=...
  • 现行的常用文件格式类别 简析

    千次阅读 2009-02-25 22:59:00
    简要的说数据信息在存储器中存储的排列方式不同为啦方便理解和交流规范为不同的文件格式,这点在...BMP是一与硬件设备无关的图像文件格式,使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 403,409
精华内容 161,363
关键字:

常用的文件格式有几种