m3u8 文件格式详解

简介

M3U8 是 Unicode 版本的 M3U,用 UTF-8 编码。"M3U" 和 "M3U8" 文件都是苹果公司使用的 HTTP Live Streaming(HLS) 协议格式的基础,这种协议格式可以在 iPhone 和 Macbook 等设备播放。

上述文字定义来自于维基百科。可以看到,m3u8 文件其实是 HTTP Live Streaming(缩写为 HLS) 协议的部分内容,而 HLS 是一个由苹果公司提出的基于 HTTP 的流媒体网络传输协议。

HLS 的工作原理是把整个流分成一个个小的基于 HTTP 的文件来下载,每次只下载一些。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。在开始一个流媒体会话时,客户端会下载一个包含元数据的 extended M3U (m3u8) playlist文件,用于寻找可用的媒体流。
HLS 只请求基本的 HTTP 报文,与实时传输协议(RTP)不同,HLS 可以穿过任何允许 HTTP 数据通过的防火墙或者代理服务器。它也很容易使用内容分发网络来传输媒体流。

简而言之,HLS 是新一代流媒体传输协议,其基本实现原理为将一个大的媒体文件进行分片,将该分片文件资源路径记录于 m3u8 文件(即 playlist)内,其中附带一些额外描述(比如该资源的多带宽信息···)用于提供给客户端。客户端依据该 m3u8 文件即可获取对应的媒体资源,进行播放。

因此,客户端获取 HLS 流文件,主要就是对 m3u8 文件进行解析操作。

那么,下面就简单介绍下 m3u8 文件。

M3U8 文件简介

m3u8 文件实质是一个播放列表(playlist),其可能是一个媒体播放列表(Media Playlist),或者是一个主列表(Master Playlist)。但无论是哪种播放列表,其内部文字使用的都是 utf-8 编码。

当 m3u8 文件作为媒体播放列表(Meida Playlist)时,其内部信息记录的是一系列媒体片段资源,顺序播放该片段资源,即可完整展示多媒体资源。其格式如下所示:

#EXTM3U
#EXT-X-TARGETDURATION:10

#EXTINF:9.009,
http://media.example.com/first.ts
#EXTINF:9.009,
http://media.example.com/second.ts
#EXTINF:3.003,
http://media.example.com/third.ts

对于点播来说,客户端只需按顺序下载上述片段资源,依次进行播放即可。而对于直播来说,客户端需要 定时重新请求 该 m3u8 文件,看下是否有新的片段数据需要进行下载并播放。

当 m3u8 作为主播放列表(Master Playlist)时,其内部提供的是同一份媒体资源的多份流列表资源(Variant Stream)。其格式如下所示:

#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=150000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/low/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=240000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/lo_mid/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=440000,RESOLUTION=416x234,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/hi_mid/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=640000,RESOLUTION=640x360,CODECS="avc1.42e00a,mp4a.40.2"
http://example.com/high/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=64000,CODECS="mp4a.40.5"
http://example.com/audio/index.m3u8

该备用流资源指定了多种不同码率,不同格式的媒体播放列表,并且,该备用流资源也可同时提供不同版本的资源内容,比如不同语言的音频文件,不同角度拍摄的视屏文件等等。客户可以根据不同的网络状态选取合适码流的资源,并且最好根据用户喜好选择合适的资源内容。

更多详细内容,可查看:

  • Creating a Master Playlist
  • Adding Alternate Media to a Playlist

以上,就是 m3u8 文件的大概内容。下面,我们就对 m3u8 内容格式进行讲解。

m3u8 文件格式简解

m3u8 的文件格式主要包含三方面内容:

  1. 文件播放列表格式定义:播放列表(Playlist,也即 m3u8 文件) 内容需严格满足规范定义所提要求。下面罗列一些主要遵循的条件:
  • m3u8 文件必须以 utf-8 进行编码,不能使用 Byte Order Mark(BOM)字节序, 不能包含 utf-8 控制字符(U+0000 ~ U_001F 和 U+007F ~ u+009F)。

  • m3u8 文件的每一行要么是一个 URI,要么是空行,要么就是以 # 开头的字符串。不能出现空白字符,除了显示声明的元素。

  • m3u8 文件中以 # 开头的字符串要么是注释,要么就是标签。标签以 #EXT 开头,大小写敏感。

  1. 属性列表(Attribute Lists):某些特定的标签的值为属性列表。标签后面的属性列表以 逗号 作为分隔符,分离出多组不带空格的 属性/值 对。
    属性/值 对的语法格式如下:
AttributeName=AttributeValue

其中:

  • 属性AttributeName是由 [A..Z],[0..9] 和 - 组成的不带引号的字符串。因此,属性AttributeName只能使用大写字母,不能使用小写字母,并且AttributeName=中间不能有空格,同理,=AttributeValue之间也不能有空格。

  • AttributeValue的只能取以下类型:

    • 十进制整型(decimal-interger):由 [0..9] 之间组成的十进制不带引号的字符串,范围为 ~ (18446744073709551615),字符长度为 1 ~ 20 之间。
    • 十六进制序列:由 [0..9] 和 [A..F] 且前缀为 0x 或 0X 组合成的不带引号的字符串。其序列的最大长度取决于他的属性名AttributeNames
    • 带符号十进制浮点型(signed-decimal-floating-point):由 [0..9],-.组合成的不带引号的字符串。
    • 字符串(quoted-string):由双引号包裹表示的字符串。其中,0xA,0xD 和 双引号"不能出现在该字符串中。该字符串区分大小写。
    • 可枚举字符串(enumerated-string):由AttributeName显示定义的一系列不带引号的字符串。该字符串不能包含双引号",逗号,和空白字符。
    • decimal-resolution:由字符x进行隔离的两个十进制整型数。第一个整型表示水平宽度大小,第二个整型数表示垂直方向高度大小(单位:像素)。
  1. 标签:标签用于指定 m3u8 文件的全局参数或在其后面的切片文件/媒体播放列表的一些信息。

标签的类型可分为五种类型:基础标签(Basic Tags)媒体片段类型标签(Media Segment Tags)媒体播放列表类型标签主播放列表类型标签播放列表类型标签。其具体内容如下所示:

  • 基础标签(Basic Tags):可同时适用于媒体播放列表(Media Playlist)和主播放列表(Master Playlist)。具体标签如下:

    • EXTM3U:表明该文件是一个 m3u8 文件。每个 M3U 文件必须将该标签放置在第一行。
    • EXT-X-VERSION:表示 HLS 的协议版本号,该标签与流媒体的兼容性相关。该标签为全局作用域,使能整个 m3u8 文件;每个 m3u8 文件内最多只能出现一个该标签定义。如果 m3u8 文件不包含该标签,则默认为协议的第一个版本。
  • 媒体片段类型标签(Media Segment Tags):每个切片 URI 前面都有一系列媒体片段标签对其进行描述。有些片段标签只对其后切片资源有效;有些片段标签对其后所有切片都有效,直到后续遇到另一个该标签描述。媒体片段类型标签不能出现在主播放列表(Master Playlist)中。具体标签如下:

    • EXTINF:表示其后 URL 指定的媒体片段时长(单位为秒)。每个 URL 媒体片段之前必须指定该标签。该标签的使用格式为:

      #EXTINF:,[]
      </code></pre> <p>其中:</p> 
           <ul> 
            <li> <code>duration</code>:可以为十进制的整型或者浮点型,其值必须小于或等于 <strong>EXT-X-TARGETDURATION</strong> 指定的值。<br> 注:建议始终使用浮点型指定时长,这可以让客户端在定位流时,减少四舍五入错误。但是如果兼容版本号 <strong>EXT-X-VERSION</strong> 小于 3,那么必须使用整型。</li> 
           </ul> </li> 
          <li> <p><strong>EXT-X-BYTERANGE</strong>:该标签表示接下来的切片资源是其后 URI 指定的媒体片段资源的局部范围(即截取 URI 媒体资源部分内容作为下一个切片)。该标签只对其后一个 URI 起作用。其格式为:</p> <pre><code class="m3u8">#EXT-X-BYTERANGE:<n>[@<o>]
      </code></pre> <p>其中:</p> 
           <ul> 
            <li> <code>n</code>是一个十进制整型,表示截取片段大小(单位:字节)。</li> 
            <li>可选参数<code>o</code>也是一个十进制整型,指示截取起始位置(以字节表示,在 URI 指定的资源开头移动该字节位置后进行截取)。<br> 如果<code>o</code>未指定,则截取起始位置从上一个该标签截取完成的下一个字节(即上一个<code>n+o+1</code>)开始截取。<br> 如果没有指定该标签,则表明的切分范围为整个 URI 资源片段。<br> 注:使用 <strong>EXT-X-BYTERANGE</strong> 标签要求兼容版本号 <strong>EXT-X-VERSION</strong> 大于等于 4。</li> 
           </ul> </li> 
          <li> <p><strong>EXT-X-DISCONTINUITY</strong>:该标签表明其前一个切片与下一个切片之间存在中断。其格式为:</p> <pre><code class="m3u8">#EXT-X-DISCONTINUITY
      </code></pre> <p>当以下任一情况变化时,必须使用该标签:</p> 
           <ul> 
            <li>文件格式(file format)</li> 
            <li>数字(number),类型(type),媒体标识符(identifiers of tracks)</li> 
            <li>时间戳序列(timestamp sequence)</li> 
           </ul> <p>当以下任一情况变化时,应当使用该标签:</p> 
           <ul> 
            <li>编码参数(encoding parameters)</li> 
            <li>编码序列(encoding sequence)</li> 
           </ul> <p>注:<strong>EXT-X-DISCONTINUITY</strong> 的一个经典使用场景就是在视屏流中插入广告,由于视屏流与广告视屏流不是同一份资源,因此在这两种流切换时使用 <strong>EXT-X-DISCONTINUITY</strong> 进行指明,客户端看到该标签后,就会处理这种切换中断问题,让体验更佳。<br> 更多详细内容,请查看:Incorporating Ads into a Playlist</p> </li> 
          <li> <p><strong>EXT-X-KEY</strong>:媒体片段可以进行加密,而该标签可以指定解密方法。<br> 该标签对所有 <em>媒体片段</em> 和 由标签 <strong>EXT-X-MAP</strong> 声明的围绕其间的所有 <em>媒体初始化块(Meida Initialization Section)</em> 都起作用,直到遇到下一个 <strong>EXT-X-KEY</strong>(若 m3u8 文件只有一个 <strong>EXT-X-KEY</strong> 标签,则其作用于所有媒体片段)。<br> 多个 <strong>EXT-X-KEY</strong> 标签如果最终生成的是同样的秘钥,则他们都可作用于同一个媒体片段。<br> 该标签使用格式为:</p> <pre><code class="m3u8">#EXT-X-KEY:<attribute-list>
      </code></pre> <p>属性列表可以包含如下几个键:</p> 
           <ul> 
            <li><p><strong>METHOD</strong>:该值是一个可枚举的字符串,指定了加密方法。<br> 该键是必须参数。其值可为<code>NONE</code>,<code>AES-128</code>,<code>SAMPLE-AES</code>当中的一个。<br> 其中:<br> <code>NONE</code>:表示切片未进行加密(此时其他属性不能出现);<br> <code>AES-128</code>:表示表示使用 AES-128 进行加密。<br> <code>SAMPLE-AES</code>:意味着媒体片段当中包含样本媒体,比如音频或视频,它们使用 AES-128 进行加密。这种情况下 <strong>IV</strong> 属性可以出现也可以不出现。</p></li> 
            <li><p><strong>URI</strong>:指定密钥路径。<br> 该密钥是一个 16 字节的数据。<br> 该键是必须参数,除非 <strong>METHOD</strong> 为<code>NONE</code>。</p></li> 
            <li><p><strong>IV</strong>:该值是一个 128 位的十六进制数值。<br> AES-128 要求使用相同的 16字节 IV 值进行加密和解密。使用不同的 IV 值可以增强密码强度。<br> 如果属性列表出现 <strong>IV</strong>,则使用该值;如果未出现,则默认使用媒体片段序列号(即 <strong>EXT-X-MEDIA-SEQUENCE</strong>)作为其 <strong>IV</strong> 值,使用大端字节序,往左填充 0 直到序列号满足 16 字节(128 位)。</p></li> 
            <li><p><strong>KEYFORMAT</strong>:由双引号包裹的字符串,标识密钥在密钥文件中的存储方式(密钥文件中的 AES-128 密钥是以二进制方式存储的16个字节的密钥)。<br> 该属性为可选参数,其默认值为<code>"identity"</code>。<br> 使用该属性要求兼容版本号 <strong>EXT-X-VERSION</strong> 大于等于 5。</p></li> 
            <li><p><strong>KEYFORMATVERSIONS</strong>:由一个或多个被<code>/</code>分割的正整型数值构成的带引号的字符串(比如:<code>"1"</code>,<code>"1/2"</code>,<code>"1/2/5"</code>)。<br> 如果有一个或多特定的 <strong>KEYFORMT</strong> 版本被定义了,则可使用该属性指示具体版本进行编译。<br> 该属性为可选参数,其默认值为<code>"1"</code>。<br> 使用该属性要求兼容版本号 <strong>EXT-X-VERSION</strong> 大于等于 5。</p></li> 
           </ul> </li> 
          <li> <p><strong>EXT-X-MAP</strong>:该标签指明了获取媒体初始化块(Meida Initialization Section)的方法。<br> 该标签对其后所有媒体片段生效,直至遇到另一个 <strong>EXT-X-MAP</strong> 标签。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-MAP:<attribute-list>
      </code></pre> <p>其属性列表取值范围如下:</p> 
           <ul> 
            <li><p><strong>URI</strong>:由引号包裹的字符串,指定了包含媒体初始化块的资源的路径。该属性为必选参数。</p></li> 
            <li><p><strong>BYTERANGE</strong>:由引号包裹的字符串,指定了媒体初始化块在 <strong>URI</strong> 指定的资源的位置(片段)。<br> 该属性指定的范围应当只包含媒体初始化块。<br> 该属性为可选参数,如果未指定,则表示 <strong>URI</strong> 指定的资源就是全部的媒体初始化块。</p></li> 
           </ul> </li> 
          <li> <p><strong>EXT-X-PROGRAM-DATE-TIME</strong>:该标签使用一个绝对日期/时间表明第一个样本片段的取样时间。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-PROGRAM-DATE-TIME:<date-time-msec>
      </code></pre> <p>其中,<code>date-time-msec</code>是一个 ISO/IEC 8601:2004 规定的日期格式,形如:YYYY-MM-DDThh:mm:ss.SSSZ。</p> </li> 
          <li> <p><strong>EXT-X-DATERANGE</strong>:该标签定义了一系列由属性/值对组成的日期范围。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-DATERANGE:<attribute-list>
      </code></pre> <p>其属性列表取值如下:</p> 
           <ul> 
            <li><p><strong>ID</strong>:双引号包裹的唯一指明日期范围的标识。<br> 该属性为必选参数。</p></li> 
            <li><p><strong>CLASS</strong>:双引号包裹的由客户定义的一系列属性与与之对应的语意值。<br> 所有拥有同一 <strong>CLASS</strong> 属性的日期范围必须遵守对应的语意。<br> 该属性为可选参数。</p></li> 
            <li><p><strong>START-DATE</strong>:双引号包裹的日期范围起始值。<br> 该属性为必选参数。</p></li> 
            <li><p><strong>END-DATE</strong>:双引号包裹的日期范围结束值。<br> 该属性值必须大于或等于 <strong>START-DATE</strong>。<br> 该属性为可选参数。</p></li> 
            <li><p><strong>DURATION</strong>:日期范围的持续时间是一个十进制浮点型数值类型(单位:秒)。<br> 该属性值不能为负数。<br> 当表达立即时间时,将该属性值设为 0 即可。<br> 该属性为可选参数。</p></li> 
            <li><p><strong>PLANNED-DURATION</strong>:该属性为日期范围的期望持续时长。<br> 其值为一个十进制浮点数值类型(单位:秒)。<br> 该属性值不能为负数。<br> 在预先无法得知真实持续时长的情况下,可使用该属性作为日期范围的期望预估时长。<br> 该属性为可选参数。</p></li> 
           </ul> </li> 
          <li><p><strong>X-<client-attribute></strong>:<code>X-</code>前缀是预留给客户端自定义属性的命名空间。<br> 客户端自定义属性名时,应当使用反向 DNS(reverse-DNS)语法来避免冲突。<br> 自定义属性值必须是使用双引号包裹的字符串,或者是十六进制序列,或者是十进制浮点数,比如:<code>X-COM-EXAMPLE-AD-ID="XYZ123"</code>。<br> 该属性为可选参数。</p></li> 
          <li><p><strong>SCTE35-CMD, SCTE35-OUT, SCTE35-IN</strong>:用于携带 SCET-35 数据。<br> 该属性为可选参数。</p></li> 
          <li><p><strong>END-ON-NEXT</strong>:该属性值为一个可枚举字符串,其值必须为<code>YES</code>。<br> 该属性表明达到该范围末尾,也即等于后续范围的起始位置 <strong>START-DATE</strong>。后续范围是指具有相同 <strong>CLASS</strong> 的,在该标签 <strong>START-DATE</strong> 之后的具有最早 <strong>START-DATE</strong> 值的日期范围。<br> 该属性时可选参数。</p></li> 
         </ul> </li> 
        <li> <p><strong>媒体播放列表类型标签</strong>:媒体播放列表标签为 m3u8 文件的全局参数信息。<br> 这些标签只能在 m3u8 文件中至多出现一次。<br> 媒体播放列表(Media Playlist)标签不能出现在主播放列表(Master Playlist)中。<br> 媒体播放列表具体标签如下所示:</p> 
         <ul> 
          <li> <p><strong>EXT-X-TARGETDURATION</strong>:表示每个视频分段最大的时长(单位秒)。<br> 该标签为必选标签。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-TARGETDURATION:<s>
      </code></pre> <p>其中:参数<code>s</code>表示目标时长(单位:秒)。</p> </li> 
          <li> <p><strong>EXT-X-MEDIA-SEQUENCE</strong>:表示播放列表第一个 URL 片段文件的序列号。<br> 每个媒体片段 URL 都拥有一个唯一的整型序列号。<br> 每个媒体片段序列号按出现顺序依次加 1。<br> 如果该标签未指定,则默认序列号从 0 开始。<br> 媒体片段序列号与片段文件名无关。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-MEDIA-SEQUENCE:<number>
      </code></pre> <p>其中:参数<code>number</code>即为切片序列号。</p> </li> 
          <li> <p><strong>EXT-X-DISCONTINUITY-SEQUENCE</strong>:该标签使能同步相同流的不同 Rendition 和 具备 <strong>EXT-X-DISCONTINUITY</strong> 标签的不同备份流。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-DISCONTINUITY-SEQUENCE:<number>
      </code></pre> <p>其中:参数<code>number</code>为一个十进制整型数值。<br> 如果播放列表未设置 <strong>EXT-X-DISCONTINUITY-SEQUENCE</strong> 标签,那么对于第一个切片的中断序列号应当为 0。</p> </li> 
          <li> <p><strong>EXT-X-ENDLIST</strong>:表明 m3u8 文件的结束。<br> 该标签可出现在 m3u8 文件任意位置,一般是结尾。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-ENDLIST
      </code></pre> </li> 
          <li> <p><strong>EXT-X-PLAYLIST-TYPE</strong>:表明流媒体类型。全局生效。<br> 该标签为可选标签。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-PLAYLIST-TYPE:<type-enum>
      </code></pre> <p>其中:<code>type-enum</code>可选值如下:</p> 
           <ul> 
            <li><p><strong>VOD</strong>:即 Video on Demand,表示该视屏流为点播源,因此服务器不能更改该 m3u8 文件;</p></li> 
            <li><p><strong>EVENT</strong>:表示该视频流为直播源,因此服务器不能更改或删除该文件任意部分内容(但是可以在文件末尾添加新内容)。<br> 注:<strong>VOD</strong> 文件通常带有 <strong>EXT-X-ENDLIST</strong> 标签,因为其为点播源,不会改变;而 <strong>EVEVT</strong> 文件初始化时一般不会有 <strong>EXT-X-ENDLIST</strong> 标签,暗示有新的文件会添加到播放列表末尾,因此也需要客户端定时获取该 m3u8 文件,以获取新的媒体片段资源,直到访问到 <strong>EXT-X-ENDLIST</strong> 标签才停止)。</p></li> 
           </ul> </li> 
          <li> <p><strong>EXT-X-I-FRAMES-ONLY</strong>:该标签表示每个媒体片段都是一个 <strong>I-frame</strong>。<strong>I-frames</strong> 帧视屏编码不依赖于其他帧数,因此可以通过 <strong>I-frame</strong> 进行快速播放,急速翻转等操作。<br> 该标签全局生效。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-I-FRAMES-ONLY
      </code></pre> <p>如果播放列表设置了 <strong>EXT-X-I-FRAMES-ONLY</strong>,那么切片的时长(<strong>EXTINF</strong> 标签的值)即为当前切片 <strong>I-frame</strong> 帧开始到下一个 <strong>I-frame</strong> 帧出现的时长。<br> 媒体资源如果包含 <strong>I-frame</strong> 切片,那么必须提供媒体初始化块或者通过 <strong>EXT-X-MAP</strong> 标签提供媒体初始化块的获取途径,这样客户端就能通过这些 <strong>I-frame</strong> 切片以任意顺序进行加载和解码。<br> 如果 <strong>I-frame</strong> 切片设置了 <strong>EXT-BYTERANGE</strong>,那么就绝对不能提供媒体初始化块。<br> 使用 <strong>EXT-X-I-FRAMES-ONLY</strong> 要求的兼容版本号 <strong>EXT-X-VERSION</strong> 大于等于 4。</p> </li> 
         </ul> </li> 
        <li> <p><strong>主播放列表类型标签</strong>:主播放列表(Master Playlist)定义了备份流,多语言翻译流和其他全局参数。<br> 主播放列表标签绝不能出现在媒体播放列表(Media Playlist)中。<br> 其具体标签如下:</p> 
         <ul> 
          <li> <p><strong>EXT-X-MEDIA</strong>:用于指定相同内容的可替换的多语言翻译播放媒体列表资源。<br> 比如,通过三个 <strong>EXT-X-MEIDA</strong> 标签,可以提供包含英文,法语和西班牙语版本的相同内容的音频资源,或者通过两个 <strong>EXT-X-MEDIA</strong> 提供两个不同拍摄角度的视屏资源。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-MEDIA:<attribute-list>
      </code></pre> <p>其中,属性列表取值范围如下:</p> 
           <ul> 
            <li><p><strong>TYPE</strong>:该属性值为一个可枚举字符串。<br> 其值有如下四种:<code>AUDIO</code>,<code>VIDEO</code>,<code>SUBTITLES</code>,<code>CLOSED-CAPTIONS</code>。<br> 通常使用的都是<code>CLOSED-CAPTIONS</code>。<br> 该属性为必选参数。</p></li> 
            <li><p><strong>URI</strong>:双引号包裹的媒体资源播放列表路径。<br> 如果 <strong>TYPE</strong> 属性值为 <code>CLOSED-CAPTIONS</code>,那么则不能提供 <strong>URI</strong>。<br> 该属性为可选参数。</p></li> 
            <li><p><strong>GROUP-ID</strong>:双引号包裹的字符串,表示多语言翻译流所属组。<br> 该属性为必选参数。</p></li> 
            <li><p><strong>LANGUAGE</strong>:双引号包裹的字符串,用于指定流主要使用的语言。<br> 该属性为可选参数。</p></li> 
            <li><p><strong>ASSOC-LANGUAGE</strong>:双引号包裹的字符串,其内包含一个语言标签,用于提供多语言流的其中一种语言版本。<br> 该参数为可选参数。</p></li> 
            <li><p><strong>NAME</strong>:双引号包裹的字符串,用于为翻译流提供可读的描述信息。<br> 如果设置了 <strong>LANGUAGE</strong> 属性,那么也应当设置 <strong>NAME</strong> 属性。<br> 该属性为必选参数。</p></li> 
            <li><p><strong>DEFAULT</strong>:该属性值为一个可枚举字符串。<br> 可选值为<code>YES</code>和<code>NO</code>。<br> 该属性未指定时默认值为<code>NO</code>。<br> 如果该属性设为<code>YES</code>,那么客户端在缺乏其他可选信息时应当播放该翻译流。<br> 该属性为可选参数。</p></li> 
            <li><p><strong>AUTOSELECT</strong>:该属性值为一个可枚举字符串。<br> 其有效值为<code>YES</code>或<code>NO</code>。<br> 未指定时,默认设为<code>NO</code>。<br> 如果该属性设置<code>YES</code>,那么客户端在用户没有显示进行设置时,可以选择播放该翻译流,因为其能配置当前播放环境,比如系统语言选择。<br> 如果设置了该属性,那么当 <strong>DEFAULT</strong> 设置<code>YES</code>时,该属性也必须设置为<code>YES</code>。<br> 该属性为可选参数。</p></li> 
            <li><p><strong>FORCED</strong>:该属性值为一个可枚举字符串。<br> 其有效值为<code>YES</code>或<code>NO</code>。<br> 未指定时,默认设为<code>NO</code>。<br> 只有在设置了 <strong>TYPE</strong> 为 <strong>SUBTITLES</strong> 时,才可以设置该属性。<br> 当该属性设为<code>YES</code>时,则暗示该翻译流包含重要内容。当设置了该属性,客户端应当选择播放匹配当前播放环境最佳的翻译流。<br> 当该属性设为<code>NO</code>时,则表示该翻译流内容意图用于回复用户显示进行请求。<br> 该属性为可选参数。</p></li> 
            <li><p><strong>INSTREAM-ID</strong>:由双引号包裹的字符串,用于指示切片的语言(Rendition)版本。<br> 当 <strong>TYPE</strong> 设为 <strong>CLOSED-CAPTIONS</strong> 时,必须设置该属性。<br> 其可选值为:<code>"CC1"</code>, <code>"CC2"</code>, <code>"CC3"</code>, <code>"CC4"</code> 和 <code>"SERVICEn"</code>(<code>n</code>的值为 1~63)。<br> 对于其他 <strong>TYPE</strong> 值,该属性绝不能进行设置。</p></li> 
            <li><p><strong>CHARACTERISTICS</strong>:由双引号包裹的由一个或多个由逗号分隔的 UTI 构成的字符串。<br> 每个 UTI 表示一种翻译流的特征。<br> 该属性可包含私有 UTI。<br> 该属性为可选参数。</p></li> 
            <li><p><strong>CHANNELS</strong>:由双引号包裹的有序,由反斜杠<code>/</code>分隔的参数列表组成的字符串。<br> 所有音频 <strong>EXT-X-MEDIA</strong> 标签应当都设置 <strong>CHANNELS</strong> 属性。<br> 如果主播放列表包含两个相同编码但是具有不同数目 channed 的翻译流,则必须设置 <strong>CHANNELS</strong> 属性;否则,<strong>CHANNELS</strong> 属性为可选参数。</p></li> 
           </ul> </li> 
          <li> <p><strong>EXT-X-STREAM-INF</strong>:该属性指定了一个备份源。该属性值提供了该备份源的相关信息。<br> 其格式为:</p> <pre><code>#EXT-X-STREAM-INF:<attribute-list>
      <URI>
      </code></pre> <p>其中:</p> 
           <ul> 
            <li><p><strong>URI</strong> 指定的媒体播放列表携带了该标签指定的翻译备份源。<br> <strong>URI</strong> 为必选参数。</p></li> 
            <li> <p><strong>EXT-X-STREAM-INF</strong> 标签的参数属性列表有如下选项:</p> 
             <ul> 
              <li><p><strong>BANDWIDTH</strong>:该属性为每秒传输的比特数,也即带宽。代表该备份流的巅峰速率。<br> 该属性为必选参数。</p></li> 
              <li><p><strong>AVERAGE-BANDWIDTH</strong>:该属性为备份流的平均切片传输速率。<br> 该属性为可选参数。</p></li> 
              <li><p><strong>CODECS</strong>:双引号包裹的包含由逗号分隔的格式列表组成的字符串。<br> 每个 <strong>EXT-X-STREAM-INF</strong> 标签都应当携带 <strong>CODECS</strong> 属性。</p></li> 
              <li><p><strong>RESOLUTION</strong>:该属性描述备份流视屏源的最佳像素方案。<br> 该属性为可选参数,但对于包含视屏源的备份流建议增加该属性设置。</p></li> 
              <li><p><strong>FRAME-RATE</strong>:该属性用一个十进制浮点型数值作为描述备份流所有视屏最大帧率。<br> 对于备份流中任意视屏源帧数超过每秒 30 帧的,应当增加该属性设置。<br> 该属性为可选参数,但对于包含视屏源的备份流建议增加该属性设置。</p></li> 
              <li><p><strong>HDCP-LEVEL</strong>:该属性值为一个可枚举字符串。<br> 其有效值为<code>TYPE-0</code>或<code>NONE</code>。<br> 值为<code>TYPE-0</code>表示该备份流可能会播放失败,除非输出被高带宽数字内容保护(HDCP)。<br> 值为<code>NONE</code>表示流内容无需输出拷贝保护。<br> 使用不同程度的 HDCP 加密备份流应当使用不同的媒体加密密钥。<br> 该属性为可选参数。在缺乏 HDCP 可能存在播放失败的情况下,应当提供该属性。</p></li> 
              <li><p><strong>AUDIO</strong>:属性值由双引号包裹,其值必须与定义在主播放列表某处的设置了 <strong>TYPE</strong> 属性值为 <strong>AUDIO</strong> 的 <strong>EXT-X-MEDIA</strong> 标签的 <strong>GROUP-ID</strong> 属性值相匹配。<br> 该属性为可选参数。</p></li> 
              <li><p><strong>VIDEO</strong>:属性值由双引号包裹,其值必须与定义在主播放列表某处的设置了 <strong>TYPE</strong> 属性值为 <strong>VIDEO</strong> 的 <strong>EXT-X-MEDIA</strong> 标签的 <strong>GROUP-ID</strong> 属性值相匹配。<br> 该属性为可选参数。</p></li> 
              <li><p><strong>SUBTITLES</strong>:属性值由双引号包裹,其值必须与定义在主播放列表某处的设置了 <strong>TYPE</strong> 属性值为 <strong>SUBTITLES</strong> 的 <strong>EXT-X-MEDIA</strong> 标签的 <strong>GROUP-ID</strong> 属性值相匹配。<br> 该属性为可选参数。</p></li> 
              <li><p><strong>CLOSED-CAPTIONS</strong>:该属性值可以是一个双引号包裹的字符串或<code>NONE</code>。<br> 如果其值为一个字符串,则必须与定义在主播放列表某处的设置了 <strong>TYPE</strong> 属性值为 <strong>CLOSED-CAPTIONS</strong> 的 <strong>EXT-X-MEDIA</strong> 标签的 <strong>GROUP-ID</strong> 属性值相匹配。<br> 如果其值为<code>NONE</code>,则所有的 <strong>ext-x-stream-inf</strong> 标签必须同样将该属性设置<code>NONE</code>,表示主播放列表备份流均没有关闭的标题。对于某个备份流具备关闭标题,另一个备份流不具备关闭标题可能会触发播放中断。<br> 该属性为可选参数。</p></li> 
             </ul> </li> 
           </ul> </li> 
          <li> <p><strong>EXT-X-I-FRAME-STREAM-INF</strong>:该标签表明媒体播放列表文件包含多种媒体资源的 <strong>I-frame</strong> 帧。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-I-FRAME-STREAM-INF:<attribute-list>
      </code></pre> <p>该标签的属性列表包含了 <strong>EXT-X-I-FRAME-STREAM-INF</strong> 标签同样的属性列表选项,除了 <strong>FRAME-RATE</strong>,<strong>AUDIO</strong>,<strong>SUBTITLES</strong> 和 <strong>CLOSED-CAPTIONS</strong>。除此之外,其他的属性还有:</p> 
           <ul> 
            <li> <strong>URI</strong>:该属性值由双引号包裹的字符串,指示了 <strong>I-frame</strong> 媒体播放列表文件的路径,该媒体播放列表文件必须包含 <strong>EXT-X-I-FRAMES-ONLY</strong> 标签。</li> 
           </ul> </li> 
          <li> <p><strong>EXT-X-SESSION-DATA</strong>:该标签允许主播放列表携带任意 session 数据。<br> 该标签为可选参数。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-SESSION-DATA:<attribute-list>
      </code></pre> <p>其中,其参数属性列表值如下可选项:</p> 
           <ul> 
            <li><p><strong>DATA-ID</strong>:由双引号包裹的字符串,代表一个特定的数据值。<br> 该属性应当使用反向 DNS 进行命名,如<code>"com.example.movie.title"</code>。然而,由于没有中央注册机构,所以可能出现冲突情况。<br> 该属性为必选参数。</p></li> 
            <li><p><strong>VALUE</strong>:该属性值为一个双引号包裹的字符串,其包含 <strong>DATA-ID</strong> 指定的值。<br> 如果设置了 <strong>LANGUAGE</strong>,则 <strong>VALUE</strong> 应当包含一个用该语言书写的可读字符串。</p></li> 
            <li><p><strong>URI</strong>:由双引号包裹的 URI 字符串。由该 URI 指示的资源必选使用 JSON 格式,否则,客户端可能会解析失败。</p></li> 
            <li><p><strong>LANGUAGE</strong>:由双引号包裹的,包含一个语言标签的字符串。指示了 <strong>VALUE</strong> 所使用的语言。</p></li> 
           </ul> </li> 
         </ul> </li> 
       </ul> 
       <ul> 
        <li> <strong>EXT-X-SESSION-KEY</strong>:该标签允许主播放列表(Master Playlist)指定媒体播放列表(Meida Playlist)的加密密钥。这使得客户端可以预先加载这些密钥,而无需从媒体播放列表中获取。<br> 该标签为可选参数。<br> 其格式为: <pre><code class="m3u8">#EXT-X-SESSION-KEY:<attribute-list>
      </code></pre> 其属性列表与 <strong>EXT-X-KEY</strong> 相同,除了 <strong>METHOD</strong> 属性的值必须不为<code>NONE</code>。</li> 
       </ul> 
       <ul> 
        <li> <p><strong>播放列表类型标签</strong>:以下标签可同时设置于主播放列表(Master Playlist)和媒体播放列表(Media Playlist)中。<br> 但是对于在主播放列表中设置了的标签,不应当再次设置在主播放列表指向的媒体播放列表中。<br> 同时出现在两者播放列表的相同标签必须具备相同的值。这些标签在播放列表中不能出现多次(只能使用一次)。具体标签如下所示:</p> 
         <ul> 
          <li> <p><strong>EXT-X-INDEPENDENT-SEGMENTS</strong>:该标签表明对于一个媒体片段中的所有媒体样本均可独立进行解码,而无须依赖其他媒体片段信息。<br> 该标签对列表内所有媒体片段均有效。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-INDEPENDENT-SEGMENTS
      </code></pre> <p>如果该标签出现在主播放列表中,则其对所有媒体播放列表的所有媒体片段都生效。</p> </li> 
          <li> <p><strong>EXT-X-START</strong>:该标签表示播放列表播放起始位置。<br> 默认情况下,客户端开启一个播放会话时,应当使用该标签指定的位置进行播放。<br> 该标签为可选标签。<br> 其格式为:</p> <pre><code class="m3u8">#EXT-X-START:<attribute-list>
      </code></pre> <p>其参数属性列表的取值范围如下:</p> 
           <ul> 
            <li><p><strong>TIME-OFFSET</strong>:该属性值为一个带符号十进制浮点数(单位:秒)。<br> 一个正数表示以播放列表起始位置开始的时间偏移量。<br> 一个负数表示播放列表上一个媒体片段最后位置往前的时间偏移量。<br> 该属性的绝对值应当不超过播放列表的时长。如果超过,则表示到达文件结尾(数值为正数),或者达到文件起始(数值为负数)。<br> 如果播放列表不包含 <strong>EXT-X-ENDLIST</strong> 标签,那么 <strong>TIME-OFFSET</strong> 属性值不应当在播放文件末尾三个切片时长之内。</p></li> 
            <li><p><strong>PRECISE</strong>:该值为一个可枚举字符串。<br> 有效的取值为<code>YES</code> 或 <code>NO</code>。<br> 如果值为<code>YES</code>,客户端应当播放包含 <strong>TIME-OFFSET</strong> 的媒体片段,但不要渲染该块内优先于 <strong>TIME-OFFSET</strong> 的样本块。<br> 如果值为<code>NO</code>,客户端应当尝试渲染在媒体片段内的所有样本块。<br> 该属性为可选参数,未指定则认为<code>NO</code>。</p></li> 
           </ul> </li> 
         </ul> </li> 
       </ul> 
       <p>到此,m3u8 相关的标签我们已经完全介绍完毕。</p> 
       <p>下面我们再简单介绍下资源文件的获取具体操作。</p> 
       <p>上文提到,m3u8 文件要么是媒体播放列表(Meida Playlist),要么是主播放列表(Master Playlist)。但无论是哪种列表,其有效内容均由两部分结构组成:</p> 
       <ul> 
        <li>以 <strong>#EXT</strong> 开头的为标签信息,作为对媒体资源的进一步描述;</li> 
        <li>剩余的为资源信息,要么是片段资源(Media Playlist)路径,要么是 m3u8 资源(Master Playlist)路径;</li> 
       </ul> 
       <p>我们先简单介绍下 m3u8 文件媒体片段的表示方法:</p> 
       <ul> 
        <li>m3u8 文件中,媒体片段可以采用全路径表示。如下所示:</li> 
       </ul> 
       <pre><code class="m3u8">#EXTINF:10.0,
      http://example.com/movie1/fileSequenceA.ts
      </code></pre> 
       <p>这样,获取资源片段的路径就是 m3u8 文件内指定的路径,即:<code>http://example.com/movie1/fileSequenceA.ts</code></p> 
       <ul> 
        <li>m3u8 文件中,媒体片段还可以使用相对路径表示。如下所示:</li> 
       </ul> 
       <pre><code class="txt">#EXTINF:10.0,
      fileSequenceA.ts
      </code></pre> 
       <p>这表示片段文件的路径是相对于 m3u8 文件路径的,即假设当前 m3u8 的路径为:<code>https://127.0.0.1/hls/m3u8</code>,那么,片段文件 fileSequenceA.ts 的路径即为:<code>https://127.0.0.1/hls/fileSequenceA.ts</code></p> 
       <p>尽管可以在 m3u8 文件中使用绝对路径指定媒体片段资源路径,但是更好的选择是使用相对路径。相对路径相较于绝对路径更轻便,同时是相对于 m3u8 文件的 URL。相比之下,绝对路径增加了 m3u8 文件内容(更多字符),增大了文件内容,同时也增大了网络传输量。</p> 
       <h2>其余一些注意事项</h2> 
       <ul> 
        <li><p>有两种请求 m3u8 播放列表的方法:一是通过 m3u8 的 URI 进行请求,则该文件必须以 .m3u8 或 .m3u 结尾;<br> 二是通过 HTTP 进行请求,则请求头<code>Content-Type</code>必须设置为 <code>application/vnd.apple.mpegurl</code>或者<code>audio/mpegurl</code>。</p></li> 
        <li><p>空行和注释行在解析时都忽略。</p></li> 
        <li><p>媒体播放列表(Media Playlist)的流资源总时长就是各切片资源的时长之和。</p></li> 
        <li><p>每个切片的码率(bit rate)就是切片的大小除以它对应的时长(<strong>EXTINF</strong> 指定的时长)。</p></li> 
        <li><p>一个标签的属性列表的同一个属性<code>AttributeName</code>只能出现一次。</p></li> 
        <li><p><strong>EXT-X-TARGETDURATION</strong> 指定的时长绝对不能进行更改。通常该值指定的时长为 10 秒。</p></li> 
        <li><p>对于指定了 <strong>EXT-X-I-FRAMES-ONLY</strong> 且 第一个媒体片段(或者第一个尾随 <strong>EXT-X-DISCONTINUITY</strong> 的片段)其资源没有立即携带媒体初始化块的切片,应当增加使用标签 <strong>EXT-X-MAP</strong> 指定媒体初始化块获取途径。</p></li> 
        <li><p>使用 <strong>EXT-X-MAP</strong> 标签内含标签 <strong>EXT-X-I-FRAMES-ONLY</strong> 要求的兼容版本号 <strong>EXT-X-VERSION</strong> 要大于等于 5;只使用 <strong>EXT-X-MAP</strong> 要求的兼容版本号要大于等于 6。</p></li> 
        <li><p>由标签 <strong>EXT-X-MAP</strong> 声明的媒体初始化块可使用 AES-128 方法进行加密,此时,作用于 <strong>EXT-X-MAP</strong> 标签的 <strong>EXT-X-KEY</strong> 标签必须设置 <strong>IV</strong> 属性。</p></li> 
        <li><p>带有属性 <strong>END-ON-NEXT=YES</strong> 的标签 <strong>EXT-X-DATERANGE</strong> 必须携带 <strong>CLASS</strong> 属性,但不能携带 <strong>DURATION</strong> 和 <strong>END-DATE</strong> 属性。其余带有相同 <strong>CLASS</strong> 的标签 <strong>EXT-X-DATERANGE</strong> 不能指定重叠的日期范围。</p></li> 
        <li><p>日期范围如果未指明 <strong>DURATION</strong>,<strong>END_DATE</strong>,<strong>END-ON-NEXT=YES</strong> 属性时,则其时长(duration)未知,即使其设置了 <strong>PLANNED-DURATION</strong> 属性。</p></li> 
        <li><p>如果播放列表设置了 <strong>EXT-X-DATERANGE</strong> 标签,则必须同时设置 <strong>EXT-X-PROGRAM-DATE-TIME</strong> 标签。</p></li> 
        <li><p>如果播放列表设置了拥有相同 <strong>ID</strong> 属性值的两个 <strong>EXT-X-DATERANGE</strong> 标签,则对于相同的属性名,在这两个 <strong>EXT-X-DATERANGE</strong> 中对应的值必须一致。</p></li> 
        <li><p>如果 <strong>EXT-X-DATERANGE</strong> 同时设置了 <strong>DURATION</strong> 和 <strong>END-DATE</strong> 属性,则 <strong>END-DATE</strong> 属性值必须等于 <strong>START-DATE</strong> 属性值加上 <strong>DURATION</strong> 属性值。</p></li> 
        <li><p><strong>EXT-X-MEDIA-SEQUENCE</strong> 标签必须出现在播放列表第一个切片之前。</p></li> 
        <li><p><strong>EXT-X-DISCONTINUITY-DEQUENCE</strong> 标签必须出现在播放列表第一个切片之前。</p></li> 
        <li><p><strong>EXT-X-DISCONTINUITY-DEQUENCE</strong> 标签必须出现在任意 <strong>EXT-X-DISCONTINUITY</strong> 标签之前。</p></li> 
        <li><p>m3u8 文件如果没有设置 <strong>EXT-X-PLAYLIST-TYPE</strong> 标签,那么播放列表可以随时进行更改。比如,可以更新或删除播放列表中的媒体片段。</p></li> 
        <li><p>每个 <strong>EXT-X-I-FRAME-STREAM-INF</strong> 标签必须包含一个 <strong>BANDWIDTH</strong> 和 <strong>URI</strong> 属性。</p></li> 
        <li><p>每个 <strong>EXT-X-SESSION-DATA</strong> 标签都必须包含一个 <strong>VALUE</strong> 或 <strong>URI</strong> 属性,但不能同时包含两者。</p></li> 
        <li><p>一个播放列表可以包含多个携带相同 <strong>DATA-ID</strong> 属性的 <strong>EXT-X-SESSION-DATA</strong> 标签。但是不能包含多个携带相同 <strong>DATA-ID</strong> 和相同 <strong>LANGUAGE</strong> 属性的 <strong>EXT-X-SESSION-DATA</strong> 标签。</p></li> 
        <li><p>如果设置了 <strong>EXT-X-SESSION-KEY</strong>,那么其 <strong>METHOD</strong>,<strong>KEYFORMAT</strong> 和 <strong>KEYFORMATVERSIONS</strong> 属性值必须与任意相同 <strong>URI</strong> 的 <strong>EXT-X-KEY</strong> 标签值相同。</p></li> 
        <li><p>如果多份备用流或者多语言流使用相同的加密密钥和格式,则应当设置 <strong>EXT-X-SESSION-KEY</strong> 标签。</p></li> 
        <li><p>主播放列表必须不能设置多个具有相同 <strong>METHOD</strong>,<strong>URI</strong>,<strong>IV</strong>,<strong>KEYFORMAT</strong> 和 <strong>KEYFORMATVERSIONS</strong> 属性值得 <strong>EXT-X-SESSION-KEY</strong> 标签。</p></li> 
       </ul> 
       <h2>附录</h2> 
       <ul> 
        <li><p>苹果官方文档</p></li> 
        <li><p>HTTP Live Streaming - rfc8216</p></li> 
        <li><p>视频内容加密封装技术研究</p></li> 
       </ul> 
      </article>
                                  </div>
                              </div>
                          </div>
                          <!--PC和WAP自适应版-->
                          <div id="SOHUCS" sid="1385921066421014528"></div>
                          <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                          <!-- 文章页-底部 动态广告位 -->
                          <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                      </div>
                      <div class="col-md-3">
                          <div class="row" id="ad">
                              <!-- 文章页-右侧1 动态广告位 -->
                              <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                                  <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                              </div>
                              <!-- 文章页-右侧2 动态广告位 -->
                              <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                                  <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                              </div>
                              <!-- 文章页-右侧3 动态广告位 -->
                              <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                                  <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                              </div>
                          </div>
                      </div>
                  </div>
              </div>
          </div>
          <div class="container">
              <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(m3u8 文件格式详解)</h4>
              <div id="paradigm-article-related">
                  <div class="recommend-post mb30">
                      <ul class="widget-links">
                          <li><a href="/article/1943975753808932864.htm"
                                 title="霍夫变换(Hough Transform)算法原来详解和纯C++代码实现以及OpenCV中的使用示例" target="_blank">霍夫变换(Hough Transform)算法原来详解和纯C++代码实现以及OpenCV中的使用示例</a>
                              <span class="text-muted">点云SLAM</span>
      <a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E5%BD%A2%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86/1.htm">图形图像处理</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/opencv/1.htm">opencv</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86%E4%B8%8E%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89%E7%AE%97%E6%B3%95/1.htm">图像处理与计算机视觉算法</a><a class="tag" taget="_blank" href="/search/%E7%9B%B4%E7%BA%BF%E6%8F%90%E5%8F%96%E6%A3%80%E6%B5%8B/1.htm">直线提取检测</a><a class="tag" taget="_blank" href="/search/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/1.htm">目标检测</a><a class="tag" taget="_blank" href="/search/%E9%9C%8D%E5%A4%AB%E5%8F%98%E6%8D%A2%E7%AE%97%E6%B3%95/1.htm">霍夫变换算法</a>
                              <div>霍夫变换(HoughTransform)是一种经典的图像处理与计算机视觉算法,广泛用于检测图像中的几何形状,例如直线、圆、椭圆等。其核心思想是将图像空间中的“点”映射到参数空间中的“曲线”,从而将形状检测问题转化为参数空间中的峰值检测问题。一、霍夫变换基本思想输入:边缘图像(如经过Canny边缘检测)输出:一组满足几何模型的形状(如直线、圆)关键思想:图像空间中的一个点→参数空间中的一个曲线参数空</div>
                          </li>
                          <li><a href="/article/1943973357707915264.htm"
                                 title="MySQL Explain 详解:从入门到精通,让你的 SQL 飞起来" target="_blank">MySQL Explain 详解:从入门到精通,让你的 SQL 飞起来</a>
                              <span class="text-muted"></span>
      
                              <div>引言:为什么Explain是SQL优化的“照妖镜”?在Java开发中,我们常常会遇到数据库性能瓶颈的问题。一条看似简单的SQL语句,在数据量增长到一定规模后,可能会从毫秒级响应变成秒级甚至分钟级响应,直接拖慢整个应用的性能。此时,你是否曾困惑于:为什么这条SQL突然变慢了?索引明明建了,为什么没生效?到底是哪里出了问题?答案就藏在MySQL的EXPLAIN命令里。EXPLAIN就像一面“照妖镜”,</div>
                          </li>
                          <li><a href="/article/1943971717185597440.htm"
                                 title="Python中的静态方法和类方法详解" target="_blank">Python中的静态方法和类方法详解</a>
                              <span class="text-muted"></span>
      
                              <div>在Python中,`@staticmethod`和`@classmethod`是两种装饰器,它们用于定义类中的方法,但是它们的行为和用途有所不同。###@staticmethod`@staticmethod`装饰器用于定义一个静态方法。静态方法不接收类或实例的引用作为第一个参数,因此它不能访问类的状态或实例的状态。静态方法可以看作是与类关联的普通函数,但它们可以通过类名直接调用。classMath</div>
                          </li>
                          <li><a href="/article/1943969448046161920.htm"
                                 title="Python中类静态方法:@classmethod/@staticmethod详解和实战示例" target="_blank">Python中类静态方法:@classmethod/@staticmethod详解和实战示例</a>
                              <span class="text-muted"></span>
      
                              <div>在Python中,类方法(@classmethod)和静态方法(@staticmethod)是类作用域下的两种特殊方法。它们使用装饰器定义,并且与实例方法(deffunc(self))的行为有所不同。1.三种方法的对比概览方法类型是否访问实例(self)是否访问类(cls)典型用途实例方法✅是❌否访问对象属性类方法@classmethod❌否✅是创建类的替代构造器,访问类变量等静态方法@stati</div>
                          </li>
                          <li><a href="/article/1943969069501837312.htm"
                                 title="EasyCwmp源码分析与接口实现详解:深入理解源码架构,掌握核心接口" target="_blank">EasyCwmp源码分析与接口实现详解:深入理解源码架构,掌握核心接口</a>
                              <span class="text-muted"></span>
      
                              <div>EasyCwmp源码分析与接口实现详解:深入理解源码架构,掌握核心接口去发现同类优质开源项目:https://gitcode.com/在开源项目中,寻找一款能够提升开发效率、简化流程的工具是每个开发者的追求。今天,我们要介绍的这款开源项目EasyCwmp,正是为了帮助开发者深入了解源码架构,掌握核心接口实现,从而加速项目开发进程。以下是关于EasyCwmp源码分析与接口实现详解的项目推荐文章。项目</div>
                          </li>
                          <li><a href="/article/1943968187112550400.htm"
                                 title="OpenWebUI(12)源码学习-后端constants.py常量定义文件" target="_blank">OpenWebUI(12)源码学习-后端constants.py常量定义文件</a>
                              <span class="text-muted">青苔猿猿</span>
      <a class="tag" taget="_blank" href="/search/AI%E5%A4%A7%E6%A8%A1%E5%9E%8B/1.htm">AI大模型</a><a class="tag" taget="_blank" href="/search/openwebui/1.htm">openwebui</a><a class="tag" taget="_blank" href="/search/constants%E5%B8%B8%E9%87%8F%E5%AE%9A%E4%B9%89/1.htm">constants常量定义</a>
                              <div>目录文件名:`constants.py`功能概述:主要功能点详解1.**MESSAGES枚举类**2.**WEBHOOK_MESSAGES枚举类**3.**ERROR_MESSAGES枚举类**✅默认错误模板✅认证与用户相关错误✅资源冲突与重复错误✅验证失败类错误✅权限限制类错误✅文件上传与格式错误✅模型与API错误✅请求频率与安全限制✅数据库与配置错误4.**TASKS枚举类**✅总结实际应用场</div>
                          </li>
                          <li><a href="/article/1943967933940166656.htm"
                                 title="蓝牙MTU含义 ,协商修改的过程案例分析" target="_blank">蓝牙MTU含义 ,协商修改的过程案例分析</a>
                              <span class="text-muted">悟空胆好小</span>
      <a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a>
                              <div>蓝牙MTU含义,协商修改的过程案例分析文章目录**蓝牙MTU含义,协商修改的过程案例分析****一、MTU含义解析****二、MTU协商过程详解****步骤流程****三、修改MTU的实践案例分析****案例1:中心设备主动设置(主控端)****案例2:外设端响应优化(从设备)****案例3:调试工具强制修改****四、关键限制与注意事项**蓝牙MTU(MaximumTransmissionUni</div>
                          </li>
                          <li><a href="/article/1943962514060537856.htm"
                                 title="Spring Cloud Gateway 的执行链路详解" target="_blank">Spring Cloud Gateway 的执行链路详解</a>
                              <span class="text-muted">愤怒的代码</span>
      <a class="tag" taget="_blank" href="/search/SpringCloud/1.htm">SpringCloud</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/cloud/1.htm">cloud</a>
                              <div>SpringCloudGateway的执行链路详解核心目标明确SpringCloudGateway的请求处理全过程(从接收到请求→到转发→到返回响应),方便你在合适的生命周期节点插入你的逻辑。核心执行链路图(执行顺序)┌──────────────┐│客户端请求│└────┬─────────┘↓┌────┴─────────────┐│NettyHttpServer│←→ReactorNetty</div>
                          </li>
                          <li><a href="/article/1943962514903592960.htm"
                                 title="RocketMQ 核心特性实战详解" target="_blank">RocketMQ 核心特性实战详解</a>
                              <span class="text-muted">愤怒的代码</span>
      <a class="tag" taget="_blank" href="/search/RocketMQ%E5%AE%9E%E6%88%98/1.htm">RocketMQ实战</a><a class="tag" taget="_blank" href="/search/rocketmq/1.htm">rocketmq</a>
                              <div>RocketMQ核心特性实战详解本文基于RocketMQ4.x+rocketmq-spring-boot-starter2.3.1,从零搭建,逐步讲解RocketMQ11大核心特性,每一段代码都能直接跑。0.项目环境准备依赖引入在pom.xml文件添加:org.apache.rocketmqrocketmq-spring-boot-starter2.3.1配置文件application.ymlse</div>
                          </li>
                          <li><a href="/article/1943955456124841984.htm"
                                 title="C#接口实现详解:从理论到实践,掌握面向对象编程的核心技巧" target="_blank">C#接口实现详解:从理论到实践,掌握面向对象编程的核心技巧</a>
                              <span class="text-muted">钢铁男儿</span>
      <a class="tag" taget="_blank" href="/search/C%23/1.htm">C#</a><a class="tag" taget="_blank" href="/search/%E5%9B%BE%E8%A7%A3%E6%95%99%E7%A8%8B/1.htm">图解教程</a><a class="tag" taget="_blank" href="/search/c%23/1.htm">c#</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                              <div>在C#的世界里,接口是实现多态性和解耦设计的利器接口实现的核心规则实现主体限制只有类和结构体(struct)能实现接口。接口本身不包含实现代码,而是定义一组必须由实现类提供的成员契约。双重实现要求声明关联:在类/结构体的基类列表中明确包含接口名称classMyClass:IMyInterface//接口声明在冒号后成员实现:为接口声明的每个成员提供具体的实现代码,包括匹配的方法签名、属性和返回值类</div>
                          </li>
                          <li><a href="/article/1943943735205228544.htm"
                                 title="Python 常用内置函数详解(七):dir()函数——获取当前本地作用域中的名称列表或对象的有效属性列表" target="_blank">Python 常用内置函数详解(七):dir()函数——获取当前本地作用域中的名称列表或对象的有效属性列表</a>
                              <span class="text-muted"></span>
      
                              <div>目录一、功能二、语法和示例一、功能dir()函数获取当前本地作用域中的名称列表或对象的有效属性列表。二、语法和示例dir()函数有两种形式,如果没有实参,则返回当前本地作用域中的名称列表。如果有实参,它会尝试返回该对象的有效属性列表。如果对象有一个名为__dir__()的方法,那么该方法将被调用,并且必须返回一个属性列表。dir()函数的语法格式如下:C:\Users\amoxiang>ipyth</div>
                          </li>
                          <li><a href="/article/1943942727079096320.htm"
                                 title="【unity编辑器开发与拓展EditorGUILayoyt和GUILayoyt】" target="_blank">【unity编辑器开发与拓展EditorGUILayoyt和GUILayoyt】</a>
                              <span class="text-muted">死也不注释</span>
      <a class="tag" taget="_blank" href="/search/Unity%E7%BC%96%E8%BE%91%E5%99%A8%E5%BC%80%E5%8F%91%E4%B8%8E%E6%8B%93%E5%B1%95%E7%AC%94%E8%AE%B0/1.htm">Unity编辑器开发与拓展笔记</a><a class="tag" taget="_blank" href="/search/unity/1.htm">unity</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E8%BE%91%E5%99%A8/1.htm">编辑器</a><a class="tag" taget="_blank" href="/search/%E6%B8%B8%E6%88%8F%E5%BC%95%E6%93%8E/1.htm">游戏引擎</a>
                              <div>EditorGUILayout与GUILayout的核心区别及使用场景详解一、对比表特性GUILayoutEditorGUILayout命名空间UnityEngineUnityEditor使用场景运行时UI+编辑器扩展仅限编辑器扩展控件风格基础游戏风格(无编辑器优化)原生Unity编辑器风格布局复杂度基础流式布局高级自动布局(带标签对齐/间距优化)序列化支持❌不支持✅直接支持SerializedP</div>
                          </li>
                          <li><a href="/article/1943942347976929280.htm"
                                 title="【DBC】DBC中CAN信号多路复用" target="_blank">【DBC】DBC中CAN信号多路复用</a>
                              <span class="text-muted">徐饼干</span>
      <a class="tag" taget="_blank" href="/search/DBC/1.htm">DBC</a><a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E4%BA%BA%E7%94%9F/1.htm">程序人生</a><a class="tag" taget="_blank" href="/search/%E5%85%B6%E4%BB%96/1.htm">其他</a><a class="tag" taget="_blank" href="/search/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/1.htm">经验分享</a>
                              <div>DBC文件信号多路复用详解1何时定义有些信号比较长,但是又不常用,就可以定义多路复用信号以节约空间。2具体定义2.1定义一个短信号来当做“控制开关”。【若定义1bit,则有2种可能0x00和0x01,复用两路】【若定义2bit,则有4种可能0x00和0x01和0x10和0x11,复用四路】…所以说,这个短信号的长度和你想复用多少路有关,多长?放在什么位置?由定义者决定2.2节约空间是如何体现的现在</div>
                          </li>
                          <li><a href="/article/1943940584297263104.htm"
                                 title="【华为机试】HJ61 放苹果" target="_blank">【华为机试】HJ61 放苹果</a>
                              <span class="text-muted">不爱熬夜的Coder</span>
      <a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BA%E6%9C%BA%E8%AF%95/1.htm">华为机试</a><a class="tag" taget="_blank" href="/search/golang/1.htm">golang</a><a class="tag" taget="_blank" href="/search/%E5%8D%8E%E4%B8%BA/1.htm">华为</a><a class="tag" taget="_blank" href="/search/golang/1.htm">golang</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a>
                              <div>文章目录HJ61放苹果描述输入描述输出描述示例1示例2解题思路算法分析问题本质分析状态定义与转移递推关系详解动态规划表构建算法流程图示例推导过程代码实现思路时间复杂度分析关键优化点边界情况处理递归解法对比实际应用场景测试用例分析算法特点数学原理完整题解代码HJ61放苹果描述我们需要将m个相同的苹果放入n个相同的盘子中,允许有的盘子空着不放。求解有多少种不同的分法。输入描述输入两个整数m,n(0B[</div>
                          </li>
                          <li><a href="/article/1943934034631520256.htm"
                                 title=".Net程序集强签名详解" target="_blank">.Net程序集强签名详解</a>
                              <span class="text-muted"></span>
      
                              <div>强签名:1.可以将强签名的dll注册到GAC,不同的应用程序可以共享同一dll。2.强签名的库,或者应用程序只能引用强签名的dll,不能引用未强签名的dll,但是未强签名的dll可以引用强签名的dll。3.强签名无法保护源代码,强签名的dll是可以被反编译的。4.强签名的dll可以防止第三方恶意篡改。强签名的方法:1.有源代码:1.1使用vstoolcommand:snk–kmykey.snk生成</div>
                          </li>
                          <li><a href="/article/1943932394662850560.htm"
                                 title="Docker容器底层原理详解:从零理解容器化技术" target="_blank">Docker容器底层原理详解:从零理解容器化技术</a>
                              <span class="text-muted">Debug Your Career</span>
      <a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/%E5%AE%B9%E5%99%A8/1.htm">容器</a><a class="tag" taget="_blank" href="/search/docker/1.htm">docker</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                              <div>一、容器本质:一个“隔离的进程”关键认知:Docker容器并不是一个完整的操作系统,而是一个被严格隔离的进程。这个进程拥有独立的文件系统、网络、进程视图等资源,但它直接运行在宿主机内核上(而虚拟机需要模拟硬件和操作系统)。类比理解:想象你在一个办公楼里租了一间独立办公室(容器)。你有自己的桌椅(文件系统)、电话分机(网络)、门牌号(主机名),但共享整栋楼的水电(宿主机内核)和电梯(硬件资源)。办公</div>
                          </li>
                          <li><a href="/article/1943930881873866752.htm"
                                 title="flutter redux状态管理" target="_blank">flutter redux状态管理</a>
                              <span class="text-muted">liao277218962</span>
      <a class="tag" taget="_blank" href="/search/Flutter/1.htm">Flutter</a><a class="tag" taget="_blank" href="/search/flutter/1.htm">flutter</a><a class="tag" taget="_blank" href="/search/state/1.htm">state</a><a class="tag" taget="_blank" href="/search/redux/1.htm">redux</a>
                              <div>Flutter状态管理系列文章目录Flutter状态管理(setState、InheritedWidget、Provider、Riverpod、BLoC/Cubit、GetX、MobX、Redux)setState()使用详解:原理及注意事项InheritedWidget组件使用及原理Flutter中Provider的使用、注意事项与原理解析(含代码实战)GetX用法详细解析以及注意事项Flutt</div>
                          </li>
                          <li><a href="/article/1943929488433803264.htm"
                                 title=".NET nupkg包的深度解析与安全防护指南" target="_blank">.NET nupkg包的深度解析与安全防护指南</a>
                              <span class="text-muted">深盾科技</span>
      <a class="tag" taget="_blank" href="/search/.net/1.htm">.net</a>
                              <div>在.NET开发领域,nupkg包是开发者们不可或缺的工具。它不仅是代码分发和资源共享的核心载体,还贯穿了开发、构建、部署的全流程。今天,我们将深入探讨nupkg包的核心功能、打包发布流程以及安全防护措施,帮助你在.NET开发中更加得心应手。nupkg包的核心功能nupkg是NuGet包的文件格式,本质上是一个ZIP压缩包,包含编译后的程序集(.dll文件)、调试符号(.pdb文件)、描述文件(.n</div>
                          </li>
                          <li><a href="/article/1943923817982259200.htm"
                                 title="Java Web 之 Session 详解" target="_blank">Java Web 之 Session 详解</a>
                              <span class="text-muted">艾伦~耶格尔</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/session/1.htm">session</a>
                              <div>在JavaWeb开发中,Session就像网站的专属记忆管家,为每个用户保管着重要的信息和状态,确保用户在网站的旅程顺畅无阻。场景一:想象你去一家大型超市购物,推着购物车挑选商品。这个购物车就如同Session,它记录了你的购物信息,方便你在结账时一次性结算。场景二:你在玩一个在线游戏,登录账号后,你的游戏进度、等级、装备等信息都会被保存在Session中,即使你中途关闭游戏,下次登录时依然可以继</div>
                          </li>
                          <li><a href="/article/1943922306841636864.htm"
                                 title="提升企业级数据处理效率!TDengine 四个集群优化点详解" target="_blank">提升企业级数据处理效率!TDengine 四个集群优化点详解</a>
                              <span class="text-muted">TDengine (老段)</span>
      <a class="tag" taget="_blank" href="/search/TDengine/1.htm">TDengine</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/%E7%89%A9%E8%81%94%E7%BD%91/1.htm">物联网</a><a class="tag" taget="_blank" href="/search/%E6%97%B6%E5%BA%8F%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">时序数据库</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a><a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a><a class="tag" taget="_blank" href="/search/tdengine/1.htm">tdengine</a>
                              <div>为了帮助企业更好地进行大数据处理,我们在此前TDengine3.x系列版本中进行了几项与集群相关的优化和新功能开发,以提升集群的稳定性和在异常情况下的恢复能力。这些优化包括clusterID隔离、leaderrebalance、raftlearner和restorednode。本文将对这几项重要优化进行详细阐述,以解答企业在此领域的疑问,并帮助大家更好地应对相关挑战。clusterID隔离问题fi</div>
                          </li>
                          <li><a href="/article/1943919153068961792.htm"
                                 title="Ajax之核心语法详解" target="_blank">Ajax之核心语法详解</a>
                              <span class="text-muted">AA-代码批发V哥</span>
      <a class="tag" taget="_blank" href="/search/Ajax%2FAxios/1.htm">Ajax/Axios</a><a class="tag" taget="_blank" href="/search/ajax/1.htm">ajax</a>
                              <div>Ajax之核心语法详解一、Ajax的核心原理与优势1.1什么是Ajax?1.2Ajax的优势二、XMLHttpRequest:Ajax的核心对象2.1XHR的基本使用流程2.2核心属性与事件解析2.2.1`readyState`:请求状态2.2.2`status`:HTTP状态码2.2.3响应数据属性2.2.4常用事件三、HTTP请求方法与数据传递3.1GET请求:获取数据3.2POST请求:提交</div>
                          </li>
                          <li><a href="/article/1943919026744913920.htm"
                                 title="JavaScript之DOM操作与事件处理详解" target="_blank">JavaScript之DOM操作与事件处理详解</a>
                              <span class="text-muted">AA-代码批发V哥</span>
      <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                              <div>JavaScript之DOM操作与事件处理详解一、DOM基础:理解文档对象模型二、DOM元素的获取与访问2.1基础获取方法2.2集合的区别与注意事项三、DOM元素的创建与修改3.1创建与插入元素3.2修改元素属性与样式3.2.1属性操作3.2.2样式操作3.3元素内容的修改四、DOM元素的删除与替换4.1删除元素4.2替换元素五、事件处理:实现页面交互5.1事件绑定的三种方式5.1.1HTML属性</div>
                          </li>
                          <li><a href="/article/1943917893620133888.htm"
                                 title="V少JS基础班之第五弹" target="_blank">V少JS基础班之第五弹</a>
                              <span class="text-muted">V少在逆向</span>
      <a class="tag" taget="_blank" href="/search/JS%E5%9F%BA%E7%A1%80%E7%8F%AD/1.htm">JS基础班</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a>
                              <div>文章目录一、前言二、本节涉及知识点三、重点内容1-函数的定义2-函数的构成1.函数参数详解1)参数个数不固定2)默认参数3)arguments对象(类数组)4)剩余参数(Rest参数)5)函数参数是按值传递的6)解构参数传递7)参数校验技巧(JavaScript没有类型限制,需要手动校验)2.函数返回值详解3-函数的分类1-函数声明式:2-函数表达式:3-箭头函数:4-构造函数:5-IIFE:6-</div>
                          </li>
                          <li><a href="/article/1943914611900215296.htm"
                                 title="ZooKeeper架构及应用场景详解" target="_blank">ZooKeeper架构及应用场景详解</a>
                              <span class="text-muted">走过冬季</span>
      <a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/1.htm">学习笔记</a><a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a><a class="tag" taget="_blank" href="/search/%E6%9E%B6%E6%9E%84/1.htm">架构</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%B8%83%E5%BC%8F/1.htm">分布式</a>
                              <div>ZooKeeper是一个开源的分布式协调服务,由Apache软件基金会维护。它旨在为分布式应用提供高性能、高可用、强一致性的基础服务,解决分布式系统中常见的协调难题(如配置管理、命名服务、分布式锁、服务发现、领导者选举等)。核心软件架构ZooKeeper的架构设计围绕其核心目标(协调)而优化,主要包含以下关键组件:集群模式(Ensemble):ZooKeeper通常部署为集群(称为ensemble</div>
                          </li>
                          <li><a href="/article/1943902134995054592.htm"
                                 title="11. TCP 滑动窗口、拥塞控制是什么,有什么区别" target="_blank">11. TCP 滑动窗口、拥塞控制是什么,有什么区别</a>
                              <span class="text-muted">yqcoder</span>
      <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95-%E6%9C%8D%E5%8A%A1%E5%8D%8F%E8%AE%AE/1.htm">前端面试-服务协议</a><a class="tag" taget="_blank" href="/search/tcp%2Fip/1.htm">tcp/ip</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a><a class="tag" taget="_blank" href="/search/php/1.htm">php</a>
                              <div>总结滑动窗口:早期网络,通信双方不考虑网络拥挤情况,导致掉包。滑动窗口大小意味着有多少缓冲区接受数据。拥塞控制:防止过多数据注入网络中,拥塞控制是一个全局过程,控制网络流量。区别:滑动窗口解决掉包问题,拥塞控制解决网络拥塞问题。TCP滑动窗口与拥塞控制详解在TCP协议中,为了实现可靠传输和高效通信,引入了两个核心机制:滑动窗口(SlidingWindow)和拥塞控制(CongestionContr</div>
                          </li>
                          <li><a href="/article/1943895331490033664.htm"
                                 title="STM32 ADC详解" target="_blank">STM32 ADC详解</a>
                              <span class="text-muted">月入鱼饵</span>
      <a class="tag" taget="_blank" href="/search/stm32/1.htm">stm32</a><a class="tag" taget="_blank" href="/search/%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%A1%AC%E4%BB%B6/1.htm">嵌入式硬件</a><a class="tag" taget="_blank" href="/search/%E5%8D%95%E7%89%87%E6%9C%BA/1.htm">单片机</a>
                              <div>本文介绍stm32ADC的使用,本文较长,可以配合目录跳转到需要的地方阅读。ADC转换原理本文重点在于STM32的ADC的使用,介绍ADC转换原理是为了更好理解STM32中关于ADC的配置,所以这里只是简单介绍一下ADC的转换原理,想详细了解ADC的转换原理可以看看看完这篇文章,终于搞懂了ADC原理及分类!和ADC基本工作原理-CSDN。简单来说,模拟信号输入进来,经过低通滤波操作预处理信号之后,</div>
                          </li>
                          <li><a href="/article/1943894069293936640.htm"
                                 title="Spring 声明式事务:从原理到实现的完整解析" target="_blank">Spring 声明式事务:从原理到实现的完整解析</a>
                              <span class="text-muted">Code季风</span>
      <a class="tag" taget="_blank" href="/search/Spring%E8%AF%A6%E8%A7%A3/1.htm">Spring详解</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a>
                              <div>在后端开发中,事务管理是保证数据一致性的核心机制。尤其是在复杂业务场景下,一个操作可能涉及多步数据库操作,任何一步失败都需要回滚到初始状态。Spring的声明式事务通过AOP思想,将事务管理从业务逻辑中剥离,让开发者更专注于核心业务。本文将结合实际实现,详解声明式事务的核心机制和设计思路。一、为什么需要声明式事务?在讨论实现之前,我们先明确一个问题:为什么要用声明式事务,而不是手动编写事务代码?假</div>
                          </li>
                          <li><a href="/article/1943877171621720064.htm"
                                 title="多态与虚函数详解" target="_blank">多态与虚函数详解</a>
                              <span class="text-muted">tkevinjd</span>
      <a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E5%A4%9A%E6%80%81/1.htm">多态</a><a class="tag" taget="_blank" href="/search/%E8%99%9A%E5%87%BD%E6%95%B0/1.htm">虚函数</a>
                              <div>多态(Polymorphism)是面向对象编程(OOP)的三大特性之一(另外两个是封装和继承)。多态的意思是“多种形态”,它允许不同的对象对同一消息作出不同的响应。简单来说,多态是指通过统一的接口调用不同的实现。1.多态的核心思想多态的核心思想是:同一操作作用于不同的对象,可以有不同的解释,产生不同的结果。例如,动物都会“叫”,但不同的动物(如猫、狗)的叫声是不同的。通过多态,我们可以用统一的“叫</div>
                          </li>
                          <li><a href="/article/1943875911363391488.htm"
                                 title="Java实习模拟面试之安徽九德 —— 面向对象编程、Spring框架与数据库技术详解" target="_blank">Java实习模拟面试之安徽九德 —— 面向对象编程、Spring框架与数据库技术详解</a>
                              <span class="text-muted">培风图南以星河揽胜</span>
      <a class="tag" taget="_blank" href="/search/java%E9%9D%A2%E8%AF%95/1.htm">java面试</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a>
                              <div>关键词:Java实习生、模拟面试、安徽九德、SpringBoot、MySQL、Redis、面向对象编程、团队协作一、前言作为一名计算机相关专业的学生,想要顺利进入一家互联网公司或软件开发企业实习,技术面试是必须面对的一道门槛。本文将带你走进一场真实的Java实习生模拟面试场景,以“安徽九德”公司为背景,围绕其发布的招聘岗位要求,进行一次全方位的技术面试演练。本次模拟面试涵盖以下核心知识点:Java</div>
                          </li>
                          <li><a href="/article/1943867340949090304.htm"
                                 title="大模型MoE模型技术详解" target="_blank">大模型MoE模型技术详解</a>
                              <span class="text-muted">大雷神</span>
      <a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD/1.htm">人工智能</a><a class="tag" taget="_blank" href="/search/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/1.htm">机器学习</a><a class="tag" taget="_blank" href="/search/AI/1.htm">AI</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%A8%A1%E5%9E%8B/1.htm">大模型</a>
                              <div>场景:大型超市的收银区域想象一下周末的超市,人山人海(就像大模型要处理海量的Token)。众多收银台(专家):超市有20个收银台,每个收银台都是一个“专家”。有的收银台是人工柜台(擅长处理现金、复杂商品、老人购物);有的是自助扫码机(适合年轻人、商品少、动作快);有的是快速通道(只允许买5件商品以下的顾客);有的是大宗商品通道(专门处理整箱饮料、大件物品)。智能引导系统(门控网络):顾客(每个To</div>
                          </li>
                                      <li><a href="/article/57.htm"
                                             title="多线程编程之join()方法" target="_blank">多线程编程之join()方法</a>
                                          <span class="text-muted">周凡杨</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/JOIN/1.htm">JOIN</a><a class="tag" taget="_blank" href="/search/%E5%A4%9A%E7%BA%BF%E7%A8%8B/1.htm">多线程</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/%E7%BA%BF%E7%A8%8B/1.htm">线程</a>
                                          <div>现实生活中,有些工作是需要团队中成员依次完成的,这就涉及到了一个顺序问题。现在有T1、T2、T3三个工人,如何保证T2在T1执行完后执行,T3在T2执行完后执行?问题分析:首先问题中有三个实体,T1、T2、T3, 因为是多线程编程,所以都要设计成线程类。关键是怎么保证线程能依次执行完呢?   
      Java实现过程如下: 
      public class T1 implements Runnabl</div>
                                      </li>
                                      <li><a href="/article/184.htm"
                                             title="java中switch的使用" target="_blank">java中switch的使用</a>
                                          <span class="text-muted">bingyingao</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/enum/1.htm">enum</a><a class="tag" taget="_blank" href="/search/break/1.htm">break</a><a class="tag" taget="_blank" href="/search/continue/1.htm">continue</a>
                                          <div>java中的switch仅支持case条件仅支持int、enum两种类型。 
      用enum的时候,不能直接写下列形式。 
       
       
      switch (timeType) {
                  case ProdtransTimeTypeEnum.DAILY:
      
                      break;
      
                  default:
                      br</div>
                                      </li>
                                      <li><a href="/article/311.htm"
                                             title="hive having count 不能去重" target="_blank">hive having count 不能去重</a>
                                          <span class="text-muted">daizj</span>
      <a class="tag" taget="_blank" href="/search/hive/1.htm">hive</a><a class="tag" taget="_blank" href="/search/%E5%8E%BB%E9%87%8D/1.htm">去重</a><a class="tag" taget="_blank" href="/search/having+count/1.htm">having count</a><a class="tag" taget="_blank" href="/search/%E8%AE%A1%E6%95%B0/1.htm">计数</a>
                                          <div>hive在使用having count()是,不支持去重计数 
        
      hive (default)> select imei from t_test_phonenum where ds=20150701 group by imei having count(distinct phone_num)>1 limit 10;  
      FAILED: SemanticExcep</div>
                                      </li>
                                      <li><a href="/article/438.htm"
                                             title="WebSphere对JSP的缓存" target="_blank">WebSphere对JSP的缓存</a>
                                          <span class="text-muted">周凡杨</span>
      <a class="tag" taget="_blank" href="/search/WAS+JSP+%E7%BC%93%E5%AD%98/1.htm">WAS JSP 缓存</a>
                                          <div>      对于线网上的工程,更新JSP到WebSphere后,有时会出现修改的jsp没有起作用,特别是改变了某jsp的样式后,在页面中没看到效果,这主要就是由于websphere中缓存的缘故,这就要清除WebSphere中jsp缓存。要清除WebSphere中JSP的缓存,就要找到WAS安装后的根目录。 
             现服务</div>
                                      </li>
                                      <li><a href="/article/565.htm"
                                             title="设计模式总结" target="_blank">设计模式总结</a>
                                          <span class="text-muted">朱辉辉33</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a>
                                          <div>1.工厂模式 
        1.1 工厂方法模式 (由一个工厂类管理构造方法) 
           1.1.1普通工厂模式(一个工厂类中只有一个方法) 
           1.1.2多工厂模式(一个工厂类中有多个方法) 
           1.1.3静态工厂模式(将工厂类中的方法变成静态方法) 
      &n</div>
                                      </li>
                                      <li><a href="/article/692.htm"
                                             title="实例:供应商管理报表需求调研报告" target="_blank">实例:供应商管理报表需求调研报告</a>
                                          <span class="text-muted">老A不折腾</span>
      <a class="tag" taget="_blank" href="/search/finereport/1.htm">finereport</a><a class="tag" taget="_blank" href="/search/%E6%8A%A5%E8%A1%A8%E7%B3%BB%E7%BB%9F/1.htm">报表系统</a><a class="tag" taget="_blank" href="/search/%E6%8A%A5%E8%A1%A8%E8%BD%AF%E4%BB%B6/1.htm">报表软件</a><a class="tag" taget="_blank" href="/search/%E4%BF%A1%E6%81%AF%E5%8C%96%E9%80%89%E5%9E%8B/1.htm">信息化选型</a>
                                          <div>引言 
      随着企业集团的生产规模扩张,为支撑全球供应链管理,对于供应商的管理和采购过程的监控已经不局限于简单的交付以及价格的管理,目前采购及供应商管理各个环节的操作分别在不同的系统下进行,而各个数据源都独立存在,无法提供统一的数据支持;因此,为了实现对于数据分析以提供采购决策,建立报表体系成为必须。 业务目标 
      1、通过报表为采购决策提供数据分析与支撑 
      2、对供应商进行综合评估以及管理,合理管理和</div>
                                      </li>
                                      <li><a href="/article/819.htm"
                                             title="mysql" target="_blank">mysql</a>
                                          <span class="text-muted">林鹤霄</span>
      
                                          <div>转载源:http://blog.sina.com.cn/s/blog_4f925fc30100rx5l.html 
      mysql -uroot -p 
      ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) 
        
      [root@centos var]# service mysql</div>
                                      </li>
                                      <li><a href="/article/946.htm"
                                             title="Linux下多线程堆栈查看工具(pstree、ps、pstack)" target="_blank">Linux下多线程堆栈查看工具(pstree、ps、pstack)</a>
                                          <span class="text-muted">aigo</span>
      <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a>
                                          <div>原文:http://blog.csdn.net/yfkiss/article/details/6729364 
        
      1. pstree 
      pstree以树结构显示进程$ pstree -p work | grep adsshd(22669)---bash(22670)---ad_preprocess(4551)-+-{ad_preprocess}(4552)  &n</div>
                                      </li>
                                      <li><a href="/article/1073.htm"
                                             title="html input与textarea 值改变事件" target="_blank">html input与textarea 值改变事件</a>
                                          <span class="text-muted">alxw4616</span>
      <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a>
                                          <div>// 文本输入框(input) 文本域(textarea)值改变事件 
      // onpropertychange(IE) oninput(w3c) 
      $('input,textarea').on('propertychange input', function(event) { 
           console.log($(this).val()) 
      }); 
        </div>
                                      </li>
                                      <li><a href="/article/1200.htm"
                                             title="String类的基本用法" target="_blank">String类的基本用法</a>
                                          <span class="text-muted">百合不是茶</span>
      <a class="tag" taget="_blank" href="/search/String/1.htm">String</a>
                                          <div>  
      字符串的用法; 
          // 根据字节数组创建字符串 
      byte[] by = { 'a', 'b', 'c', 'd' };
      String newByteString = new String(by); 
        
        
          1,length()  获取字符串的长度 
        
        &nbs</div>
                                      </li>
                                      <li><a href="/article/1327.htm"
                                             title="JDK1.5 Semaphore实例" target="_blank">JDK1.5 Semaphore实例</a>
                                          <span class="text-muted">bijian1013</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/thread/1.htm">thread</a><a class="tag" taget="_blank" href="/search/java%E5%A4%9A%E7%BA%BF%E7%A8%8B/1.htm">java多线程</a><a class="tag" taget="_blank" href="/search/Semaphore/1.htm">Semaphore</a>
                                          <div>Semaphore类 
             一个计数信号量。从概念上讲,信号量维护了一个许可集合。如有必要,在许可可用前会阻塞每一个 acquire(),然后再获取该许可。每个 release() 添加一个许可,从而可能释放一个正在阻塞的获取者。但是,不使用实际的许可对象,Semaphore 只对可用许可的号码进行计数,并采取相应的行动。 
      S</div>
                                      </li>
                                      <li><a href="/article/1454.htm"
                                             title="使用GZip来压缩传输量" target="_blank">使用GZip来压缩传输量</a>
                                          <span class="text-muted">bijian1013</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/GZip/1.htm">GZip</a>
                                          <div>        启动GZip压缩要用到一个开源的Filter:PJL Compressing Filter。这个Filter自1.5.0开始该工程开始构建于JDK5.0,因此在JDK1.4环境下只能使用1.4.6。 
              PJL Compressi</div>
                                      </li>
                                      <li><a href="/article/1581.htm"
                                             title="【Java范型三】Java范型详解之范型类型通配符" target="_blank">【Java范型三】Java范型详解之范型类型通配符</a>
                                          <span class="text-muted">bit1129</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                          <div>  
        
      定义如下一个简单的范型类, 
        
      package com.tom.lang.generics;
      
      public class Generics<T> {
          private T value;
          public Generics(T  value) {
              this.value = value;
          }
      } </div>
                                      </li>
                                      <li><a href="/article/1708.htm"
                                             title="【Hadoop十二】HDFS常用命令" target="_blank">【Hadoop十二】HDFS常用命令</a>
                                          <span class="text-muted">bit1129</span>
      <a class="tag" taget="_blank" href="/search/hadoop/1.htm">hadoop</a>
                                          <div>1. 修改日志文件查看器 
        
      hdfs oev -i edits_0000000000000000081-0000000000000000089 -o edits.xml
      cat edits.xml 
        
      修改日志文件转储为xml格式的edits.xml文件,其中每条RECORD就是一个操作事务日志 
        2. fsimage查看HDFS中的块信息等 
      &nb</div>
                                      </li>
                                      <li><a href="/article/1835.htm"
                                             title="怎样区别nginx中rewrite时break和last" target="_blank">怎样区别nginx中rewrite时break和last</a>
                                          <span class="text-muted">ronin47</span>
      
                                          <div>在使用nginx配置rewrite中经常会遇到有的地方用last并不能工作,换成break就可以,其中的原理是对于根目录的理解有所区别,按我的测试结果大致是这样的。  
       
       location /    
       {     
           proxy_pass http://test; </div>
                                      </li>
                                      <li><a href="/article/1962.htm"
                                             title="java-21.中兴面试题 输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 , 使其和等于 m" target="_blank">java-21.中兴面试题 输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 , 使其和等于 m</a>
                                          <span class="text-muted">bylijinnan</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                          <div>
      import java.util.ArrayList;
      import java.util.List;
      import java.util.Stack;
      
      public class CombinationToSum {
      
      	/*
      第21 题
      2010 年中兴面试题
      编程求解:
      输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 ,
      使其和等</div>
                                      </li>
                                      <li><a href="/article/2089.htm"
                                             title="eclipse svn 帐号密码修改问题" target="_blank">eclipse svn 帐号密码修改问题</a>
                                          <span class="text-muted">开窍的石头</span>
      <a class="tag" taget="_blank" href="/search/eclipse/1.htm">eclipse</a><a class="tag" taget="_blank" href="/search/SVN/1.htm">SVN</a><a class="tag" taget="_blank" href="/search/svn%E5%B8%90%E5%8F%B7%E5%AF%86%E7%A0%81%E4%BF%AE%E6%94%B9/1.htm">svn帐号密码修改</a>
                                          <div>问题描述: 
           Eclipse的SVN插件Subclipse做得很好,在svn操作方面提供了很强大丰富的功能。但到目前为止,该插件对svn用户的概念极为淡薄,不但不能方便地切换用户,而且一旦用户的帐号、密码保存之后,就无法再变更了。 
      解决思路: 
           删除subclipse记录的帐号、密码信息,重新输入</div>
                                      </li>
                                      <li><a href="/article/2216.htm"
                                             title="[电子商务]传统商务活动与互联网的结合" target="_blank">[电子商务]传统商务活动与互联网的结合</a>
                                          <span class="text-muted">comsci</span>
      <a class="tag" taget="_blank" href="/search/%E7%94%B5%E5%AD%90%E5%95%86%E5%8A%A1/1.htm">电子商务</a>
                                          <div> 
       
            某一个传统名牌产品,过去销售的地点就在某些特定的地区和阶层,现在进入互联网之后,用户的数量群突然扩大了无数倍,但是,这种产品潜在的劣势也被放大了无数倍,这种销售利润与经营风险同步放大的效应,在最近几年将会频繁出现。。。。 
       
             如何避免销售量和利润率增加的</div>
                                      </li>
                                      <li><a href="/article/2343.htm"
                                             title="java 解析 properties-使用 Properties-可以指定配置文件路径" target="_blank">java 解析 properties-使用 Properties-可以指定配置文件路径</a>
                                          <span class="text-muted">cuityang</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/properties/1.htm">properties</a>
                                          <div>#mq 
      xdr.mq.url=tcp://192.168.100.15:61618; 
       
      import java.io.IOException; 
      import java.util.Properties; 
       
       
      public class Test { 
       
       String conf = "log4j.properties"; 
       private static final</div>
                                      </li>
                                      <li><a href="/article/2470.htm"
                                             title="Java核心问题集锦" target="_blank">Java核心问题集锦</a>
                                          <span class="text-muted">darrenzhu</span>
      <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%9F%BA%E7%A1%80/1.htm">基础</a><a class="tag" taget="_blank" href="/search/%E6%A0%B8%E5%BF%83/1.htm">核心</a><a class="tag" taget="_blank" href="/search/%E9%9A%BE%E7%82%B9/1.htm">难点</a>
                                          <div>注意,这里的参考文章基本来自Effective Java和jdk源码 
       
       
      1)ConcurrentModificationException 
      当你用for each遍历一个list时,如果你在循环主体代码中修改list中的元素,将会得到这个Exception,解决的办法是: 
      1)用listIterator, 它支持在遍历的过程中修改元素, 
      2)不用listIterator, new一个</div>
                                      </li>
                                      <li><a href="/article/2724.htm"
                                             title="1分钟学会Markdown语法" target="_blank">1分钟学会Markdown语法</a>
                                          <span class="text-muted">dcj3sjt126com</span>
      <a class="tag" taget="_blank" href="/search/markdown/1.htm">markdown</a>
                                          <div>markdown 简明语法 基本符号 
       
       *,-,+ 3个符号效果都一样,这3个符号被称为 Markdown符号  
       空白行表示另起一个段落 
       `是表示inline代码,tab是用来标记 代码段,分别对应html的code,pre标签 
       换行 
       
       单一段落( <p>) 用一个空白行 
       连续两个空格 会变成一个 <br> 
       连续3个符号,然后是空行</div>
                                      </li>
                                      <li><a href="/article/2851.htm"
                                             title="Gson使用二(GsonBuilder)" target="_blank">Gson使用二(GsonBuilder)</a>
                                          <span class="text-muted">eksliang</span>
      <a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/gson/1.htm">gson</a><a class="tag" taget="_blank" href="/search/GsonBuilder/1.htm">GsonBuilder</a>
                                          <div>转载请出自出处:http://eksliang.iteye.com/blog/2175473 一.概述 
          GsonBuilder用来定制java跟json之间的转换格式 
        二.基本使用 
      实体测试类: 
      温馨提示:默认情况下@Expose注解是不起作用的,除非你用GsonBuilder创建Gson的时候调用了GsonBuilder.excludeField</div>
                                      </li>
                                      <li><a href="/article/2978.htm"
                                             title="报ClassNotFoundException: Didn't find class "...Activity" on path: DexPathList" target="_blank">报ClassNotFoundException: Didn't find class "...Activity" on path: DexPathList</a>
                                          <span class="text-muted">gundumw100</span>
      <a class="tag" taget="_blank" href="/search/android/1.htm">android</a>
                                          <div>有一个工程,本来运行是正常的,我想把它移植到另一台PC上,结果报: 
       
       java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.mobovip.bgr/com.mobovip.bgr.MainActivity}: java.lang.ClassNotFoundException: Didn't f</div>
                                      </li>
                                      <li><a href="/article/3105.htm"
                                             title="JavaWeb之JSP指令" target="_blank">JavaWeb之JSP指令</a>
                                          <span class="text-muted">ihuning</span>
      <a class="tag" taget="_blank" href="/search/javaweb/1.htm">javaweb</a>
                                          <div>  
      要点 
        
      JSP指令简介  
      page指令  
      include指令  
        
      JSP指令简介  
        
      JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。 
      JSP指令的基本语法格式: 
      <%@ 指令 属性名="</div>
                                      </li>
                                      <li><a href="/article/3232.htm"
                                             title="mac上编译FFmpeg跑ios" target="_blank">mac上编译FFmpeg跑ios</a>
                                          <span class="text-muted">啸笑天</span>
      <a class="tag" taget="_blank" href="/search/ffmpeg/1.htm">ffmpeg</a>
                                          <div>1、下载文件:https://github.com/libav/gas-preprocessor, 复制gas-preprocessor.pl到/usr/local/bin/下, 修改文件权限:chmod 777 /usr/local/bin/gas-preprocessor.pl 
      2、安装yasm-1.2.0 
      curl http://www.tortall.net/projects/yasm</div>
                                      </li>
                                      <li><a href="/article/3359.htm"
                                             title="sql mysql oracle中字符串连接" target="_blank">sql mysql oracle中字符串连接</a>
                                          <span class="text-muted">macroli</span>
      <a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/SQL+Server/1.htm">SQL Server</a>
                                          <div>有的时候,我们有需要将由不同栏位获得的资料串连在一起。每一种资料库都有提供方法来达到这个目的: 
       
       MySQL: CONCAT() 
       Oracle: CONCAT(), || 
       SQL Server: + 
       
      CONCAT() 的语法如下: 
      Mysql 中 CONCAT(字串1, 字串2, 字串3, ...): 将字串1、字串2、字串3,等字串连在一起。 
      请注意,Oracle的CON</div>
                                      </li>
                                      <li><a href="/article/3486.htm"
                                             title="Git fatal: unab SSL certificate problem: unable to get local issuer ce rtificate" target="_blank">Git fatal: unab SSL certificate problem: unable to get local issuer ce rtificate</a>
                                          <span class="text-muted">qiaolevip</span>
      <a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0%E6%B0%B8%E6%97%A0%E6%AD%A2%E5%A2%83/1.htm">学习永无止境</a><a class="tag" taget="_blank" href="/search/%E6%AF%8F%E5%A4%A9%E8%BF%9B%E6%AD%A5%E4%B8%80%E7%82%B9%E7%82%B9/1.htm">每天进步一点点</a><a class="tag" taget="_blank" href="/search/git/1.htm">git</a><a class="tag" taget="_blank" href="/search/%E7%BA%B5%E8%A7%82%E5%8D%83%E8%B1%A1/1.htm">纵观千象</a>
                                          <div>// 报错如下: 
      $ git pull origin master 
      fatal: unable to access 'https://git.xxx.com/': SSL certificate problem: unable to get local issuer ce 
      rtificate 
        
      // 原因: 
      由于git最新版默认使用ssl安全验证,但是我们是使用的git未设</div>
                                      </li>
                                      <li><a href="/article/3613.htm"
                                             title="windows命令行设置wifi" target="_blank">windows命令行设置wifi</a>
                                          <span class="text-muted">surfingll</span>
      <a class="tag" taget="_blank" href="/search/windows/1.htm">windows</a><a class="tag" taget="_blank" href="/search/wifi/1.htm">wifi</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0%E6%9C%ACwifi/1.htm">笔记本wifi</a>
                                          <div>还没有讨厌无线wifi的无尽广告么,还在耐心等待它慢慢启动么 
      教你命令行设置 笔记本电脑wifi: 
       
      1、开启wifi命令 
       
      
      netsh wlan set hostednetwork mode=allow ssid=surf8 key=bb123456
      netsh wlan start hostednetwork
      pause
       
       其中pause是等待输入,可以去掉 
       
      2、</div>
                                      </li>
                                      <li><a href="/article/3740.htm"
                                             title="Linux(Ubuntu)下安装sysv-rc-conf" target="_blank">Linux(Ubuntu)下安装sysv-rc-conf</a>
                                          <span class="text-muted">wmlJava</span>
      <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a><a class="tag" taget="_blank" href="/search/sysv-rc-conf/1.htm">sysv-rc-conf</a>
                                          <div>安装:sudo apt-get install sysv-rc-conf 使用:sudo sysv-rc-conf 
      操作界面十分简洁,你可以用鼠标点击,也可以用键盘方向键定位,用空格键选择,用Ctrl+N翻下一页,用Ctrl+P翻上一页,用Q退出。 
        
        
      背景知识 
      sysv-rc-conf是一个强大的服务管理程序,群众的意见是sysv-rc-conf比chkconf</div>
                                      </li>
                                      <li><a href="/article/3867.htm"
                                             title="svn切换环境,重发布应用多了javaee标签前缀" target="_blank">svn切换环境,重发布应用多了javaee标签前缀</a>
                                          <span class="text-muted">zengshaotao</span>
      <a class="tag" taget="_blank" href="/search/javaee/1.htm">javaee</a>
                                          <div>更换了开发环境,从杭州,改变到了上海。svn的地址肯定要切换的,切换之前需要将原svn自带的.svn文件信息删除,可手动删除,也可通过废弃原来的svn位置提示删除.svn时删除。 
        
      然后就是按照最新的svn地址和规范建立相关的目录信息,再将原来的纯代码信息上传到新的环境。然后再重新检出,这样每次修改后就可以看到哪些文件被修改过,这对于增量发布的规范特别有用。 
        
      检出</div>
                                      </li>
                      </ul>
                  </div>
              </div>
          </div>
      
      <div>
          <div class="container">
              <div class="indexes">
                  <strong>按字母分类:</strong>
                  <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                      href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                      href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                      href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                      href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                      href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                      href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                      href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                      href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
              </div>
          </div>
      </div>
      <footer id="footer" class="mb30 mt30">
          <div class="container">
              <div class="footBglm">
                  <a target="_blank" href="/">首页</a> -
                  <a target="_blank" href="/custom/about.htm">关于我们</a> -
                  <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
                  <a target="_blank" href="/sitemap.txt">Sitemap</a> -
                  <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
              </div>
              <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
      <!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
              </div>
          </div>
      </footer>
      <!-- 代码高亮 -->
      <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
      <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
      <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
      <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
      <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>
      
      
      
      
      
      </body>
      
      </html>