#navi(contents-page-name): No such page: .NET プログラミング研究

.NETプログラミング研究 第43号

.NET質問箱

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

ページ範囲を指定して印刷するには?

注意

この記事の最新版は「ページ範囲を指定して印刷する」で公開しています。

【質問】

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

【回答】

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

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

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

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
'現在のページ
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
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
//現在のページ
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++;
    }
}

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

文字コードを判別するには?

注意

この記事の最新版は「文字コードを判別する」で公開しています。

【質問】

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

【回答】

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

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

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
''' <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
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/// <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にその内容を表示しています。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
'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
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
//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のようです。

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

以下に.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にその内容を表示しています。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
'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
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
//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型配列に変換しています。

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

コメント



ページ情報
  • カテゴリ : .NET
  • 作成日 : 2004-10-14 (木) 06:00:00
  • 作成者 : DOBON!
  • 最終編集日 : 2010-03-21 (日) 19:40:10
  • 最終編集者 : DOBON!
[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]