.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クラスについては以下のページでも解説しています。
- ファイル入出力 §.文字コード
- EncodingクラスとBOMありなしの制御 .NET FrameworkにおけるBOMの扱いについて
- Shift JISとEUC-JPの判別 文字コードを検出する例
- 文字・文字列のバイト数を調べる
- Modified UTF-7のエンコード・デコード
Base64
バイト配列をBase64に変換するにはSystem.ConvertクラスのToBase64Stringメソッド・FromBase64Stringメソッドを使います。 文字列と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));
}
}
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でメールの本文をエンコードする場合などに使用することができます。
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);
}
}
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名前空間のCryptoStreamとToBase64Transform・FromBase64Transformを組み合わせて使います。
次のコードは、Base64・UTF-8でエンコードしてファイルを読み書きする例です。
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());
}
}
}
}
}
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
77u/44GL44GU44KB44GL44GU44KBCuOBi+OBlOOBruOBquOBi+OBruOBqOOCiuOBrwrjgYTjgaTjgYTjgaTjgafjgoTjgosK
かごめかごめ かごのなかのとりは いついつでやる
このコードでは、次のようにして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のエンコード・デコードを行うクラスやメソッドは用意されていません。 必要な場合は独自に実装する必要があります。
MIMEエンコード (Qエンコード・Bエンコード)
.NET FrameworkにはMIMEエンコード・デコードを行うクラスやメソッドは用意されていません。 必要な場合はBASE64の変換・quoted-printableの変換・文字コードの変換を組み合わせて独自に実装する必要があります。
URLエンコード・パーセントエンコード
エンコード
URLエンコード(パーセントエンコード)を行うメソッドには次の4つを使うことができます。 それぞれの違いは次のとおりです。
メソッド | 動作と適用範囲 | 文字コード | 必要アセンブリ・バージョン |
---|---|---|---|
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以降) |
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));
}
}
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までの文字と各メソッドの変換結果の違いを表にすると次のようになります。
! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / | 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 |
@ | 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 | _ |
` | 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つのメソッドを使うことができます。 それぞれの違いは次のとおりです。
メソッド | 動作 | 文字コード | 必要アセンブリ・バージョン |
---|---|---|---|
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以降) |
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));
}
}
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クラスのHtmlEncode・HtmlDecodeメソッドを使うことでHTMLエンコードを行うことができます。 HtmlEncodeメソッドでは、"
&
<
>
に加えて'
の計5つの記号がエンコードされます。 HtmlDecodeメソッドでは、'
"
&
<
>
がデコードされるほか、10進・16進の数値文字参照(エンティティ)もデコードされます。
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("'"&<>"));
Console.WriteLine(WebUtility.HtmlDecode("ABCABC日本語"));
}
}
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("'"&<>"))
Console.WriteLine(WebUtility.HtmlDecode("ABCABC日本語"))
End Sub
End Class
'"&<> <script>alert('Hello, world!');</script> '"&<> ABCABC日本語
4.5より前の.NET FrameworkやASP.NETでは、System.Web.dllにあるSystem.Web.HttpUtilityクラスのHtmlEncode・HtmlDecodeメソッドを使うことで同様のことを行えます。
一部の記号だけでなくすべての文字を数値文字参照に変換(エンティティ化)するメソッドは用意されていないので、次の例のように独自に実装する必要があります。
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));
}
}
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
foo@example.net foo@example.net 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で詳しく解説しています。