#title(.NETプログラミング研究 第43号)

#navi(.NET プログラミング研究)

#contents

*.NETプログラミング研究 第43号 [#z0685b9a]

**.NET質問箱 [#ccd73841]

「.NET質問箱」では、「どぼん!のプログラミング掲示板」に書き込まれた.NETプログラミングに関する投稿を基に、さらに考察を加え、Q&A形式にまとめて紹介します。

-[[どぼん!のプログラミング掲示板>http://dobon.net/vb/bbs.html]]

***ページ範囲を指定して印刷するには? [#u32b923c]

#column(注意){{
この記事の最新版は「[[ページ範囲を指定して印刷する>http://dobon.net/vb/dotnet/graphics/printrange.html]]」で公開しています。
}}

''【質問】''

PrintDialogクラスを使って印刷ダイアログを表示する際に、PrintDialog.AllowSomePagesをTrueにして「ページ指定」ができるようにしたのですが、「ページ指定」を選んでもすべてのページが印刷されてしまいます。どのようにすれば指定されたページだけ印刷されるようになりますか?

''【回答】''

PrintDialog.AllowSomePagesをTrueにすることにより、印刷ダイアログでユーザーが印刷範囲を指定できるようになりますが、これだけで指定されたページのみが印刷されるようになるわけではありません。実際に指定されたページのみ印刷されるようにするには、そうなるように自分でコーディングする必要があります。

方法としては、PrinterSettings.PrintRangeがPrintRange.SomePagesとなっている時(つまり、「ページ指定」が指定された時)にPrinterSettings.FromPageとPrinterSettings.ToPageを調べてその範囲のページだけが印刷されるようにします。

次の具体的なサンプルを示します。ここではButton1がクリックされた時に印刷ダイアログが表示され、「OK」がクリックされると印刷が開始されるようにしています。印刷されるページは10ページあり、ページ数が印刷されるようになっています。「ページ指定」が指定されていると、指定されたページのみが印刷されます。

#code(vbnet){{
'現在のページ
Private currentPage As Integer = 1

'Button1のクリックイベントハンドラ
Private Sub Button1_Click(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    'PrintDocumentオブジェクトの作成
    Dim pd As New System.Drawing.Printing.PrintDocument
    'PrintPageイベントハンドラの追加
    AddHandler pd.PrintPage, AddressOf pd_PrintPage

    'PrintDialogクラスの作成
    Dim pdlg As New PrintDialog
    'PrintDocumentを指定
    pdlg.Document = pd

    'ページ指定できるようにする
    pdlg.AllowSomePages = True
    'ページ指定の最小値と最大値を指定する
    pdlg.PrinterSettings.MinimumPage = 1
    pdlg.PrinterSettings.MaximumPage = 10
    '印刷開始と終了ページを指定する
    pdlg.PrinterSettings.FromPage = pdlg.PrinterSettings.MinimumPage
    pdlg.PrinterSettings.ToPage = pdlg.PrinterSettings.MaximumPage

    '印刷の選択ダイアログを表示する
    If pdlg.ShowDialog() = DialogResult.OK Then
        'OKがクリックされた時は印刷する
        pd.Print()
    End If
End Sub

Private Sub pd_PrintPage(ByVal sender As Object, _
    ByVal e As System.Drawing.Printing.PrintPageEventArgs)
    'ページ範囲が指定されており、始めのページのときは、
    '印刷開始ページまで飛ばす
    If e.PageSettings.PrinterSettings.PrintRange = _
        System.Drawing.Printing.PrintRange.SomePages AndAlso _
        currentPage = 1 Then
        currentPage = e.PageSettings.PrinterSettings.FromPage
    End If

    'currentPageで指定されたページを描画する
    Dim f As New Font("Arial", 100)
    e.Graphics.DrawString(currentPage.ToString(), f, Brushes.Black, 0, 0)
    f.Dispose()

    '次のページがあるか調べる
    If currentPage >= 10 OrElse _
        (e.PageSettings.PrinterSettings.PrintRange = _
        System.Drawing.Printing.PrintRange.SomePages AndAlso _
        e.PageSettings.PrinterSettings.ToPage <= currentPage) Then
        '次のページがないことを通知する
        e.HasMorePages = False
        currentPage = 1
    Else
        e.HasMorePages = True
        currentPage += 1
    End If
End Sub
}}

#code(csharp){{
//現在のページ
private int currentPage = 1;

//Button1のクリックイベントハンドラ
private void Button1_Click(object sender, System.EventArgs e)
{
    //PrintDocumentオブジェクトの作成
    System.Drawing.Printing.PrintDocument pd =
        new System.Drawing.Printing.PrintDocument();
    //PrintPageイベントハンドラの追加
    pd.PrintPage +=
        new System.Drawing.Printing.PrintPageEventHandler(pd_PrintPage);

    //PrintDialogクラスの作成
    PrintDialog pdlg = new PrintDialog();
    //PrintDocumentを指定
    pdlg.Document = pd;

    //ページ指定できるようにする
    pdlg.AllowSomePages = true;
    //ページ指定の最小値と最大値を指定する
    pdlg.PrinterSettings.MinimumPage = 1;
    pdlg.PrinterSettings.MaximumPage = 10;
    //印刷開始と終了ページを指定する
    pdlg.PrinterSettings.FromPage = pdlg.PrinterSettings.MinimumPage;
    pdlg.PrinterSettings.ToPage = pdlg.PrinterSettings.MaximumPage;

    //印刷の選択ダイアログを表示する
    if (pdlg.ShowDialog() == DialogResult.OK)
    {
        //OKがクリックされた時は印刷する
        pd.Print();
    }
}

private void pd_PrintPage(object sender,
    System.Drawing.Printing.PrintPageEventArgs e)
{
    //ページ範囲が指定されており、始めのページのときは、
    //印刷開始ページまで飛ばす
    if (e.PageSettings.PrinterSettings.PrintRange ==
        System.Drawing.Printing.PrintRange.SomePages &&
        currentPage == 1)
    {
        currentPage = e.PageSettings.PrinterSettings.FromPage;
    }

    //currentPageで指定されたページを描画する
    Font f = new Font("Arial", 100);
    e.Graphics.DrawString(currentPage.ToString(),
        f, Brushes.Black, 0, 0);
    f.Dispose();

    //次のページがあるか調べる
    if (currentPage >= 10 ||
        (e.PageSettings.PrinterSettings.PrintRange ==
        System.Drawing.Printing.PrintRange.SomePages &&
        e.PageSettings.PrinterSettings.ToPage <= currentPage))
    {
        //次のページがないことを通知する
        e.HasMorePages = false;
        currentPage = 1;
    }
    else
    {
        e.HasMorePages = true;
        currentPage++;
    }
}
}}

○この記事の基になった掲示板のスレッド

-[[プリンタ選択ダイアログのページ指定印刷について | 投稿者(敬称略) のぶ, 管理人>http://dobon.net/vb/bbs/log3-3/1505.html]]

***文字コードを判別するには? [#q9ccef78]

#column(注意){{
この記事の最新版は「[[文字コードを判別する>http://dobon.net/vb/dotnet/string/detectcode.html]]」で公開しています。
}}

''【質問】''

文字コードの分からないテキストファイルを読み込む時に、その文字コードはどのように判別すればよいのでしょうか?

''【回答】''

.NET Frameworkでは文字コードを判別する方法が用意されていませんので、外部DLL、OCX等を使うか、自分でコードを書くかということになるでしょう。

次に示すコードは、私がJcode.pmのgetcodeメソッドを参考にして書かせていただいた(移植したつもり)メソッドです。バイナリ配列で渡されたデータが、JIS、Shift-JIS、EUC、UTF-8(もしくはASCII)のいずれであるかを判別し、結果をEncodingオブジェクトで返します。

-[[Jcode.pm>http://openlab.ring.gr.jp/Jcode/index-j.html]]

#code(vbnet){{
''' <summary>
''' 文字コードを判別する
''' </summary>
''' <remarks>
''' Jcode.pmのgetcodeメソッドを移植したものです。
''' Jcode.pm(http://openlab.ring.gr.jp/Jcode/index-j.html)
''' Jcode.pmのCopyright : Copyright 1999 Dan Kogai.
''' </remarks>
''' <param name="byts">文字コードを調べるデータ</param>
''' <returns>適当と思われるEncodingオブジェクト。
''' 判断できなかった時はnull。</returns>
Public Shared Function GetCode(ByVal byts() As Byte) As System.Text.Encoding
    Const bESC As Byte = &H1B
    Const bAT As Byte = &H40
    Const bDollar As Byte = &H24
    Const bAnd As Byte = &H26
    Const bOP As Byte = &H28 '(
    Const bB As Byte = &H42
    Const bD As Byte = &H44
    Const bJ As Byte = &H4A
    Const bI As Byte = &H49

    Dim len As Integer = byts.Length
    Dim [binary] As Integer = 0
    Dim ucs2 As Integer = 0
    Dim sjis As Integer = 0
    Dim euc As Integer = 0
    Dim utf8 As Integer = 0
    Dim b1, b2 As Byte

    Dim i As Integer
    For i = 0 To len - 1
        If byts(i) <= &H6 OrElse byts(i) = &H7F OrElse byts(i) = &HFF Then
            ''binary'
            [binary] += 1
            If len - 1 > i AndAlso _
            byts(i) = &H0 AndAlso byts(i - 1) <= &H7F Then
                'smells like raw unicode
                ucs2 += 1
            End If
        End If
    Next i

    If [binary] > 0 Then
        If ucs2 > 0 Then
            'JIS
            'ucs2(Unicode)
            Return System.Text.Encoding.Unicode
            'binary
        Else
            Return Nothing
        End If
    End If

    For i = 0 To len - 2
        b1 = byts(i)
        b2 = byts(i + 1)

        If b1 = bESC Then
            If b2 >= &H80 Then
                'not Japanese
                'ASCII
                Return System.Text.Encoding.ASCII
            Else
                If len - 2 > i AndAlso _
                b2 = bDollar AndAlso byts(i + 2) = bAT Then
                    'JIS_0208 1978
                    'JIS
                    Return System.Text.Encoding.GetEncoding(50220)
                ElseIf len - 2 > i AndAlso _
                b2 = bDollar AndAlso byts(i + 2) = bB Then
                    'JIS_0208 1983
                    'JIS
                    Return System.Text.Encoding.GetEncoding(50220)
                ElseIf len - 5 > i AndAlso _
                b2 = bAnd AndAlso byts(i + 2) = bAT AndAlso _
                byts(i + 3) = bESC AndAlso byts(i + 4) = bDollar AndAlso _
                byts((i + 5)) = bB Then
                    'JIS_0208 1990
                    'JIS
                    Return System.Text.Encoding.GetEncoding(50220)
                ElseIf len - 3 > i AndAlso _
                b2 = bDollar AndAlso byts(i + 2) = bOP AndAlso _
                byts(i + 3) = bD Then
                    'JIS_0212
                    'JIS
                    Return System.Text.Encoding.GetEncoding(50220)
                ElseIf len - 2 > i AndAlso b2 = bOP AndAlso _
                (byts(i + 2) = bB OrElse byts(i + 2) = bJ) Then
                    'JIS_ASC
                    'JIS
                    Return System.Text.Encoding.GetEncoding(50220)
                ElseIf len - 2 > i AndAlso _
                b2 = bOP AndAlso byts(i + 2) = bI Then
                    'JIS_KANA
                    'JIS
                    Return System.Text.Encoding.GetEncoding(50220)
                End If
            End If
        End If
    Next i

    For i = 0 To len - 2
        b1 = byts(i)
        b2 = byts(i + 1)
        If ((b1 >= &H81 AndAlso b1 <= &H9F) OrElse _
        (b1 >= &HE0 AndAlso b1 <= &HFC)) AndAlso _
        ((b2 >= &H40 AndAlso b2 <= &H7E) OrElse _
        (b2 >= &H80 AndAlso b2 <= &HFC)) Then
            sjis += 2
            i += 1
        End If
    Next i

    For i = 0 To len - 2
        b1 = byts(i)
        b2 = byts(i + 1)
        If ((b1 >= &HA1 AndAlso b1 <= &HFE) AndAlso _
        (b2 >= &HA1 AndAlso b2 <= &HFE)) OrElse _
        (b1 = &H8E AndAlso (b2 >= &HA1 AndAlso b2 <= &HDF)) Then
            euc += 2
            i += 1
        ElseIf len - 2 > i AndAlso b1 = &H8E AndAlso _
        (b2 >= &HA1 AndAlso b2 <= &HFE) AndAlso _
        (byts(i + 2) >= &HA1 AndAlso byts(i + 2) <= &HFE) Then
            euc += 3
            i += 2
        End If
    Next i

    For i = 0 To len - 2
        b1 = byts(i)
        b2 = byts(i + 1)
        If (b1 >= &HC0 AndAlso b1 <= &HDF) AndAlso _
        (b2 >= &H80 AndAlso b2 <= &HBF) Then
            utf8 += 2
            i += 1
        ElseIf len - 2 > i AndAlso _
        (b1 >= &HE0 AndAlso b1 <= &HEF) AndAlso _
        (b2 >= &H80 AndAlso b2 <= &HBF) AndAlso _
        (byts(i + 2) >= &H80 AndAlso byts(i + 2) <= &HBF) Then
            utf8 += 3
            i += 2
        End If
    Next i

    If euc > sjis AndAlso euc > utf8 Then
        'EUC
        Return System.Text.Encoding.GetEncoding(51932)
    ElseIf sjis > euc AndAlso sjis > utf8 Then
        'SJIS
        Return System.Text.Encoding.GetEncoding(932)
    ElseIf utf8 > euc AndAlso utf8 > sjis Then
        'UTF8
        Return System.Text.Encoding.UTF8
    End If
    Return Nothing
End Function
}}

#code(csharp){{
/// <summary>
/// 文字コードを判別する
/// </summary>
/// <remarks>
/// Jcode.pmのgetcodeメソッドを移植したものです。
/// Jcode.pm(http://openlab.ring.gr.jp/Jcode/index-j.html)
/// </remarks>
/// <param name="byts">文字コードを調べるデータ</param>
/// <returns>適当と思われるEncodingオブジェクト。
/// 判断できなかった時はnull。</returns>
public static System.Text.Encoding GetCode(byte [] byts)
{
    const byte bESC = 0x1B;
    const byte bAT = 0x40;
    const byte bDollar = 0x24;
    const byte bAnd = 0x26;
    const byte bOP  = 0x28;    //(
    const byte bB = 0x42;
    const byte bD = 0x44;
    const byte bJ = 0x4A;
    const byte bI = 0x49;

    int len = byts.Length;
    int binary = 0;
    int ucs2 = 0;
    int sjis = 0;
    int euc = 0;
    int utf8 = 0;
    byte b1, b2;

    for (int i = 0; i < len; i++)
    {
        if (byts[i] <= 0x06 || byts[i] == 0x7F || byts[i] == 0xFF)
        {
            //'binary'
            binary++;
            if (len - 1 > i && byts[i] == 0x00 && byts[i - 1] <= 0x7F)
            {
                //smells like raw unicode
                ucs2++;
            }
        }
    }

    if (binary > 0)
    {
        if (ucs2 > 0)
            //JIS
            //ucs2(Unicode)
            return System.Text.Encoding.Unicode;
        else
            //binary
            return null;
    }

    for (int i = 0; i < len - 1; i++)
    {
        b1 = byts[i];
        b2 = byts[i + 1];

        if (b1 == bESC)
        {
            if (b2 >= 0x80)
                //not Japanese
                //ASCII
                return System.Text.Encoding.ASCII;
            else if (len - 2 > i &&
                b2 == bDollar && byts[i + 2] == bAT)
                //JIS_0208 1978
                //JIS
                return System.Text.Encoding.GetEncoding(50220);
            else if (len - 2 > i &&
                b2 == bDollar && byts[i + 2] == bB)
                //JIS_0208 1983
                //JIS
                return System.Text.Encoding.GetEncoding(50220);
            else if (len - 5 > i &&
                b2 == bAnd && byts[i + 2] == bAT && byts[i + 3] == bESC &&
                byts[i + 4] == bDollar && byts[i + 5] == bB)
                //JIS_0208 1990
                //JIS
                return System.Text.Encoding.GetEncoding(50220);
            else if (len - 3 > i &&
                b2 == bDollar && byts[i + 2] == bOP && byts[i + 3] == bD)
                //JIS_0212
                //JIS
                return System.Text.Encoding.GetEncoding(50220);
            else if (len - 2 > i &&
                b2 == bOP && (byts[i + 2] == bB || byts[i + 2] == bJ))
                //JIS_ASC
                //JIS
                return System.Text.Encoding.GetEncoding(50220);
            else if (len - 2 > i &&
                b2 == bOP && byts[i + 2] == bI)
                //JIS_KANA
                //JIS
                return System.Text.Encoding.GetEncoding(50220);
        }
    }

    for (int i = 0; i < len - 1; i++)
    {
        b1 = byts[i];
        b2 = byts[i + 1];
        if (((b1 >= 0x81 && b1 <= 0x9F) || (b1 >= 0xE0 && b1 <= 0xFC)) &&
            ((b2 >= 0x40 && b2 <= 0x7E) || (b2 >= 0x80 && b2 <= 0xFC)))
        {
            sjis += 2;
            i++;
        }
    }
    for (int i = 0; i < len - 1; i++)
    {
        b1 = byts[i];
        b2 = byts[i + 1];
        if (((b1 >= 0xA1 && b1 <= 0xFE) && (b2 >= 0xA1 && b2 <= 0xFE)) ||
            (b1 == 0x8E && (b2 >= 0xA1 && b2 <= 0xDF)))
        {
            euc += 2;
            i++;
        }
        else if (len - 2 > i && 
            b1 == 0x8E && (b2 >= 0xA1 && b2 <= 0xFE) &&
            (byts[i + 2] >= 0xA1 && byts[i + 2] <= 0xFE))
        {
            euc += 3;
            i += 2;
        }
    }
    for (int i = 0; i < len - 1; i++)
    {
        b1 = byts[i];
        b2 = byts[i + 1];
        if ((b1 >= 0xC0 && b1 <= 0xDF) && (b2 >= 0x80 && b2 <= 0xBF))
        {
            utf8 += 2;
            i++;
        }
        else if (len - 2 > i &&
            (b1 >= 0xE0 && b1 <= 0xEF) && (b2 >= 0x80 && b2 <= 0xBF) &&
            (byts[i + 2] >= 0x80 && byts[i + 2] <= 0xBF))
        {
            utf8 += 3;
            i += 2;
        }
    }

    if (euc > sjis && euc > utf8)
        //EUC
        return System.Text.Encoding.GetEncoding(51932);
    else if (sjis > euc && sjis > utf8)
        //SJIS
        return System.Text.Encoding.GetEncoding(932);
    else if (utf8 > euc && utf8 > sjis)
        //UTF8
        return System.Text.Encoding.UTF8;

    return null;
}
}}

次にこのメソッドの使い方を示します。このサンプルでは、TextBox1にテキストファイルのパスを入力し、Button1をクリックすると、テキストファイルの文字コードを調べ、デコードし、RichTextBox1にその内容を表示しています。

#code(vbnet){{
'Button1のクリックイベントハンドラ
Private Sub Button1_Click(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    'テキストファイルを開く
    Dim fs As New System.IO.FileStream(TextBox1.Text, _
        System.IO.FileMode.Open, System.IO.FileAccess.Read)
    Dim bs(fs.Length - 1) As Byte
    'byte配列に読み込む
    fs.Read(bs, 0, bs.Length)
    fs.Close()

    '文字コードを取得する
    Dim enc As System.Text.Encoding = GetCode(bs)

    'デコードして表示する
    RichTextBox1.Text = enc.GetString(bs)
End Sub
}}

#code(csharp){{
//Button1のクリックイベントハンドラ
private void Button1_Click(object sender, System.EventArgs e)
{
    //テキストファイルを開く
    System.IO.FileStream fs = new System.IO.FileStream(
        TextBox1.Text, System.IO.FileMode.Open,
        System.IO.FileAccess.Read);
    byte[] bs = new byte[fs.Length];
    //byte配列に読み込む
    fs.Read(bs, 0, bs.Length);
    fs.Close();

    //文字コードを取得する
    System.Text.Encoding enc = GetCode(bs);

    //デコードして表示する
    RichTextBox1.Text = enc.GetString(bs);
}
}}

またクラスとして、「G-PROJECT」さんが「文字コード判別・変換クラス」を公開されています。判別できる文字コードは、JIS、Shift-JIS、EUC、UTF-8のようです。

-[[■G-PROJECT■ -文字コード判別・変換クラス(C#)>http://kasumi.sakura.ne.jp/~gm/gpj/dev/tips/net/txtenc.shtml]]

外部DLLに頼る方法としては、mlang.dllのIMultiLanguage2::DetectInputCodepageを使用する方法があります。文字コードの判別が必要な大半のアプリで、これが使われているのではないかと思います。(Internet Explorer 5以上で使用できます。)

-[[IMultiLanguage2::DetectInputCodepage Method>http://msdn.microsoft.com/workshop/misc/mlang/reference/ifaces/imultilanguage2/detectinputcodepage.asp]]

以下に.NETでIMultiLanguage2::DetectInputCodepageメソッドを使うための方法を簡単に説明します。

mlang.dllを使うため、VS.NETの「参照の追加」でCOMを探してみても、mlang.dllは通常見つかりません。これは、mlang.dllにタイプライブラリがないためです。よってまず"MIDL.EXE"を使用して、"MLang.Idl"から"MLang.tlb"を作成し、これを"regtlib.exe"を使って登録します。(VS.NET 2003 をインストールしたフォルダが"C:\Program Files\Microsoft Visual Studio .NET 2003"であるならば、"MIDL.EXE"は"C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\Bin\Midl.Exe"に、"MLang.Idl"は"C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include\MLang.Idl"にあるでしょう。)これで「参照の追加」の「COM」で"mlang.dll"(MultiLanguage Object Model)を選択できるようになります。(VS.NETを使わない場合は、"Tlbimp.exe"を使ってinterop assembly(相互運用機能アセンブリ)を作成します。)

これで、DetectInputCodepageメソッドを使う準備ができました。次にDetectInputCodepageメソッドを使って文字コードを判別するサンプルを紹介します。このサンプルでも先と同じく、TextBox1にテキストファイルのパスを入力し、Button1をクリックすると、テキストファイルの文字コードを調べ、デコードし、RichTextBox1にその内容を表示しています。

#code(vbnet){{
'Button1のクリックイベントハンドラ
Private Sub Button1_Click(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
    'テキストファイルを開く
    Dim fs As New System.IO.FileStream(TextBox1.Text, _
        System.IO.FileMode.Open, System.IO.FileAccess.Read)
    Dim bs(fs.Length - 1) As Byte
    'byte配列に読み込む
    fs.Read(bs, 0, bs.Length)
    fs.Close()

    'sbyte型配列に変換する
    Dim sbs(bs.Length - 1) As System.SByte
    System.Buffer.BlockCopy(bs, 0, sbs, 0, bs.Length)

    '文字コードを判別する
    Dim enc As System.Text.Encoding = DetectEncoding(sbs)

    'デコードして表示する
    RichTextBox1.Text = enc.GetString(bs)
End Sub

''' <summary>
''' IMultiLanguage2.DetectInputCodepageを使って文字コードを判別する
''' </summary>
''' <param name="sbyts">文字コードを調べるデータ</param>
''' <returns>適当と思われるEncodingオブジェクト。</returns>
Public Shared Function DetectEncoding(ByVal sbyts() As System.SByte) _
    As System.Text.Encoding
    '準備
    Dim ml As New MultiLanguage.CMultiLanguageClass
    Dim scores As Integer = 10
    Dim detects(scores - 1) As MultiLanguage.tagDetectEncodingInfo
    Dim len As Integer = sbyts.Length

    '文字コードを判別
    ml.DetectInputCodepage(Convert.ToUInt32(0), Convert.ToUInt32(0), _
        sbyts(0), len, detects(0), scores)

    '一番初めのtagDetectEncodingInfoのEncodingを返す
    Return System.Text.Encoding.GetEncoding( _
        Convert.ToInt32(detects(0).nCodePage))
End Function
}}

#code(csharp){{
//Button1のクリックイベントハンドラ
private void Button1_Click(object sender, System.EventArgs e)
{
    //テキストファイルを開く
    System.IO.FileStream fs = new System.IO.FileStream(
        TextBox1.Text, System.IO.FileMode.Open,
        System.IO.FileAccess.Read);
    byte[] bs = new byte[fs.Length];
    //byte配列に読み込む
    fs.Read(bs, 0, bs.Length);
    fs.Close();

    //sbyte型配列に変換する
    sbyte[] sbs = new sbyte[bs.Length];
    System.Buffer.BlockCopy(bs, 0, sbs, 0, bs.Length);

    //文字コードを判別する
    System.Text.Encoding enc = DetectEncoding(sbs);

    //デコードして表示する
    RichTextBox1.Text = enc.GetString(bs);
}

/// <summary>
/// IMultiLanguage2.DetectInputCodepageを使って文字コードを判別する
/// </summary>
/// <param name="sbyts">文字コードを調べるデータ</param>
/// <returns>適当と思われるEncodingオブジェクト。</returns>
public static System.Text.Encoding DetectEncoding(sbyte [] sbyts)
{
    //準備
    MultiLanguage.IMultiLanguage2 ml = new
        MultiLanguage.CMultiLanguageClass();
    int scores = 10;
    MultiLanguage.tagDetectEncodingInfo[] detects =
        new MultiLanguage.tagDetectEncodingInfo[scores];
    int len = sbyts.Length;

    //文字コードを判別
    ml.DetectInputCodepage(
        0, 0, ref sbyts[0], ref len, ref detects[0], ref scores);

    //一番初めのtagDetectEncodingInfoのEncodingを返す
    return System.Text.Encoding.GetEncoding(
        (int) detects[0].nCodePage);
}
}}

DetectInputCodepageメソッドにより、複数の候補がtagDetectEncodingInfoとして取得されることがありますが、0番目のtagDetectEncodingInfoを採用するようにしています。また上記の方法では判別するデータをsbyte型配列として指定するため、byte型配列をsbyte型配列に変換しています。

○この記事の基になった掲示板のスレッド

-[[文字コードについて | 投稿者(敬称略) nao, 管理人>http://dobon.net/vb/bbs/log3-4/1733.html]]

**コメント [#x91966b6]
#comment

//これより下は編集しないでください
#pageinfo([[:Category/.NET]],2004-10-14 (木) 06:00:00,DOBON!,2010-03-21 (日) 19:40:10,DOBON!)
[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]