.NET Frameworkにおけるテキストのエンコード・デコード、エスケープ・アンエスケープ、フォーマット変換、暗号化などについて。

文字コード

文字コードを指定して文字列をバイト配列にエンコードしたり、逆にデコードしたりする場合にはSystem.Text.Encodingクラスを使います。

文字コードを指定したデコード・エンコード
using System;
using System.Text;

class Sample {
  static void Main()
  {
    // SHIFT_JISでのエンコード・デコードを行うEncodingを取得する
    Encoding e = Encoding.GetEncoding("shift_jis");

    // 文字列をエンコードしてSHIFT_JISのバイト配列に変換する
    byte[] bytes = e.GetBytes("日本語");

    Console.WriteLine(BitConverter.ToString(bytes));

    // SHIFT_JISのバイト配列をデコードして文字列に変換する
    string str = e.GetString(new byte[] {0x93, 0xFA, 0x96, 0x7B, 0x8C, 0xEA});

    Console.WriteLine(str);
  }
}
文字コードを指定したデコード・エンコード
Imports System
Imports System.Text

Class Sample
  Shared Sub Main()
    ' SHIFT_JISでのエンコード・デコードを行うEncodingを取得する
    Dim e As Encoding = Encoding.GetEncoding("shift_jis")

    ' 文字列をエンコードしてSHIFT_JISのバイト配列に変換する
    Dim bytes As Byte() = e.GetBytes("日本語")

    Console.WriteLine(BitConverter.ToString(bytes))

    ' SHIFT_JISのバイト配列をデコードして文字列に変換する
    Dim str As String = e.GetString(New Byte() {&h93, &hFA, &h96, &h7B, &h8C, &hEA})

    Console.WriteLine(str)
  End Sub
End Class
実行結果
93-FA-96-7B-8C-EA
日本語

バイト配列を別の文字コードでの表現に変換するにはEncoding.Convertメソッドを使います。

文字コードの変換
using System;
using System.Text;

class Sample {
  static void Main()
  {
    // SHIFT_JISの文字列"日本語"のバイト配列表現
    byte[] shift_jis = new byte[] {0x93, 0xFA, 0x96, 0x7B, 0x8C, 0xEA};

    Console.WriteLine("SHIFT_JIS: {0}", BitConverter.ToString(shift_jis));

    // バイト配列をSHIFT_JISからUTF-8に変換する
    byte[] utf8 = Encoding.Convert(Encoding.GetEncoding("shift_jis"), Encoding.UTF8, shift_jis);

    Console.WriteLine("UTF-8: {0}", BitConverter.ToString(utf8));
  }
}
文字コードの変換
Imports System
Imports System.Text

Class Sample
  Shared Sub Main()
    ' SHIFT_JISの文字列"日本語"のバイト配列表現
    Dim shift_jis As Byte() = New Byte() {&h93, &hFA, &h96, &h7B, &h8C, &hEA}

    Console.WriteLine("SHIFT_JIS: {0}", BitConverter.ToString(shift_jis))

    ' バイト配列をSHIFT_JISからUTF-8に変換する
    Dim utf8 As Byte() = Encoding.Convert(Encoding.GetEncoding("shift_jis"), Encoding.UTF8, shift_jis)

    Console.WriteLine("UTF-8: {0}", BitConverter.ToString(utf8))
  End Sub
End Class
実行結果
SHIFT_JIS: 93-FA-96-7B-8C-EA
UTF-8: E6-97-A5-E6-9C-AC-E8-AA-9E

文字コードを指定したファイルの読み書きについてはStreamReaderクラス・StreamWriterクラスで解説しています。 その他、文字コードとEncodingクラスについては以下のページでも解説しています。

Base64

バイト配列をBase64に変換するにはSystem.ConvertクラスToBase64StringメソッドFromBase64Stringメソッドを使います。 文字列とBase64形式の文字列を直接相互に変換することは出来ないので、その場合にはまず文字列をバイト配列に変換してからこれらのメソッドを呼び出す必要があります。

Base64の変換
using System;
using System.Text;

class Sample {
  static void Main()
  {
    byte[] bytes;
    string base64;

    // バイト配列からBase64形式の文字列への変換
    bytes = new byte[] {0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47}; // "ABCDEFG"
    base64 = Convert.ToBase64String(bytes);

    Console.WriteLine(base64);

    // Base64形式の文字列からバイト配列への変換
    base64 = "QUJDREVGRw==";
    bytes = Convert.FromBase64String(base64);

    Console.WriteLine(BitConverter.ToString(bytes));

    // 得られたバイト配列をさらに文字列へと変換
    Console.WriteLine(Encoding.ASCII.GetString(bytes));
  }
}
Base64の変換
Imports System
Imports System.Text

Class Sample
  Shared Sub Main()
    Dim bytes As Byte()
    Dim base64 As String

    ' バイト配列からBase64形式の文字列への変換
    bytes = New Byte() {&h41, &h42, &h43, &h44, &h45, &h46, &h47} ' "ABCDEFG"
    base64 = Convert.ToBase64String(bytes)

    Console.WriteLine(base64)

    ' Base64形式の文字列からバイト配列への変換
    base64 = "QUJDREVGRw=="
    bytes = Convert.FromBase64String(base64)

    Console.WriteLine(BitConverter.ToString(bytes))

    ' 得られたバイト配列をさらに文字列へと変換
    Console.WriteLine(Encoding.ASCII.GetString(bytes))
  End Sub
End Class
実行結果
QUJDREVGRw==
41-42-43-44-45-46-47
ABCDEFG

ToBase64Stringメソッドでは、引数にBase64FormattingOptions.InsertLineBreaksを指定すると、Base64への変換に際して76文字ごとに改行を入れるようにすることができます。 Base64でメールの本文をエンコードする場合などに使用することができます。

改行を挿入したBase64の変換
using System;
using System.Text;

class Sample {
  static void Main()
  {
    byte[] bytes = new byte[] {
      0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
      0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
      0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
      0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
      0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
      0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
      0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
      0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
    };

    // 76文字ごとに改行を含めてBase64に変換する
    string base64 = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);

    Console.WriteLine(base64);

    // 改行を含めずBase64に変換する
    base64 = Convert.ToBase64String(bytes, Base64FormattingOptions.None);

    Console.WriteLine(base64);
  }
}
改行を挿入したBase64の変換
Imports System
Imports System.Text

Class Sample
  Shared Sub Main()
    Dim bytes As Byte() = New Byte() { _
      &h41, &h42, &h43, &h44, &h45, &h46, &h47, &h48, &h49, &h4a, &h4b, &h4c, &h4d, &h4e, &h4f, &h50, _
      &h41, &h42, &h43, &h44, &h45, &h46, &h47, &h48, &h49, &h4a, &h4b, &h4c, &h4d, &h4e, &h4f, &h50, _
      &h41, &h42, &h43, &h44, &h45, &h46, &h47, &h48, &h49, &h4a, &h4b, &h4c, &h4d, &h4e, &h4f, &h50, _
      &h41, &h42, &h43, &h44, &h45, &h46, &h47, &h48, &h49, &h4a, &h4b, &h4c, &h4d, &h4e, &h4f, &h50, _
      &h41, &h42, &h43, &h44, &h45, &h46, &h47, &h48, &h49, &h4a, &h4b, &h4c, &h4d, &h4e, &h4f, &h50, _
      &h41, &h42, &h43, &h44, &h45, &h46, &h47, &h48, &h49, &h4a, &h4b, &h4c, &h4d, &h4e, &h4f, &h50, _
      &h41, &h42, &h43, &h44, &h45, &h46, &h47, &h48, &h49, &h4a, &h4b, &h4c, &h4d, &h4e, &h4f, &h50, _
      &h41, &h42, &h43, &h44, &h45, &h46, &h47, &h48, &h49, &h4a, &h4b, &h4c, &h4d, &h4e, &h4f, &h50  _
    }

    ' 76文字ごとに改行を含めてBase64に変換する
    Dim base64 As String = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks)

    Console.WriteLine(base64)

    ' 改行を含めずBase64に変換する
    base64 = Convert.ToBase64String(bytes, Base64FormattingOptions.None)

    Console.WriteLine(base64)
  End Sub
End Class
実行結果
QUJDREVGR0hJSktMTU5PUEFCQ0RFRkdISUpLTE1OT1BBQkNERUZHSElKS0xNTk9QQUJDREVGR0hJ
SktMTU5PUEFCQ0RFRkdISUpLTE1OT1BBQkNERUZHSElKS0xNTk9QQUJDREVGR0hJSktMTU5PUEFC
Q0RFRkdISUpLTE1OT1A=
QUJDREVGR0hJSktMTU5PUEFCQ0RFRkdISUpLTE1OT1BBQkNERUZHSElKS0xNTk9QQUJDREVGR0hJSktMTU5PUEFCQ0RFRkdISUpLTE1OT1BBQkNERUZHSElKS0xNTk9QQUJDREVGR0hJSktMTU5PUEFCQ0RFRkdISUpLTE1OT1A=

ストリームをBase64で変換したり、Base64形式でファイルの読み書きをする場合には、System.Security.Cryptography名前空間CryptoStreamToBase64TransformFromBase64Transformを組み合わせて使います。

次のコードは、Base64・UTF-8でエンコードしてファイルを読み書きする例です。

Base64形式でのファイルの読み書き
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

class Sample {
  static void Main()
  {
    // ファイルbase64.txtに書き込むストリームを作成する
    using (FileStream fileStream = new FileStream("base64.txt", FileMode.Create, FileAccess.Write)) {
      // Base64への変換を行った上でfileStreamに書き込みを行うCryptoStreamを作成する
      using (CryptoStream base64Stream = new CryptoStream(fileStream, new ToBase64Transform(), CryptoStreamMode.Write)) {
        // UTF-8にエンコードして書き込むStreamWriterを作成する
        using (StreamWriter writer = new StreamWriter(base64Stream, Encoding.UTF8)) {
          // ファイルに文字列を書き込む
          writer.WriteLine("かごめかごめ");
          writer.WriteLine("かごのなかのとりは");
          writer.WriteLine("いついつでやる");
        }
      }
    }

    // ファイルbase64.txtを読み込むストリームを作成する
    using (FileStream fileStream = new FileStream("base64.txt", FileMode.Open, FileAccess.Read)) {
      // fileStreamから読み込んだ後にBase64からの変換を行うCryptoStreamを作成する
      using (CryptoStream base64Stream = new CryptoStream(fileStream, new FromBase64Transform(), CryptoStreamMode.Read)) {
        // UTF-8でデコードして読み込むStreamReaderを作成する
        using (StreamReader reader = new StreamReader(base64Stream, Encoding.UTF8)) {
          // ファイル全体を読み込んで表示する
          Console.Write(reader.ReadToEnd());
        }
      }
    }
  }
}
Base64形式でのファイルの読み書き
Imports System
Imports System.IO
Imports System.Security.Cryptography
Imports System.Text

Class Sample
  Shared Sub Main()
    ' ファイルbase64.txtに書き込むストリームを作成する
    Using fileStream As New FileStream("base64.txt", FileMode.Create, FileAccess.Write)
      ' Base64への変換を行った上でfileStreamに書き込みを行うCryptoStreamを作成する
      Using base64Stream As New CryptoStream(fileStream, New ToBase64Transform(), CryptoStreamMode.Write)
        ' UTF-8にエンコードして書き込むStreamWriterを作成する
        Using writer As New StreamWriter(base64Stream, Encoding.UTF8)
          ' ファイルに文字列を書き込む
          writer.WriteLine("かごめかごめ")
          writer.WriteLine("かごのなかのとりは")
          writer.WriteLine("いついつでやる")
        End Using
      End Using
    End Using

    ' ファイルbase64.txtを読み込むストリームを作成する
    Using fileStream As New FileStream("base64.txt", FileMode.Open, FileAccess.Read)
      ' fileStreamから読み込んだ後にBase64からの変換を行うCryptoStreamを作成する
      Using base64Stream As New CryptoStream(fileStream, New FromBase64Transform(), CryptoStreamMode.Read)
        ' UTF-8でデコードして読み込むStreamReaderを作成する
        Using reader As New StreamReader(base64Stream, Encoding.UTF8)
          ' ファイル全体を読み込んで表示する
          Console.Write(reader.ReadToEnd())
        End Using
      End Using
    End Using
  End Sub
End Class
base64.txtに書き込まれる内容
77u/44GL44GU44KB44GL44GU44KBCuOBi+OBlOOBruOBquOBi+OBruOBqOOCiuOBrwrjgYTjgaTjgYTjgaTjgafjgoTjgosK
実行結果
かごめかごめ
かごのなかのとりは
いついつでやる

このコードでは、次のようにしてBase64・UTF-8への変換が行われます。

Base64・UTF-8への変換の過程と各クラスの役割
 [文字列] → StreamWriter+Encoding(UTF-8のバイト配列へ変換) → CryptoStream+ToBase64Transform(Base64へ変換) → FileStream(ファイルへ書き込み) → [ファイル]
 
 [文字列] ← StreamReader+Encoding(UTF-8の文字列へ変換) ← CryptoStream+FromBase64Transform(Base64から変換) ← FileStream(ファイルから読み込み) ← [ファイル]

ストリームを多段に重ねて使う方法についてはストリームの基本とStreamクラス §.データフォーマットの変換やバッファリングなどの機能を追加するStream派生クラス、StreamWriter・StreamReaderについてはStreamReaderクラス・StreamWriterクラスで詳しく解説しています。

quoted-printable

.NET Frameworkにはquoted-printableのエンコード・デコードを行うクラスやメソッドは用意されていません。 必要な場合は独自に実装する必要があります。

実装例:quoted-printableのエンコード・デコードSmdn.Formats.Mime

MIMEエンコード (Qエンコード・Bエンコード)

.NET FrameworkにはMIMEエンコード・デコードを行うクラスやメソッドは用意されていません。 必要な場合はBASE64の変換quoted-printableの変換文字コードの変換を組み合わせて独自に実装する必要があります。

実装例:Smdn.Formats.Mime

URLエンコード・パーセントエンコード

エンコード

URLエンコード(パーセントエンコード)を行うメソッドには次の4つを使うことができます。 それぞれの違いは次のとおりです。

URLエンコードを行うメソッド
メソッド 動作と適用範囲 文字コード 必要アセンブリ・バージョン
System.Uri.EscapeUriString / # & = ?などURIで特別な意味を持つ記号は変換されない
(URIとして使用する文字列を変換する際にはこのメソッドを使用する)
常にUTF-8でエンコードされる System.dll
(.NET Framework 1.0以降)
System.Uri.EscapeDataString / # & = ?などの記号も変換される
(URIのクエリ部分などに使用する文字列を変換する際にはこのメソッドを使用する)
System.dll
(.NET Framework 1.0以降)
System.Net.WebUtility.UrlEncode System.dll
(.NET Framework 4.5以降)
System.Web.HttpUtility.UrlEncode 任意のEncodingを指定してエンコードできる System.Web.dll
(.NET Framework 1.1以降)
URLエンコード
using System;

class Sample {
  static void Main()
  {
    string str = "http://example.com/search?q=URL エスケープ&max=10";

    Console.WriteLine(System.Uri.EscapeUriString(str));
    Console.WriteLine(System.Uri.EscapeDataString(str));
    Console.WriteLine(System.Net.WebUtility.UrlEncode(str));
    Console.WriteLine(System.Web.HttpUtility.UrlEncode(str));
  }
}
URLエンコード
Imports System

Class Sample
  Shared Sub Main()
    Dim str As String = "http://example.com/search?q=URL エスケープ&max=10"

    Console.WriteLine(System.Uri.EscapeUriString(str))
    Console.WriteLine(System.Uri.EscapeDataString(str))
    Console.WriteLine(System.Net.WebUtility.UrlEncode(str))
    Console.WriteLine(System.Web.HttpUtility.UrlEncode(str))
  End Sub
End Class
実行結果
http://example.com/search?q=URL%20%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97&max=10
http%3A%2F%2Fexample.com%2Fsearch%3Fq%3DURL%20%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%26max%3D10
http%3A%2F%2Fexample.com%2Fsearch%3Fq%3DURL+%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%26max%3D10
http%3a%2f%2fexample.com%2fsearch%3fq%3dURL+%e3%82%a8%e3%82%b9%e3%82%b1%e3%83%bc%e3%83%97%26max%3d10

これらのメソッドの変換結果には細かな違いがあり、変換される記号の違いのほか、空白(0x20)を%20に変換するか+に変換するか、大文字小文字どちらにエンコードされるか、といった違いがあります。

さらにUri.EscapeUriString・Uri.EscapeDataStringについては、.NET Framework 4.0まではRFC 2396に基づいて変換を行いますが、.NET Framework 4.5以降ではRFC 3986に基づいて変換されるように動作が変更されているという点にも注意が必要です。

0x20から0x7fまでの文字と各メソッドの変換結果の違いを表にすると次のようになります。

0x20から0x3fまでの文字とエンコード結果
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
Uri.EscapeUriString (.NET 4.5以降) %20 ! %22 # $ %25 & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; %3C = %3E ?
Uri.EscapeUriString (.NET 4.0まで) %20 ! %22 # $ %25 & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; %3C = %3E ?
Uri.EscapeDataString (.NET 4.5以降) %20 %21 %22 %23 %24 %25 %26 %27 %28 %29 %2A %2B %2C - . %2F 0 1 2 3 4 5 6 7 8 9 %3A %3B %3C %3D %3E %3F
Uri.EscapeDataString (.NET 4.0まで) %20 ! %22 %23 %24 %25 %26 ' ( ) * %2B %2C - . %2F 0 1 2 3 4 5 6 7 8 9 %3A %3B %3C %3D %3E %3F
WebUtility.UrlEncode + ! %22 %23 %24 %25 %26 %27 ( ) * %2B %2C - . %2F 0 1 2 3 4 5 6 7 8 9 %3A %3B %3C %3D %3E %3F
HttpUtility.UrlEncode + ! %22 %23 %24 %25 %26 %27 ( ) * %2b %2c - . %2f 0 1 2 3 4 5 6 7 8 9 %3a %3b %3c %3d %3e %3f
0x40から0x5fまでの文字とエンコード結果
@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
Uri.EscapeUriString (.NET 4.5以降) @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ %5C ] %5E _
Uri.EscapeUriString (.NET 4.0まで) @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z %5B %5C %5D %5E _
Uri.EscapeDataString (.NET 4.5以降) %40 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z %5B %5C %5D %5E _
Uri.EscapeDataString (.NET 4.0まで) %40 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z %5B %5C %5D %5E _
WebUtility.UrlEncode %40 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z %5B %5C %5D %5E _
HttpUtility.UrlEncode %40 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z %5b %5c %5d %5e _
0x60から0x7fまでの文字とエンコード結果
` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ 
Uri.EscapeUriString (.NET 4.5以降) %60 a b c d e f g h i j k l m n o p q r s t u v w x y z %7B %7C %7D ~ %7F
Uri.EscapeUriString (.NET 4.0まで) %60 a b c d e f g h i j k l m n o p q r s t u v w x y z %7B %7C %7D ~ %7F
Uri.EscapeDataString (.NET 4.5以降) %60 a b c d e f g h i j k l m n o p q r s t u v w x y z %7B %7C %7D ~ %7F
Uri.EscapeDataString (.NET 4.0まで) %60 a b c d e f g h i j k l m n o p q r s t u v w x y z %7B %7C %7D ~ %7F
WebUtility.UrlEncode %60 a b c d e f g h i j k l m n o p q r s t u v w x y z %7B %7C %7D %7E %7F
HttpUtility.UrlEncode %60 a b c d e f g h i j k l m n o p q r s t u v w x y z %7b %7c %7d %7e %7f

デコード

URLエンコード(パーセントエンコード)された文字列のデコードを行うには次の3つのメソッドを使うことができます。 それぞれの違いは次のとおりです。

URLエンコードを行うメソッド
メソッド 動作 文字コード 必要アセンブリ・バージョン
System.Uri.UnescapeDataString 文字列中の+はそのままデコードされる 常にUTF-8でデコードされる System.dll
(.NET Framework 1.0以降)
System.Net.WebUtility.UrlDecode 文字列中の+はデコード時に空白に変換される System.dll
(.NET Framework 4.5以降)
System.Web.HttpUtility.UrlDecode 任意のEncodingを指定してデコードできる System.Web.dll
(.NET Framework 1.1以降)
URLエンコードされた文字列のデコード
using System;

class Sample {
  static void Main()
  {
    string str = "http://example.com/search?q=URL+%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97&max=10";

    Console.WriteLine(System.Uri.UnescapeDataString(str));
    Console.WriteLine(System.Net.WebUtility.UrlDecode(str));
    Console.WriteLine(System.Web.HttpUtility.UrlDecode(str));
  }
}
URLエンコードされた文字列のデコード
Imports System

Class Sample
  Shared Sub Main()
    Dim str As String = "http://example.com/search?q=URL+%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97&max=10"

    Console.WriteLine(System.Uri.UnescapeDataString(str))
    Console.WriteLine(System.Net.WebUtility.UrlDecode(str))
    Console.WriteLine(System.Web.HttpUtility.UrlDecode(str))
  End Sub
End Class
実行結果
http://example.com/search?q=URL+エスケープ&max=10
http://example.com/search?q=URL エスケープ&max=10
http://example.com/search?q=URL エスケープ&max=10

デコードする文字列と+の扱いについてはURLのデコード・アンエスケープ(HttpUtility.UrlDecode、Uri.UnescapeDataString)でも解説しています。

HTMLエンコード・エンティティ化

.NET Framework 4.5以降では、System.Net.WebUtilityクラスHtmlEncodeHtmlDecodeメソッドを使うことでHTMLエンコードを行うことができます。 HtmlEncodeメソッドでは、"&<>に加えて'の計5つの記号がエンコードされます。 HtmlDecodeメソッドでは、&apos;&quot;&amp;&lt;&gt;がデコードされるほか、10進・16進の数値文字参照(エンティティ)もデコードされます。

HTMLエンコード・デコード
using System;
using System.Net;

class Sample {
  static void Main()
  {
    // HTMLエンコード
    Console.WriteLine(WebUtility.HtmlEncode("'\"&<>"));
    Console.WriteLine(WebUtility.HtmlEncode("<script>alert('Hello, world!');</script>"));

    // HTMLデコード
    Console.WriteLine(WebUtility.HtmlDecode("&apos;&quot;&amp;&lt;&gt;"));
    Console.WriteLine(WebUtility.HtmlDecode("&#65;&#66;&#67;&#x41;&#x42;&#x43;&#x65e5;&#x672c;&#x8a9e;"));
  }
}
HTMLエンコード・デコード
Imports System
Imports System.Net

Class Sample
  Shared Sub Main()
    ' HTMLエンコード
    Console.WriteLine(WebUtility.HtmlEncode("'""&<>"))
    Console.WriteLine(WebUtility.HtmlEncode("<script>alert('Hello, world!');</script>"))

    ' HTMLデコード
    Console.WriteLine(WebUtility.HtmlDecode("&apos;&quot;&amp;&lt;&gt;"))
    Console.WriteLine(WebUtility.HtmlDecode("&#65;&#66;&#67;&#x41;&#x42;&#x43;&#x65e5;&#x672c;&#x8a9e;"))
  End Sub
End Class
実行結果
&#39;&quot;&amp;&lt;&gt;
&lt;script&gt;alert(&#39;Hello, world!&#39;);&lt;/script&gt;
'"&<>
ABCABC日本語

4.5より前の.NET FrameworkやASP.NETでは、System.Web.dllにあるSystem.Web.HttpUtilityクラスHtmlEncodeHtmlDecodeメソッドを使うことで同様のことを行えます。

一部の記号だけでなくすべての文字を数値文字参照に変換(エンティティ化)するメソッドは用意されていないので、次の例のように独自に実装する必要があります。

文字列のHTMLエンティティ化
using System;
using System.Net;
using System.Text;

class Sample {
  // 文字列を16進または10進形式でHTMLエンティティ化する
  static string HtmlEntitize(string str, bool hex)
  {
    StringBuilder ret = new StringBuilder(str.Length * 6);

    // 1文字ずつエンティティ化する
    if (hex) {
      foreach (char c in str) {
        ret.AppendFormat("&#x{0:x};", (int)c);
      }
    }
    else {
      foreach (char c in str) {
        ret.AppendFormat("&#{0:d};", (int)c);
      }
    }

    return ret.ToString();
  }

  static void Main()
  {
    string hexEntitized = HtmlEntitize("foo@example.net", true); // 16進数でエンティティ化
    string decEntitized = HtmlEntitize("foo@example.net", false); // 10進数でエンティティ化

    Console.WriteLine(hexEntitized);
    Console.WriteLine(decEntitized);

    // エンティティ化したものをWebUtility.HtmnlDecodeで元に戻す
    Console.WriteLine(WebUtility.HtmlDecode(hexEntitized));
    Console.WriteLine(WebUtility.HtmlDecode(decEntitized));
  }
}
文字列のHTMLエンティティ化
Imports System
Imports System.Net
Imports System.Text

Class Sample
  ' 文字列を16進または10進形式でHTMLエンティティ化する
  Shared Function HtmlEntitize(ByVal str As String, ByVal hex As Boolean) As String
    Dim ret As New StringBuilder(str.Length * 6)

    ' 1文字ずつエンティティ化する
    If hex Then
      For Each c As Char In str
        ret.AppendFormat("&#x{0:x};", AscW(c))
      Next
    Else
      For Each c As Char In str
        ret.AppendFormat("&#{0:d};", AscW(c))
      Next
    End If

    Return ret.ToString()
  End Function

  Shared Sub Main()
    Dim hexEntitized As String = HtmlEntitize("foo@example.net", True) ' 16進数でエンティティ化
    Dim decEntitized As String = HtmlEntitize("foo@example.net", False) ' 10進数でエンティティ化

    Console.WriteLine(hexEntitized)
    Console.WriteLine(decEntitized)

    ' エンティティ化したものをWebUtility.HtmnlDecodeで元に戻す
    Console.WriteLine(WebUtility.HtmlDecode(hexEntitized))
    Console.WriteLine(WebUtility.HtmlDecode(decEntitized))
  End Sub
End Class
実行結果
&#x66;&#x6f;&#x6f;&#x40;&#x65;&#x78;&#x61;&#x6d;&#x70;&#x6c;&#x65;&#x2e;&#x6e;&#x65;&#x74;
&#102;&#111;&#111;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#110;&#101;&#116;
foo@example.net
foo@example.net

日付と時刻

DateTime.ToStringメソッドの引数に書式を指定することにより、日時をよく使われる形式の文字列へと変換することができます。 書式指定子"r"を指定するとRFC1123形式、"o"を指定するとISO8601(W3C-DTF)形式の文字列に変換できます。

書式を指定した日時の文字列化
using System;

class Sample {
  static void Main()
  {
    DateTime dt = new DateTime(2013, 12, 3, 4, 5, 6);

    Console.WriteLine(dt.ToString("r")); // RFC1123形式で日時を文字列化
    Console.WriteLine(dt.ToString("o")); // ISO8601(W3C-DTF)形式で日時を文字列化
    Console.WriteLine();

    DateTimeOffset dto = new DateTimeOffset(2013, 12, 3, 4, 5, 6, TimeSpan.FromHours(+9)); // 日時とオフセット

    Console.WriteLine(dto.ToString("r")); // RFC1123形式で日時を文字列化
    Console.WriteLine(dto.ToString("o")); // ISO8601(W3C-DTF)形式で日時を文字列化
  }
}
書式を指定した日時の文字列化
Imports System

Class Sample
  Shared Sub Main()
    Dim dt As New DateTime(2013, 12, 3, 4, 5, 6)

    Console.WriteLine(dt.ToString("r")) ' RFC1123形式で日時を文字列化
    Console.WriteLine(dt.ToString("o")) ' ISO8601(W3C-DTF)形式で日時を文字列化
    Console.WriteLine()

    Dim dto As New DateTimeOffset(2013, 12, 3, 4, 5, 6, TimeSpan.FromHours(+9)) ' 日時とオフセット

    Console.WriteLine(dto.ToString("r")) ' RFC1123形式で日時を文字列化
    Console.WriteLine(dto.ToString("o")) ' ISO8601(W3C-DTF)形式で日時を文字列化
  End Sub
End Class
実行結果
Tue, 03 Dec 2013 04:05:06 GMT
2013-12-03T04:05:06.0000000

Mon, 02 Dec 2013 19:05:06 GMT
2013-12-03T04:05:06.0000000+09:00

また逆に、ParseExactメソッドを使うことによりこれらの形式で表記された文字列をDateTime・DateTimeOffsetに変換することができます。

文字列から日時への変換
using System;

class Sample {
  static void Main()
  {
    string str = "2013-09-08T07:06:54.3210000-05:00"; // ISO8601形式の時刻を表す文字列

    DateTime dt = DateTime.ParseExact(str, "o", null);
    DateTimeOffset dto = DateTimeOffset.ParseExact(str, "o", null);

    Console.WriteLine(dt);
    Console.WriteLine(dto);
  }
}
文字列から日時への変換
Imports System
Imports System.Net
Imports System.Text

Class Sample
  Shared Sub Main()
    Dim str As String = "2013-09-08T07:06:54.3210000-05:00" ' ISO8601形式の時刻を表す文字列

    Dim dt As DateTime = DateTime.ParseExact(str, "o", Nothing)
    Dim dto As DateTimeOffset = DateTimeOffset.ParseExact(str, "o", Nothing)

    Console.WriteLine(dt)
    Console.WriteLine(dto)
  End Sub
End Class
実行結果
09/08/2013 21:06:54
09/08/2013 07:06:54 -05:00

DateTime構造体・DateTimeOffset構造体については日付・時刻の型と操作、日時と書式については日時・文字列の変換と書式書式指定子で詳しく解説しています。

ハッシュ化

MD5, SHA-1, SHA-512などのハッシュ関数を使ってハッシュ値を求めるには、System.Security.Cryptography名前空間MD5クラスSHA1クラスSHA512クラスなどのHashAlgorithmクラスから派生したクラスを使うことができます。

これらのクラスでは、ComputeHashメソッドにバイト配列を指定すると、そのバイト配列のハッシュ値を取得することができます。 文字列から直接ハッシュ値を求めることはできないので、先に文字列をバイト配列に変換する必要があります。

以下の例ではMD5クラスを使用していますが、SHA1クラス・SHA512クラスに置き換えればSHA-1, SHA-512のハッシュ値を求めることができます。

文字列からハッシュ値を求める
using System;
using System.Security.Cryptography;
using System.Text;

class Sample {
  static void Main()
  {
    string input = "foo";

    // MD5ハッシュ関数のインスタンスを作成
    using (MD5 hashFunc = MD5.Create()) {
      // 文字列をバイト配列に変換してMD5ハッシュ値を求める
      byte[] hash = hashFunc.ComputeHash(Encoding.UTF8.GetBytes(input));

      // 求めたハッシュ値を文字列化して表示
      string hashString = BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant();

      Console.WriteLine("{0} {1}", input, hashString);
    }
  }
}
文字列からハッシュ値を求める
Imports System
Imports System.Security.Cryptography
Imports System.Text

Class Sample
  Shared Sub Main()
    Dim input As String = "foo"

    ' MD5ハッシュ関数のインスタンスを作成
    Using hashFunc As MD5 = MD5.Create()
      ' 文字列をバイト配列に変換してMD5ハッシュ値を求める
      Dim hash() As Byte = hashFunc.ComputeHash(Encoding.UTF8.GetBytes(input))

      ' 求めたハッシュ値を文字列化して表示
      Dim hashString As String = BitConverter.ToString(hash).Replace("-", String.Empty).ToLowerInvariant()

      Console.WriteLine("{0} {1}", input, hashString)
    End Using
  End Sub
End Class
実行結果
foo acbd18db4cc2f85cedef654fccc4a4d8

Computeハッシュメソッドは引数にStreamクラスを指定することもできます。 ファイルのハッシュ値を求める場合は次のようにします。

ファイルのハッシュ値を求める
using System;
using System.IO;
using System.Security.Cryptography;

class Sample {
  static void Main()
  {
    // ファイルsample.txtを読み込むストリームを作成する
    using (Stream stream = File.OpenRead("sample.txt")) {
      // MD5ハッシュ関数のインスタンスを作成
      using (MD5 hashFunc = MD5.Create()) {
        // ストリームの内容を読み込んでMD5ハッシュ値を求める
        byte[] hash = hashFunc.ComputeHash(stream);

        // 求めたハッシュ値を文字列化して表示
        string hashString = BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant();

        Console.WriteLine(hashString);
      }
    }
  }
}
ファイルのハッシュ値を求める
Imports System
Imports System.IO
Imports System.Security.Cryptography

Class Sample
  Shared Sub Main()
    ' ファイルsample.txtを読み込むストリームを作成する
    Using stream As Stream = File.OpenRead("sample.txt")
      ' MD5ハッシュ関数のインスタンスを作成
      Using hashFunc As MD5 = MD5.Create()
        ' ストリームの内容を読み込んでMD5ハッシュ値を求める
        Dim hash() As Byte = hashFunc.ComputeHash(stream)

        ' 求めたハッシュ値を文字列化して表示
        Dim hashString As String = BitConverter.ToString(hash).Replace("-", String.Empty).ToLowerInvariant()

        Console.WriteLine(hashString)
      End Using
    End Using
  End Sub
End Class

ハッシュ値を求める例については以下のページでも紹介しています。

暗号化・復号化

System.Security.Cryptography名前空間にあるクラスを使うことで暗号化・復号化を行うことができます。 次の例では、共通鍵方式のTriple DES(3DES)での暗号化・復号化を行うTripleDESクラスを使い、暗号化してファイルに文字列を書き込んだあと、再度ファイルを読み込んで復号化しています。

ファイルの暗号化・復号化
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

class Sample {
  static void Main()
  {
    // TripleDESクラスがデフォルトで生成するランダムな値を取得して
    // 暗号化・復号化の際のキー・初期ベクタとして使用する
    byte[] desKey, desIV;

    using (TripleDES des = TripleDES.Create()) {
      desKey = des.Key;
      desIV = des.IV;
    }

    // ファイルcrypto.datに書き込むストリームを作成する
    using (FileStream outputStream = new FileStream("crypto.dat", FileMode.Create, FileAccess.Write)) {
      // TripleDESアルゴリズムのインスタンスを作成する
      using (TripleDES des = TripleDES.Create()) {
        // TripleDESアルゴリズムで暗号化した上でoutputStreamに書き込むCryptoStreamを作成する
        using (CryptoStream encryptStream = new CryptoStream(outputStream, des.CreateEncryptor(desKey, desIV), CryptoStreamMode.Write)) {
          // UTF-8にエンコードしてencryptStreamに書き込むStreamWriterを作成する
          using (StreamWriter writer = new StreamWriter(encryptStream, Encoding.UTF8)) {
            // 文字列を書き込む
            writer.WriteLine("かごめかごめ");
            writer.WriteLine("かごのなかのとりは");
            writer.WriteLine("いついつでやる");
          }
        }
      }
    }

    // ファイルcrypto.datを読み込むストリームを作成する
    using (FileStream inputStream = new FileStream("crypto.dat", FileMode.Open, FileAccess.Read)) {
      // TripleDESアルゴリズムのインスタンスを作成する
      using (TripleDES des = TripleDES.Create()) {
        // inputStreamから読み込んだ後にTripleDESアルゴリズムで復号化を行うCryptoStreamを作成する
        using (CryptoStream decryptStream = new CryptoStream(inputStream, des.CreateDecryptor(desKey, desIV), CryptoStreamMode.Read)) {
          // UTF-8でデコードしてdecryptStreamから読み込むStreamReaderを作成する
          using (StreamReader reader = new StreamReader(decryptStream, Encoding.UTF8)) {
            // ファイル全体を読み込んで表示する
            Console.Write(reader.ReadToEnd());
          }
        }
      }
    }
  }
}
ファイルの暗号化・復号化
Imports System
Imports System.IO
Imports System.Security.Cryptography
Imports System.Text

Class Sample
  Shared Sub Main()
    ' TripleDESクラスがデフォルトで生成するランダムな値を取得して
    ' 暗号化・復号化の際のキー・初期ベクタとして使用する
    Dim desKey(), desIV() As Byte

    Using des As TripleDES = TripleDES.Create()
      desKey = des.Key
      desIV = des.IV
    End Using

    ' ファイルcrypto.datに書き込むストリームを作成する
    Using outputStream As New FileStream("crypto.dat", FileMode.Create, FileAccess.Write)
      ' TripleDESアルゴリズムのインスタンスを作成する
      Using des As TripleDES = TripleDES.Create()
        ' TripleDESアルゴリズムで暗号化した上でoutputStreamに書き込むCryptoStreamを作成する
        Using encryptStream As New CryptoStream(outputStream, des.CreateEncryptor(desKey, desIV), CryptoStreamMode.Write)
          ' UTF-8にエンコードしてencryptStreamに書き込むStreamWriterを作成する
          Using writer As New StreamWriter(encryptStream, Encoding.UTF8)
            ' 文字列を書き込む
            writer.WriteLine("かごめかごめ")
            writer.WriteLine("かごのなかのとりは")
            writer.WriteLine("いついつでやる")
          End Using
        End Using
      End Using
    End Using

    ' ファイルcrypto.datを読み込むストリームを作成する
    Using inputStream As New FileStream("crypto.dat", FileMode.Open, FileAccess.Read)
      ' TripleDESアルゴリズムのインスタンスを作成する
      Using des As TripleDES = TripleDES.Create()
        ' inputStreamから読み込んだ後にTripleDESアルゴリズムで復号化を行うCryptoStreamを作成する
        Using decryptStream As New CryptoStream(inputStream, des.CreateDecryptor(desKey, desIV), CryptoStreamMode.Read)
          ' UTF-8でデコードしてdecryptStreamから読み込むStreamReaderを作成する
          Using reader As New StreamReader(decryptStream, Encoding.UTF8)
            ' ファイル全体を読み込んで表示する
            Console.Write(reader.ReadToEnd())
          End Using
        End Using
      End Using
    End Using
  End Sub
End Class
実行結果
かごめかごめ
かごのなかのとりは
いついつでやる

上記の例では初期化ベクタ(IV)とキー(Key)の生成を省略しています。 初期ベクタとキーの生成・送受信には安全な方法をとるようにしてください。

ストリームを多段に重ねて使う方法についてはストリームの基本とStreamクラス §.データフォーマットの変換やバッファリングなどの機能を追加するStream派生クラス、StreamWriter・StreamReaderについてはStreamReaderクラス・StreamWriterクラスで詳しく解説しています。

圧縮・伸長

System.IO.Compression名前空間にあるクラスを使うことで圧縮・展開を行うことができます。 gzip形式での圧縮・伸長にはGZipStreamクラス、LZ77形式での圧縮・伸長にはDeflateStreamクラスを使うことができます。

これらのクラスについてはSystem.IO.Compression.GZipStreamで詳しく解説しています。