2012-07-07T21:25:50の更新内容

programming/tips/check_issubclassof/index.wiki.txt

current previous
1,157 1,15
~
${smdncms:title,型・インスタンスが派生クラスかどうかを調べる}
${smdncms:title,型情報から派生クラスかどうかを調べる}
~
${smdncms:keywords,VB.NET,C#,IsSubclassOf,IsAssignableFrom,Type,型,派生クラス,継承関係,is演算子,TypeOf演算子}
${smdncms:keywords,VB.NET,C#,IsSubclassOf,IsAssignableFrom,Type,型,派生クラス}
 
${smdncms:tags,api/.net,lang/vb,lang/c#}
${smdncms:tags,api/.net,lang/vb,lang/c#}
 
${smdncms:document_versions,codelang=cs,codelang=vb}
${smdncms:document_versions,codelang=cs,codelang=vb}
 

        

        
~
型・インスタンスが継承関係にあるかどうか、他の型に代入可能かどうかを判定する方法について。
&msdn(netfx,type,System.Type){Typeクラス};の&msdn(netfx,member,System.Type.IsSubclassOf){IsSubclassOfメソッド};を使うことで、型情報から型があるクラスから派生するものかどうかを判定できる。 ただし、このメソッドでは同じ型を表す場合はFalseを返される点に注意が必要で、同じクラスを表すかどうかを判定する場合は、&msdn(netfx,member,System.Type.Equals){Type.Equalsメソッド};もしくはis演算子(C#)やIs演算子(VB.NET)を使って判定する必要がある。
 

        

        
 
-関連するページ
-関連するページ
+
#ls2_1(programming/netfx/conversion)
+
--[[programming/vb.net/diff_7.xto8/04_isnot_operator]] (VB)
 
--[[programming/tips/plugin_assembly]]
--[[programming/tips/plugin_assembly]]
 

        

        
 
#googleadunit
#googleadunit
 

        

        
+
*インスタンスと継承関係・代入可能性の判定
+
is演算子(C#)やTypeOf演算子(VB)を使うことで、インスタンスがある型と同じか、もしくはある型から派生するものかどうかを判定できる。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Base {}
+
class Class1 : Base {}
+
class Class2 : Class1 {}
+
class Class3 {}
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    object instClass1 = new Class1();
+
    object instClass2 = new Class2();
+
    object instClass3 = new Class3();
+

          
+
    Console.WriteLine("instClass1 is Base = {0}", instClass1 is Base);
+
    Console.WriteLine("instClass2 is Base = {0}", instClass2 is Base);
+
    Console.WriteLine("instClass3 is Base = {0}", instClass3 is Base);
+
    Console.WriteLine("instClass2 is Class1 = {0}", instClass2 is Class1);
+
    Console.WriteLine("instClass1 is Class2 = {0}", instClass1 is Class2);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
instClass1 is Base = True
+
instClass2 is Base = True
+
instClass3 is Base = False
+
instClass2 is Class1 = True
+
instClass1 is Class2 = False
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Base : End Class
+
Class Class1 : Inherits Base : End Class
+
Class Class2 : Inherits Class1 : End Class
+
Class Class3 : End Class
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim instClass1 As Object = New Class1()
+
    Dim instClass2 As Object = New Class2()
+
    Dim instClass3 As Object = New Class3()
+

          
+
    Console.WriteLine("TypeOf instClass1 Is Base = {0}", TypeOf instClass1 Is Base)
+
    Console.WriteLine("TypeOf instClass2 Is Base = {0}", TypeOf instClass2 Is Base)
+
    Console.WriteLine("TypeOf instClass3 Is Base = {0}", TypeOf instClass3 Is Base)
+
    Console.WriteLine("TypeOf instClass2 Is Class1 = {0}", TypeOf instClass2 Is Class1)
+
    Console.WriteLine("TypeOf instClass1 Is Class2 = {0}", TypeOf instClass1 Is Class2)
+
  End Sub
+
End Class
+
}}
+

          
+
#prompt(実行結果){{
+
TypeOf instClass1 Is Base = True
+
TypeOf instClass2 Is Base = True
+
TypeOf instClass3 Is Base = False
+
TypeOf instClass2 Is Class1 = True
+
TypeOf instClass1 Is Class2 = False
+
}}
+
#tabpage-end
+

          
+
継承関係ではなく実装しているインターフェイスなど、インスタンスが別の型の変数に''代入可能かどうか''(型に互換性があるか)を判定したい場合も、is演算子(C#)やTypeOf演算子(VB)を使うことが出来る。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
interface IIfc1 {}
+
interface IIfc2 {}
+
class Class1 : IIfc1 {}
+
class Class2 : IIfc2 {}
+

          
+
class Sample {
+
  public static void Main()
+
  {
+
    object instClass1 = new Class1();
+
    object instClass2 = new Class2();
+

          
+
    Console.WriteLine("instClass1 is IIfc1 = {0}", instClass1 is IIfc1);
+
    Console.WriteLine("instClass2 is IIfc2 = {0}", instClass2 is IIfc2);
+
    Console.WriteLine("instClass1 is IIfc2 = {0}", instClass1 is IIfc2);
+
    Console.WriteLine("instClass2 is IIfc1 = {0}", instClass2 is IIfc1);
+
    Console.WriteLine("instClass1 is int = {0}", instClass1 is int);
+
    Console.WriteLine("instClass1 is object = {0}", instClass1 is object);
+
  }
+
}
+
}}
+

          
+
#prompt(実行結果){{
+
instClass1 is IIfc1 = True
+
instClass2 is IIfc2 = True
+
instClass1 is IIfc2 = False
+
instClass2 is IIfc1 = False
+
instClass1 is int = False
+
instClass1 is object = True
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Interface IIfc1 : End Interface
+
Interface IIfc2 : End Interface
+
Class Class1 : Implements IIfc1 : End Class
+
Class Class2 : Implements IIfc2 : End Class
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim instClass1 As Object = New Class1()
+
    Dim instClass2 As Object = New Class2()
+

          
+
    Console.WriteLine("TypeOf instClass1 Is IIfc1 = {0}", TypeOf instClass1 Is IIfc1)
+
    Console.WriteLine("TypeOf instClass2 Is IIfc2 = {0}", TypeOf instClass2 Is IIfc2)
+
    Console.WriteLine("TypeOf instClass1 Is IIfc2 = {0}", TypeOf instClass1 Is IIfc2)
+
    Console.WriteLine("TypeOf instClass2 Is IIfc1 = {0}", TypeOf instClass2 Is IIfc1)
+
    Console.WriteLine("TypeOf instClass1 Is Integer = {0}", TypeOf instClass1 Is Integer)
+
    Console.WriteLine("TypeOf instClass1 Is Object = {0}", TypeOf instClass1 Is Object)
+
  End Sub
+
End Class
+
}}
+

          
+
#prompt(実行結果){{
+
TypeOf instClass1 Is IIfc1 = True
+
TypeOf instClass2 Is IIfc2 = True
+
TypeOf instClass1 Is IIfc2 = False
+
TypeOf instClass2 Is IIfc1 = False
+
TypeOf instClass1 Is Integer = False
+
TypeOf instClass1 Is Object = True
+
}}
+
#tabpage-end
+

          
+
*型情報と継承関係・代入可能性の判定
+
&msdn(netfx,type,System.Type){Typeクラス};の&msdn(netfx,member,System.Type.IsSubclassOf){IsSubclassOfメソッド};を使うことで、型情報から型があるクラスから派生するものかどうかを判定できる。 ただし、このメソッドでは同じ型を表す場合はFalseを返される点に注意が必要で、同じクラスを表すかどうかを判定する場合は、&msdn(netfx,member,System.Type.Equals){Type.Equalsメソッド};もしくはis演算子(C#)やTypeOf演算子(VB)を使って判定する必要がある。
+

          
 
#tabpage(C#)
#tabpage(C#)
 
#code(cs){{
#code(cs){{
 
using System;
using System;

programming/tips/unicode_bom_netfx/index.wiki.txt

current previous
1,7 1,7
 
${smdncms:title,System.Text.EncodingのBOMありなしの制御}
${smdncms:title,System.Text.EncodingのBOMありなしの制御}
~
${smdncms:keywords,C#,Encoding,BOM,UTF,Unicode,StreamWriter,BinaryWriter,GetPreamble,GetBytes}
${smdncms:keywords,C#,Encoding,BOM,UTF,Unicode}
 
${smdncms:tags,lang/c#,api/.net}
${smdncms:tags,lang/c#,api/.net}
~
&msdn(netfx,type,System.Text.Encoding){System.Text.Encoding};を使う場合のBOMあり/なしの指定方法、および&msdn(netfx,type,System.IO.StreamWriter){System.IO.StreamWriter};内部の動作について。
System.Text.Encodingを使う場合のBOMあり/なしの指定方法について。
 
#googleadunit
#googleadunit
 

        

        
 
*StreamWriterでBOMが書き込まれる条件
*StreamWriterでBOMが書き込まれる条件
14,7 14,6
 
var text = "日本語";
var text = "日本語";
 

        

        
 
using (var stream = new MemoryStream()) {
using (var stream = new MemoryStream()) {
+
  // Encodingを指定しない
 
  using (var writer = new StreamWriter(stream)) {
  using (var writer = new StreamWriter(stream)) {
 
    writer.Write(text);
    writer.Write(text);
 
  }
  }
22,7 21,6
 
}
}
 

        

        
 
using (var stream = new MemoryStream()) {
using (var stream = new MemoryStream()) {
+
  // Encoding.UTF8を指定する
 
  using (var writer = new StreamWriter(stream, Encoding.UTF8)) {
  using (var writer = new StreamWriter(stream, Encoding.UTF8)) {
 
    writer.Write(text);
    writer.Write(text);
 
  }
  }
39,7 37,6
 

        

        
 
#code(cs){{
#code(cs){{
 
using (var stream = new MemoryStream()) {
using (var stream = new MemoryStream()) {
+
  // encoderShouldEmitUTF8Identifierがfalseの(BOMを出力しない)UTF8Encodingを指定する
 
  using (var writer = new StreamWriter(stream, new UTF8Encoding(false))) {
  using (var writer = new StreamWriter(stream, new UTF8Encoding(false))) {
 
    writer.Write(text);
    writer.Write(text);
 
  }
  }
47,7 44,6
 
}
}
 

        

        
 
using (var stream = new MemoryStream()) {
using (var stream = new MemoryStream()) {
+
  // encoderShouldEmitUTF8Identifierがtrueの(BOMを出力する)UTF8Encodingを指定する
 
  using (var writer = new StreamWriter(stream, new UTF8Encoding(true))) {
  using (var writer = new StreamWriter(stream, new UTF8Encoding(true))) {
 
    writer.Write(text);
    writer.Write(text);
 
  }
  }
60,79 56,57
 
EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
 
}}
}}
 

        

        
~
*StreamWriter内部の動作
このようにBOMが書き込まれるかどうかは、UTF8Encoding(およびUnicodeEncoding、UTF32Encoding)のコンストラクタに指定する値によって決まる。 具体的には、StreamWriterがBOMを出力するかどうかは、[[Encoding.GetPreambleメソッド:http://msdn.microsoft.com/ja-jp/library/system.text.encoding.getpreamble(VS.80).aspx]]が返す値次第となる(と思われる)。
+
このようにBOMが書き込まれるかどうかは、UTF8Encoding(およびUnicodeEncoding、UTF32Encoding)のコンストラクタに指定する値によって決まる。
 

        

        
~
より具体的には、StreamWriterがどのようなBOMを出力するかは[[Encoding.GetPreambleメソッド:http://msdn.microsoft.com/ja-jp/library/system.text.encoding.getpreamble(VS.80).aspx]]が返す値次第となる。 このメソッドは、エンコーディングに対応するBOMのバイト列を返す。 encoderShouldEmitUTF8Identifierにfalseになっていれば、このメソッドは空のバイト列を返す。 StreamWriterは、ストリームへ書き込む前にまずEncoding.GetPreambleメソッドを呼び出してBOMを取得し、その内容をストリームへ書き込む。 このときEncoding.GetPreambleメソッドが空のバイト列を返す場合、当然ストリームにもBOMは書き込まれない。
*BOMあり/なしの指定方法
-
StreamWriterがBOMを出力するようにするには、Encoding.GetPreambleメソッドがBOMを返すようなEncodingのインスタンスを渡す必要がある。
-

          
-
また、BinaryWriterなどはEncoding.GetPreambleメソッドの戻り値に関わらずBOMは書き込まれないので、例えばBinaryWriterでBOMありの出力を行いたい場合は、Writeメソッドを使ってEncoding.GetPreambleメソッドの戻り値を書き込む必要がある。
-

          
-
次のサンプルは、UTF8Encoding、UnicodeEncoding、UTF32Encodingの各コンストラクタにそれぞれ異なる値を指定して作成したインスタンスを使って、Encoding.GetPreambleメソッドが返す値と、BinaryWriter、StreamWriterに書き込まれる内容を比較したもの。
-

          
-
#code(cs){{
-
const bool bigEndian = true;
-
const bool littleEndian = false;
-
const bool bom = true;
-

          
-
var unicodeEncodings = new Dictionary<string, Encoding>() {
-
  {"UTF-8",                     new UTF8Encoding(!bom)},
-
  {"UTF-8 (BOM)",               new UTF8Encoding( bom)},
-
  {"Encoding.UTF8",             Encoding.UTF8},
-
  {"UTF-16LE",                  new UnicodeEncoding(littleEndian, !bom)},
-
  {"UTF-16BE",                  new UnicodeEncoding(   bigEndian, !bom)},
-
  {"UTF-16LE (BOM)",            new UnicodeEncoding(littleEndian,  bom)},
-
  {"UTF-16BE (BOM)",            new UnicodeEncoding(   bigEndian,  bom)},
-
  {"Encoding.Unicode",          Encoding.Unicode},
-
  {"Encoding.BigEndianUnicode", Encoding.BigEndianUnicode},
-
  {"UTF-32LE",                  new UTF32Encoding(littleEndian, !bom)},
-
  {"UTF-32BE",                  new UTF32Encoding(   bigEndian, !bom)},
-
  {"UTF-32LE (BOM)",            new UTF32Encoding(littleEndian,  bom)},
-
  {"UTF-32BE (BOM)",            new UTF32Encoding(   bigEndian,  bom)},
-
  {"Encoding.UTF32",            Encoding.UTF32},
-
};
 

        

        
~
[[.NET Framework Developer Center:System.System.IO に関する FAQ - テキスト ファイルのエンコード方式を調べる方法はありますか。:http://msdn.microsoft.com/ja-jp/netframework/aa569610.aspx#Question2]]より
var text = "日本語";
+
>StreamWriter クラスも Encoding::GetPreamble() メソッドを呼び出し、テキスト ファイルの先頭にこのバイト列を書き込みます。これは優れた機能です。ユーザーがテキスト ファイルのエンコード方式をはっきり特定できるからです。ただし、弊社の多くの開発者は C 言語の知識を持っているため、テキスト ファイルの先頭に UTF-8 の Unicode BOM があると混乱してしまいました。また、Unicode に対応していないエディタ (vi、以前のバージョンの Emacs など) では扱いにくいこともあります。このため、StreamWriter クラスで既定で使用される UTF8Encoding では、GetPreamble メソッドから空のバイト列が返されます。UTF-8 ファイルに Unicode BOM を書き込むには、コード内で Encoding.UTF8 を明示的に指定します。
 

        

        
~
*BOMあり/なしの指定方法
foreach (var pair in unicodeEncodings) {
~
StreamWriterがBOMを出力するようにするには、Encoding.GetPreambleメソッドがBOMを返す(encoderShouldEmitUTF8Identifierがtrueの)Encodingのインスタンスを渡す必要がある。
  var encoding = pair.Value;
 

        

        
~
一方、BinaryWriterなどはEncoding.GetPreambleメソッドの戻り値に関わらずBOMを出力しない。 また、Encoding.GetBytesも常に
  Console.WriteLine(pair.Key);
~
BOMを含まないバイト列を返す。 そのため、BinaryWriterやEncoding.GetBytesでBOMを出力させたい場合は、Encoding.GetPreambleメソッドの戻り値を取得して書き込むなどする必要がある。
  Console.WriteLine("  BOM: {0}", BitConverter.ToString(encoding.GetPreamble()));
 

        

        
~
次のサンプルでは、UTF8Encoding、UnicodeEncoding、UTF32Encodingの各コンストラクタにそれぞれ異なる値を指定して作成したインスタンスを使い、Encoding.GetPreambleメソッドが返す値と、Encoding.GetBytesが返す値、BinaryWriterおよびStreamWriterに書き込まれる内容を比較している。 (BinaryWriterは先頭に文字列のバイト長を書き込む点に注意)
  using (var stream = new MemoryStream()) {
-
    using (var writer = new BinaryWriter(stream, encoding)) {
-
      writer.Write(text);
-
    }
-
    Console.WriteLine("  BinaryWriter: {0}", BitConverter.ToString(stream.ToArray()));
-
  }
 

        

        
~
#code(cs){{
  using (var stream = new MemoryStream()) {
~
using System;
    using (var writer = new StreamWriter(stream, encoding)) {
~
using System.Collections.Generic;
      writer.Write(text);
+
using System.IO;
+
using System.Text;
+

          
+
class UnicodePreamble {
+
  public static void Main()
+
  {
+
    const bool bigEndian = true;
+
    const bool littleEndian = false;
+
    const bool bom = true;
+

          
+
    var unicodeEncodings = new Dictionary<string, Encoding>() {
+
      {"UTF-8",                     new UTF8Encoding(!bom)},
+
      {"UTF-8 (BOM)",               new UTF8Encoding( bom)},
+
      {"Encoding.UTF8",             Encoding.UTF8},
+
      {"UTF-16LE",                  new UnicodeEncoding(littleEndian, !bom)},
+
      {"UTF-16BE",                  new UnicodeEncoding(   bigEndian, !bom)},
+
      {"UTF-16LE (BOM)",            new UnicodeEncoding(littleEndian,  bom)},
+
      {"UTF-16BE (BOM)",            new UnicodeEncoding(   bigEndian,  bom)},
+
      {"Encoding.Unicode",          Encoding.Unicode},
+
      {"Encoding.BigEndianUnicode", Encoding.BigEndianUnicode},
+
      {"UTF-32LE",                  new UTF32Encoding(littleEndian, !bom)},
+
      {"UTF-32BE",                  new UTF32Encoding(   bigEndian, !bom)},
+
      {"UTF-32LE (BOM)",            new UTF32Encoding(littleEndian,  bom)},
+
      {"UTF-32BE (BOM)",            new UTF32Encoding(   bigEndian,  bom)},
+
      {"Encoding.UTF32",            Encoding.UTF32},
+
    };
+

          
+
    var text = "日本語";
+

          
+
    foreach (var pair in unicodeEncodings) {
+
      var encoding = pair.Value;
+

          
+
      Console.WriteLine(pair.Key);
+
      Console.WriteLine("  BOM: {0}", BitConverter.ToString(encoding.GetPreamble()));
+

          
+
      // StreamWriter
+
      using (var stream = new MemoryStream()) {
+
        using (var writer = new StreamWriter(stream, encoding)) {
+
          writer.Write(text);
+
        }
+
        Console.WriteLine("  StreamWriter     :    {0}", BitConverter.ToString(stream.ToArray()));
+
      }
+

          
+
      // Encoding.GetBytes
+
      Console.WriteLine("  Encoding.GetBytes:    {0}", BitConverter.ToString(encoding.GetBytes(text)));
+

          
+
      // BinaryWriter
+
      using (var stream = new MemoryStream()) {
+
        using (var writer = new BinaryWriter(stream, encoding)) {
+
          writer.Write(text);
+
        }
+
        Console.WriteLine("  BinaryWriter     : {0}", BitConverter.ToString(stream.ToArray()));
+
      }
 
    }
    }
-
    Console.WriteLine("  StreamWriter: {0}", BitConverter.ToString(stream.ToArray()));
 
  }
  }
 
}
}
 
}}
}}
140,73 114,59
 
#prompt(実行結果){{
#prompt(実行結果){{
 
UTF-8
UTF-8
 
  BOM: 
  BOM: 
~
  StreamWriter     :    E6-97-A5-E6-9C-AC-E8-AA-9E
  BinaryWriter: 09-E6-97-A5-E6-9C-AC-E8-AA-9E
~
  Encoding.GetBytes:    E6-97-A5-E6-9C-AC-E8-AA-9E
  StreamWriter: E6-97-A5-E6-9C-AC-E8-AA-9E
+
  BinaryWriter     : 09-E6-97-A5-E6-9C-AC-E8-AA-9E
 
UTF-8 (BOM)
UTF-8 (BOM)
 
  BOM: EF-BB-BF
  BOM: EF-BB-BF
~
  StreamWriter     :    EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
  BinaryWriter: 09-E6-97-A5-E6-9C-AC-E8-AA-9E
~
  Encoding.GetBytes:    E6-97-A5-E6-9C-AC-E8-AA-9E
  StreamWriter: EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
+
  BinaryWriter     : 09-E6-97-A5-E6-9C-AC-E8-AA-9E
 
Encoding.UTF8
Encoding.UTF8
 
  BOM: EF-BB-BF
  BOM: EF-BB-BF
~
  StreamWriter     :    EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
  BinaryWriter: 09-E6-97-A5-E6-9C-AC-E8-AA-9E
~
  Encoding.GetBytes:    E6-97-A5-E6-9C-AC-E8-AA-9E
  StreamWriter: EF-BB-BF-E6-97-A5-E6-9C-AC-E8-AA-9E
+
  BinaryWriter     : 09-E6-97-A5-E6-9C-AC-E8-AA-9E
 
UTF-16LE
UTF-16LE
 
  BOM: 
  BOM: 
~
  StreamWriter     :    E5-65-2C-67-9E-8A
  BinaryWriter: 06-E5-65-2C-67-9E-8A
~
  Encoding.GetBytes:    E5-65-2C-67-9E-8A
  StreamWriter: E5-65-2C-67-9E-8A
+
  BinaryWriter     : 06-E5-65-2C-67-9E-8A
 
UTF-16BE
UTF-16BE
 
  BOM: 
  BOM: 
~
  StreamWriter     :    65-E5-67-2C-8A-9E
  BinaryWriter: 06-65-E5-67-2C-8A-9E
~
  Encoding.GetBytes:    65-E5-67-2C-8A-9E
  StreamWriter: 65-E5-67-2C-8A-9E
+
  BinaryWriter     : 06-65-E5-67-2C-8A-9E
 
UTF-16LE (BOM)
UTF-16LE (BOM)
 
  BOM: FF-FE
  BOM: FF-FE
~
  StreamWriter     :    FF-FE-E5-65-2C-67-9E-8A
  BinaryWriter: 06-E5-65-2C-67-9E-8A
~
  Encoding.GetBytes:    E5-65-2C-67-9E-8A
  StreamWriter: FF-FE-E5-65-2C-67-9E-8A
+
  BinaryWriter     : 06-E5-65-2C-67-9E-8A
 
UTF-16BE (BOM)
UTF-16BE (BOM)
 
  BOM: FE-FF
  BOM: FE-FF
~
  StreamWriter     :    FE-FF-65-E5-67-2C-8A-9E
  BinaryWriter: 06-65-E5-67-2C-8A-9E
~
  Encoding.GetBytes:    65-E5-67-2C-8A-9E
  StreamWriter: FE-FF-65-E5-67-2C-8A-9E
+
  BinaryWriter     : 06-65-E5-67-2C-8A-9E
 
Encoding.Unicode
Encoding.Unicode
 
  BOM: FF-FE
  BOM: FF-FE
~
  StreamWriter     :    FF-FE-E5-65-2C-67-9E-8A
  BinaryWriter: 06-E5-65-2C-67-9E-8A
~
  Encoding.GetBytes:    E5-65-2C-67-9E-8A
  StreamWriter: FF-FE-E5-65-2C-67-9E-8A
+
  BinaryWriter     : 06-E5-65-2C-67-9E-8A
 
Encoding.BigEndianUnicode
Encoding.BigEndianUnicode
 
  BOM: FE-FF
  BOM: FE-FF
~
  StreamWriter     :    FE-FF-65-E5-67-2C-8A-9E
  BinaryWriter: 06-65-E5-67-2C-8A-9E
~
  Encoding.GetBytes:    65-E5-67-2C-8A-9E
  StreamWriter: FE-FF-65-E5-67-2C-8A-9E
+
  BinaryWriter     : 06-65-E5-67-2C-8A-9E
 
UTF-32LE
UTF-32LE
 
  BOM: 
  BOM: 
~
  StreamWriter     :    E5-65-00-00-2C-67-00-00-9E-8A-00-00
  BinaryWriter: 0C-E5-65-00-00-2C-67-00-00-9E-8A-00-00
~
  Encoding.GetBytes:    E5-65-00-00-2C-67-00-00-9E-8A-00-00
  StreamWriter: E5-65-00-00-2C-67-00-00-9E-8A-00-00
+
  BinaryWriter     : 0C-E5-65-00-00-2C-67-00-00-9E-8A-00-00
 
UTF-32BE
UTF-32BE
 
  BOM: 
  BOM: 
~
  StreamWriter     :    00-00-65-E5-00-00-67-2C-00-00-8A-9E
  BinaryWriter: 0C-00-00-65-E5-00-00-67-2C-00-00-8A-9E
~
  Encoding.GetBytes:    00-00-65-E5-00-00-67-2C-00-00-8A-9E
  StreamWriter: 00-00-65-E5-00-00-67-2C-00-00-8A-9E
+
  BinaryWriter     : 0C-00-00-65-E5-00-00-67-2C-00-00-8A-9E
 
UTF-32LE (BOM)
UTF-32LE (BOM)
 
  BOM: FF-FE-00-00
  BOM: FF-FE-00-00
~
  StreamWriter     :    FF-FE-00-00-E5-65-00-00-2C-67-00-00-9E-8A-00-00
  BinaryWriter: 0C-E5-65-00-00-2C-67-00-00-9E-8A-00-00
~
  Encoding.GetBytes:    E5-65-00-00-2C-67-00-00-9E-8A-00-00
  StreamWriter: FF-FE-00-00-E5-65-00-00-2C-67-00-00-9E-8A-00-00
+
  BinaryWriter     : 0C-E5-65-00-00-2C-67-00-00-9E-8A-00-00
 
UTF-32BE (BOM)
UTF-32BE (BOM)
 
  BOM: 00-00-FE-FF
  BOM: 00-00-FE-FF
~
  StreamWriter     :    00-00-FE-FF-00-00-65-E5-00-00-67-2C-00-00-8A-9E
  BinaryWriter: 0C-00-00-65-E5-00-00-67-2C-00-00-8A-9E
~
  Encoding.GetBytes:    00-00-65-E5-00-00-67-2C-00-00-8A-9E
  StreamWriter: 00-00-FE-FF-00-00-65-E5-00-00-67-2C-00-00-8A-9E
+
  BinaryWriter     : 0C-00-00-65-E5-00-00-67-2C-00-00-8A-9E
 
Encoding.UTF32
Encoding.UTF32
 
  BOM: FF-FE-00-00
  BOM: FF-FE-00-00
~
  StreamWriter     :    FF-FE-00-00-E5-65-00-00-2C-67-00-00-9E-8A-00-00
  BinaryWriter: 0C-E5-65-00-00-2C-67-00-00-9E-8A-00-00
~
  Encoding.GetBytes:    E5-65-00-00-2C-67-00-00-9E-8A-00-00
  StreamWriter: FF-FE-00-00-E5-65-00-00-2C-67-00-00-9E-8A-00-00
+
  BinaryWriter     : 0C-E5-65-00-00-2C-67-00-00-9E-8A-00-00
 
}}
}}
 

        

        

programming/tips/wpl_to_m3u/index.wiki.txt

current previous
1,148 1,81
~
${smdncms:title,WPL形式のプレイリストをM3U形式に変換する}
${smdncms:title,wpl形式のプレイリストをm3u形式に変換する}
~
${smdncms:keywords,wpl,m3u,フォーマット,変換}
${smdncms:keywords,wpl,m3u,変換}
~
${smdncms:tags,plat/win}
${smdncms:tags,lang/perl,plat/win}
~

          
Windows Media Player 9.0以降で使用されるプレイリストファイル(wpl形式)を、Linux等でも使用できるようにm3u形式に変換する。
+
各プレイリストファイルのフォーマットと、WPL形式・M3U形式を相互に変換する方法。
 

        

        
 
*プレイリストのフォーマット
*プレイリストのフォーマット
~
**WPL形式
Windows Media Player 9.0以降で使用されるプレイリスト(wpl形式)は、下記のような形式のXMLファイルとなっている(media要素にはsrc以外の属性が存在する場合もある)。
~
Windows Media Player 9.0以降で使用されるWPL形式のプレイリストは、下記のような形式のXMLファイルとなっている。
#code(xml){{
+

          
+
#code(xml,WPL形式のプレイリストの例){{
 
<smil>
<smil>
 
    <head>
    <head>
-
        <meta name="Generator" content="Microsoft Windows Media Player -- 9.0.0.2980"/>
-
        <author></author>
 
        <title>プレイリストのタイトル</title>
        <title>プレイリストのタイトル</title>
 
    </head>
    </head>
 
    <body>
    <body>
 
        <seq>
        <seq>
~
            <media src="Album\Track1.wma"/>
            <media src="Sample Album\01 xxxx.wma"/>
~
            <media src="Album\Track2.wma"/>
            <media src="Sample Album\02 yyyy.wma"/>
~
            <media src="C:\Documents and Settings\User\My Music\Album\Track3.wma"/>
            <media src="Sample Album\03 zzzz.wma"/>
 
        </seq>
        </seq>
 
    </body>
    </body>
 
</smil>
</smil>
 
}}
}}
 

        

        
~
/smil/body/seq/media要素の内容がプレイリストに含まれる各トラックとなり、src属性には各トラックのファイルパスを指定する。 ファイルパスは、相対パス・絶対パスどちらでもよい。 なお、ここで挙げた例は簡略化したもので、実際にはトラック情報以外にも様々な情報を記述することが出来る。
また、m3u形式の(もっともシンプルな)フォーマットは下記のような形式のテキストファイルとなっている(単にファイル名を列挙しただけ)。
~

          
#code{{
~
**M3U形式
Sample Album/01 xxxx.wma
~
M3U形式のプレイリストは、下記のような形式のテキストファイルとなっている。
Sample Album/02 yyyy.wma
~

          
Sample Album/03 zzzz.wma
+
#code(,M3U形式のプレイリストの例){{
+
Album/Track1.wma
+
Album/Track2.wma
+
Album/Track3.wma
+
http://music.example.com/extratracks.m3u
+
http://music.example.com/sample.mp3
 
}}
}}
 

        

        
~
このように、各トラックのファイルパスを順に並べて指定する。 ファイルパスは、相対パス・絶対パスどちらでもよい。 URLを指定してウェブ上のファイルを指定したり、外部のプレイリストを含めることも出来る。
wpl形式のファイルから、media要素のsrc属性のみを取り出してファイルとして書き出せば、m3u形式のプレイリストとなる。
 

        

        
~
拡張されたM3U形式の場合はより多くの情報を記述することが出来、トラックの長さ、タイトルを記述することが出来る。 拡張されたM3U形式であることを表すために、必ず1行目に"#EXTM3U"と記述しなければならない。 また、各トラックの情報を記述する場合は、ファイルパスの直前に"#EXTINF"から始まる行を既述し、トラックの長さ(秒単位)と、トラックのタイトルを記述する。 "#EXTINF"の行は省略可能。
*Perlで作成した変換スクリプト
-
wpl形式のプレイリストをm3u形式に変換するPerlスクリプト。 XMLパーサ等を使用しない手抜き版、src属性の内容は正規表現で取得している。 第一引数に変換元wpl形式のプレイリストファイルのパス、第二引数に変換後(m3u形式)のプレイリストファイルのパスを指定して実行する。
-
#code(pl){{
-
#!/usr/bin/perl
 

        

        
~
#code(,拡張されたM3U形式のプレイリストの例){{
#
~
#EXTM3U
# wpl2m3u.pl
-
# 
-
# Usage: wpl2m3u.pl source.wpl dest.m3u
-
#
 

        

        
~
#EXTINF:185,foo artist - SONG OF HOGE
my $path_win = quotemeta( 'E:\\Musics\\' );
~
Album/Track1.wma
my $path_unix = '/home/santamarta/musics/';
 

        

        
~
#EXTINF:185,foo artist - SONG OF HOGE (instrumental)
# wpl形式のファイルを読み込む
~
Album/Track2.wma
open( INPUT, "<$ARGV[0]" ) or die "couldn't open source '$ARGV[0]'";
 

        

        
~
Album/Track3.wma
my @lines = <INPUT>;
+
}}
 

        

        
~
*変換スクリプト
close( INPUT );
+
WPL形式・M3U形式のプレイリストを相互に変換する簡易スクリプト。 プレイリストをメモ帳等で開いて、コピーしたものを貼り付けた後変換ボタンを押してください。
 

        

        
~
#javascript(csview,noscript=実行するにはJavaScriptを有効にしてください){{
# m3u形式のファイルを作成する
~
function getLines(id)
open( OUTPUT, ">$ARGV[1]" ) or die "couldn't open destination '$ARGV[1]'";
+
{
+
  return $(id).val().replace(/\r\n|\r/g, "\n").split('\n');
+
}
 

        

        
~
function convertWPL2M3U()
foreach $line ( @lines ) {
~
{
  # media要素にマッチする行を取得する
~
  var lines = getLines("#wpl2m3u_wpl");
  if ( $line =~ /^\s+\<media\ssrc\=\"([^\"]+)\".+$/ ) {
~
  var m3u = "#EXTM3U\r\n";
    my $path = $1;
+

          
+
  for (var i = 0; i < lines.length; i++) {
+
    var match = lines[i].match(/^\s+\<media\ssrc\=\"([^\"]+)\".+$/);
+

          
+
    if (match) {
+
      var src = match[1];
+

          
+
      src = src.replace(/&gt;/g, '>');
+
      src = src.replace(/&lt;/g, '<');
+
      src = src.replace(/&apos;/g, "'");
+
      src = src.replace(/&quot;/g, '"');
+
      src = src.replace(/&amp;/g, '&');
+

          
+
      m3u += src;
+
      m3u += "\r\n";
+
    }
+
  }
 

        

        
~
  $("#wpl2m3u_m3u").val(m3u);
    # パスをWindows形式からUNIX形式に変換
~
}
    $path =~ s/$path_win/$path_unix/o;
-
    $path =~ s/\\/\//g;
 

        

        
~
function convertM3U2WPL()
    # エスケープされた文字を復元
~
{
    $path =~ s/\&gt\;/\>/g;
~
  var lines = getLines("#m3u2wpl_m3u");
    $path =~ s/\&lt\;/\</g;
~
  var wpl = '<?wpl version="1.0"?>\r\n<smil>\r\n';
    $path =~ s/\&apos\;/\'/g;
~

          
    $path =~ s/\&quot\;/\"/g;
~
  wpl += '  <head>\r\n'
    $path =~ s/\&amp\;/\&/g;
+
  wpl += '    <meta name="Generator" content="http://smdn.jp/programming/tips/wpl_to_m3u/"/>\r\n'
+
  wpl += '  </head>\r\n'
+
  wpl += '  <body>\r\n'
+
  wpl += '    <seq>\r\n'
+

          
+
  for (var i = 0; i < lines.length; i++) {
+
    if (lines[i] == '')
+
      continue;
+
    if (lines[i].indexOf('#EXTM3U') == 0)
+
      continue;
+
    if (lines[i].indexOf('#EXTINF') == 0)
+
      continue;
+

          
+
    var src = lines[i];
+

          
+
    src = src.replace(/&/g, '&amp;');
+
    src = src.replace(/\>/g, '&gt;');
+
    src = src.replace(/\</g, '&lt;');
+
    src = src.replace(/'/g, "&apos;");
+
    src = src.replace(/"/g, '&quot;');
 

        

        
~
    wpl += '      <media src="' + src + '"/>\r\n';
    print OUTPUT "$path\n";
 
  }
  }
+

          
+
  wpl += '    </seq>\r\n'
+
  wpl += '  </body>\r\n'
+
  wpl += '</smil>\r\n'
+

          
+
  $("#m3u2wpl_wpl").val(wpl);
 
}
}
+
}}
+

          
+
**WPL→M3U
+
#html{{
+
<form action="">
+
<label>WPL:</label><br/>
+
<textarea id="wpl2m3u_wpl" cols="80" rows="10"></textarea><br/>
+
<input type="button" value="↓M3Uに変換↓" onclick="convertWPL2M3U();"/><br/>
+
<label>M3U:</label><br/>
+
<textarea id="wpl2m3u_m3u" cols="80" rows="10"></textarea><br/>
+
</form>
+
}}
 

        

        
~
**M3U→WPL
close( OUTPUT );
+
#html{{
+
<form action="">
+
<label>M3U:</label><br/>
+
<textarea id="m3u2wpl_m3u" cols="80" rows="10"></textarea><br/>
+
<input type="button" value="↓WPLに変換↓" onclick="convertM3U2WPL();"/><br/>
+
<label>WPL:</label><br/>
+
<textarea id="m3u2wpl_wpl" cols="80" rows="10"></textarea><br/>
+
</form>
 
}}
}}
 

        

        
-
$path_winと$path_unixは音楽ファイルのあるパスを表しているので、使用している環境にあわせて書き換えること。