閉じる

【C#】文字列とバイト配列を相互変換する方法!Encodingでの文字コード指定も解説

C#を用いてアプリケーションを開発する際、テキストデータをファイルに保存したり、ネットワーク経由で送信したりする場面が多々あります。

その際、コンピューターが理解できる形式であるバイト配列(byte[])への変換は避けて通れません。

逆に、受け取ったバイナリデータを人間が読める文字列に復元する処理も同様に重要です。

本記事では、現代のC#開発において標準的かつ効率的な「文字列とバイト配列の相互変換」について、文字コードの基礎知識から最新のパフォーマンス最適化手法まで徹底的に解説します。

文字列とバイト配列の変換が必要な理由

C#の内部では、文字列(string)はUTF-16という形式で保持されています。

しかし、インターネットの世界ではUTF-8が標準であり、Windowsの古いファイルシステムではShift_JIS(CP932)が使われていることもあります。

これらの異なる「言葉のルール」を橋渡しするのが、文字エンコーディングの役割です。

エンコーディングの基本概念

文字列をバイト配列に変換することをエンコード(符号化)と呼び、その逆をデコード(復号)と呼びます。

この変換を行う際に最も重要なのが「どの文字コード(Encoding)を使用するか」という点です。

例えば、同じ「あ」という文字でも、UTF-8では3バイト(0xE3, 0x81, 0x82)になりますが、Shift_JISでは2バイト(0x82, 0xA0)になります。

変換時と復元時で異なるエンコーディングを使用すると、いわゆる文字化けが発生するため、常にペアを意識する必要があります。

文字列からバイト配列へ変換する(GetBytes)

C#で文字列をバイト配列に変換する最も一般的な方法は、System.Text.EncodingクラスのGetBytesメソッドを使用することです。

標準的な変換方法

以下のコードは、文字列をUTF-8形式のバイト配列に変換する基本的な例です。

C#
using System;
using System.Text;

class Program
{
    static void Main()
    {
        // 変換対象の文字列
        string sourceString = "C#文字列変換のテスト";

        // UTF-8エンコーディングを使用してバイト配列に変換
        byte[] byteArray = Encoding.UTF8.GetBytes(sourceString);

        // 結果を表示
        Console.WriteLine($"元の文字列: {sourceString}");
        Console.WriteLine("変換後のバイト配列(16進数):");
        foreach (byte b in byteArray)
        {
            Console.Write($"{b:X2} ");
        }
        Console.WriteLine();
        Console.WriteLine($"バイト長: {byteArray.Length}バイト");
    }
}
実行結果
元の文字列: C#文字列変換のテスト
変換後のバイト配列(16進数):
43 23 E6 96 87 E5 AD 97 E5 88 97 E5 A4 89 E6 8F 9B E3 81 AE E3 83 86 E3 82 B9 E3 83 88 
バイト長: 30バイト

この例では、Encoding.UTF8プロパティを使用してUTF-8のインスタンスを取得しています。

現代のWeb開発や多くのアプリケーションではUTF-8が推奨されるため、特に理由がない限りはこの設定を利用するのが無難です。

特定の文字コード(Shift_JISなど)を指定する

日本のレガシーシステムやExcel向けのCSV出力などでは、Shift_JISが必要になる場合があります。

ただし、モダンな.NET(Core/5以降)では、標準でShift_JISがサポートされていないため、CodePagesEncodingProviderを登録する必要があります。

C#
using System;
using System.Text;

class Program
{
    static void Main()
    {
        // .NET Core/5以降でShift_JISを扱うためにプロバイダーを登録
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

        string text = "こんにちは";

        // Shift_JIS(コードページ932)を指定
        Encoding sjis = Encoding.GetEncoding("shift_jis");
        byte[] bytes = sjis.GetBytes(text);

        Console.WriteLine($"Shift_JISでのバイト数: {bytes.Length}バイト");
        // 「こんにちは」は全角5文字なのでShift_JISでは10バイトになる
    }
}
実行結果
Shift_JISでのバイト数: 10バイト

Encoding.GetEncoding("shift_jis")を呼び出す前に、必ずEncoding.RegisterProviderを実行してください。

これを忘れるとNotSupportedExceptionが発生し、プログラムが停止してしまいます。

バイト配列から文字列へ変換する(GetString)

受け取ったバイナリデータを文字列に戻すには、GetStringメソッドを使用します。

このとき、必ずエンコード時と同じ文字コードを指定してください。

基本的なデコード処理

C#
using System;
using System.Text;

class Program
{
    static void Main()
    {
        // サンプルのバイト配列 (UTF-8での「Hello」)
        byte[] utf8Bytes = { 0x48, 0x65, 0x6C, 0x6C, 0x6F };

        // バイト配列を文字列に復元
        string result = Encoding.UTF8.GetString(utf8Bytes);

        Console.WriteLine($"復元された文字列: {result}");
    }
}
実行結果
復元された文字列: Hello

配列の一部だけを変換する場合

ネットワーク通信などで、大きなバッファの一部にだけデータが入っている場合、開始位置(インデックス)と長さを指定して変換できます。

これにより、不要なメモリコピーを抑えることが可能です。

C#
byte[] buffer = new byte[1024];
// ... 何らかの通信処理でbufferにデータが入る ...
int receivedLength = 13; // 実際に受け取ったサイズ

// 0番目からreceivedLength分だけを文字列にする
string data = Encoding.UTF8.GetString(buffer, 0, receivedLength);

主要なEncodingクラスのプロパティ

C#のEncodingクラスには、よく使われる文字コードがあらかじめプロパティとして用意されています。

それぞれの特徴を整理しました。

プロパティ文字コード特徴
Encoding.UTF8UTF-8現在の標準。多くの環境で推奨される。
Encoding.UnicodeUTF-16 (LE)C#の内部表現に最も近い。Windowsアプリ内部で多用。
Encoding.ASCIIASCII7ビット文字のみ。日本語はすべて「?」に化ける。
Encoding.DefaultOS依存.NET Core以降は常にUTF-8。古い.NET Frameworkでは環境依存。
注意点

Encoding.Defaultは実行環境によって挙動が変わる可能性があるため、明示的にEncoding.UTF8などを指定することが、バグを防ぐための鉄則です。

高度な変換手法:パフォーマンスとメモリ効率

大量のデータを扱う場合や、高頻度で変換を行うリアルタイム処理では、byte[]の新規作成によるメモリ確保(アロケーション)がパフォーマンスのボトルネックになることがあります。

Span<T>を利用した変換

.NET Core 2.1以降で導入されたSpan<T>ReadOnlySpan<T>を利用すると、スタック領域や既存のバッファを利用して高速に変換できます。

C#
using System;
using System.Text;

class Program
{
    static void Main()
    {
        string text = "高速な変換処理";
        
        // 必要なバイト数を計算
        int byteCount = Encoding.UTF8.GetByteCount(text);
        
        // スタック上にメモリを確保 (非常に高速だがサイズ制限に注意)
        Span<byte> buffer = stackalloc byte[byteCount];
        
        // Spanに直接書き込む
        int written = Encoding.UTF8.GetBytes(text, buffer);

        Console.WriteLine($"書き込まれたバイト数: {written}");
    }
}

この方法では、new byte[]を行わないため、ガベージコレクション(GC)の発生を抑え、スループットを向上させることができます。

特殊な形式への変換:Base64と16進数

文字列とバイト配列の変換において、もう一つ重要なのが「バイナリデータのテキスト化」です。

これは文字コードの変換とは異なり、バイナリそのものを文字列として表現する手法です。

Base64への変換

Base64は、任意のバイナリデータを64種類の英数字のみで表現する方式です。

メールの添付ファイルや、JSONの中に画像を埋め込む際によく使われます。

C#
using System;
using System.Text;

class Program
{
    static void Main()
    {
        byte[] data = Encoding.UTF8.GetBytes("C# Base64 Test");

        // バイト配列 -> Base64文字列
        string base64String = Convert.ToBase64String(data);
        Console.WriteLine($"Base64: {base64String}");

        // Base64文字列 -> バイト配列
        byte[] decodedBytes = Convert.FromBase64String(base64String);
        string decodedString = Encoding.UTF8.GetString(decodedBytes);
        Console.WriteLine($"復元: {decodedString}");
    }
}
実行結果
Base64: QyMgQmFzZTY0IFRlc3Q=
復元: C# Base64 Test

16進数文字列への変換

デバッグ時など、バイト配列の中身を「FF 00 AB」のような形式で確認したい場合には、BitConverterや最新のConvert.ToHexStringが便利です。

C#
byte[] bytes = { 255, 0, 171, 205 };

// モダンな方法 ( .NET 5以降 )
string hex = Convert.ToHexString(bytes);
Console.WriteLine($"HEX: {hex}"); // FF00ABCD

文字化けと例外への対策

変換時に対応していない文字が含まれている場合、デフォルトでは「?」などの代替文字に置き換わります。

しかし、データ整合性が重要な場合は、エラーとして検知したいこともあるでしょう。

エンコーディングフォールバックの設定

変換に失敗したときに例外を投げるようにするには、EncoderFallbackを設定します。

C#
// 変換できない文字がある場合に例外を投げる設定
Encoding asciiWithException = Encoding.GetEncoding(
    "us-ascii",
    new EncoderExceptionFallback(),
    new DecoderExceptionFallback()
);

try
{
    // ASCIIで表現できない日本語を含む文字列を変換
    byte[] b = asciiWithException.GetBytes("あ");
}
catch (EncoderFallbackException ex)
{
    Console.WriteLine("エラー: ASCIIに変換できない文字が含まれています。");
}

このように、要件に応じてエラーハンドリングを適切に行うことが、堅牢なシステム開発への第一歩となります。

まとめ

C#における文字列とバイト配列の変換は、System.Text.Encodingクラスを軸に展開されます。

基本となるGetBytesGetStringを使いこなすことはもちろん、利用シーンに応じて適切な文字コードを選択する能力が求められます。

Web標準のUTF-8、WindowsレガシーなShift_JIS、そしてデータ転送用のBase64など、それぞれの特性を理解しておくことが重要です。

また、現代的な開発においては、Span<T>を用いた低アロケーションな実装を検討することで、よりパフォーマンスの高いアプリケーションを構築できるでしょう。

今回紹介したコード例や注意点を参考に、正確で効率的なデータ変換処理を実装してください。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!