なぜ文字列とbyte配列の変換が必要か?
C#において、string型(文字列)は人間が読み書きするためのテキストデータ("Hello"など)を扱います。一方で、ファイルへの保存、ネットワークを通じたデータ送信、API連携、暗号化処理など、コンピュータがデータを「ストリーム」として扱う場面では、データは byte[](バイト配列、つまり数値の羅列)として処理されるのが基本です。
string を byte[] に変換する操作を「エンコード(符号化)」と呼び、byte[] を string に戻す操作を「デコード(復号)」と呼びます。
この変換(エンコード・デコード)を行う際に不可欠なのが、「どの文字コード規格(エンコーディング)で変換するか」というルールを定義する System.Text.Encoding クラスです。
System.Text.Encoding とは
エンコーディングとは、「文字(例: ‘A’)」を「バイト(例: 0x41)」に変換するためのマッピングルールです。
C#では System.Text.Encoding クラスがこの役割を担います。Encodingクラスには、一般的な規格が静的プロパティとして用意されています。
Encoding.UTF8: (推奨) 現在のWebやアプリケーション開発で最も標準的に使用されるエンコーディング。ASCII文字(英語)は1バイト、多くの日本語文字は3バイトで表現されます。互換性が高く、ストレージ効率も良いため、特別な理由がない限りUTF-8の使用が推奨されます。Encoding.Unicode: .NET内部の文字列(string)が使用するUTF-16(リトルエンディアン)を指します。すべての文字を基本的に2バイト(または4バイト)で表現します。Encoding.ASCII: 英語のアルファベットと記号のみ(7ビット)を扱う、最も基本的なエンコーディング。日本語の文字は表現できず、?に文字化けします。
1. 文字列 (string) から byte[] への変換 (エンコード)
string から byte[] への変換には、Encoding.<Type>.GetBytes(string) メソッドを使用します。
コード例: Encoding.UTF8.GetBytes
"C# 123" という文字列を、UTF-8(推奨)のルールでバイト配列に変換する例です。
using System;
using System.Text; // Encoding を使用するために必要
public class StringToBytesExample
{
public static void Main()
{
string originalString = "C# 123";
// UTF-8 エンコーディングを使用して、文字列を byte 配列にエンコード
byte[] utf8Bytes = Encoding.UTF8.GetBytes(originalString);
Console.WriteLine($"元の文字列: {originalString}");
Console.WriteLine("--- UTF-8 バイト列 (16進数) ---");
// バイト配列の中身を16進数 (hex) で表示
foreach (var b in utf8Bytes)
{
Console.Write($"{b:X2} "); // X2 は 2桁の16進数 (例: 0A, 43)
}
Console.WriteLine();
}
}
出力結果:
元の文字列: C# 123
--- UTF-8 バイト列 (16進数) ---
43 23 20 31 32 33
C->0x43#->0x23- (スペース) ->
0x20 1->0x312->0x323->0x33
2. byte[] から 文字列 (string) への変換 (デコード)
byte[] から string への変換(デコード)には、Encoding.<Type>.GetString(byte[]) メソッドを使用します。
デコードは、エンコード時に使用したものと「必ず同じエンコーディング」を使用しなければなりません。
コード例: Encoding.UTF8.GetString
先ほどUTF-8でエンコードした utf8Bytes を、同じUTF-8でデコードして string に戻します。
using System;
using System.Text;
public class BytesToStringExample
{
public static void Main()
{
// 上記の例で UTF-8 エンコードされたバイト配列
byte[] utf8Bytes = { 0x43, 0x23, 0x20, 0x31, 0x32, 0x33 };
// UTF-8 を使用して、byte 配列を文字列にデコード
string restoredString = Encoding.UTF8.GetString(utf8Bytes);
Console.WriteLine($"バイト配列 (UTF-8): {BitConverter.ToString(utf8Bytes)}");
Console.WriteLine($"デコード後の文字列: {restoredString}");
}
}
出力結果:
バイト配列 (UTF-8): 43-23-20-31-32-33
デコード後の文字列: C# 123
注意点:エンコーディングの不一致(文字化け)
もし、エンコードとデコードで異なるエンコーディングを使用すると、データは正しく復元されず「文字化け」が発生します。
例えば、日本語をUTF-8でエンコードし、それをASCII(日本語を含まない規格)でデコードしようとする例です。
using System;
using System.Text;
public class MismatchExample
{
public static void Main()
{
string japaneseText = "こんにちは";
// UTF-8 でエンコード
byte[] utf8Bytes = Encoding.UTF8.GetBytes(japaneseText);
Console.WriteLine($"UTF-8 (Bytes): {BitConverter.ToString(utf8Bytes)}");
// ASCII でデコード (間違い)
// ASCII は日本語を表現できないため、'?' に置き換えられる
string garbledText = Encoding.ASCII.GetString(utf8Bytes);
Console.WriteLine($"ASCIIデコード: {garbledText}");
// 正しいデコード (UTF-8)
string correctText = Encoding.UTF8.GetString(utf8Bytes);
Console.WriteLine($"UTF-8デコード: {correctText}");
}
}
出力結果:
UTF-8 (Bytes): E3-81-93-E3-82-93-E3-81-AB-E3-81-A1-E3-81-AF
ASCIIデコード: ???????????????
UTF-8デコード: こんにちは
まとめ
stringとbyte[]の相互変換は、System.Text.EncodingクラスのGetBytes(エンコード)とGetString(デコード)を使用するのが基本です。
Encoding.UTF8: WebやAPI連携、ファイル保存など、外部とデータをやり取りする際は、Encoding.UTF8を使用することが強く推奨されます。- 一貫性の維持:
GetBytesでエンコードした際に使用したエンコーディングは、GetStringでデコードする際に必ず同じものを使用する必要があります。
