質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • VB.NET

    916questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

  • Oracle

    601questions

    Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。

VB.NETとoracleのShift-JISエンコードについて

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 434

koji2017

score 9

Shift-JISに変換できない文字をoracleのDB(キャラクターセットはシフトJIS)にいれると半角ハテナになるかどうかを
oracleに入れる前にVB.NET上で判定する方法はありますか?
半角ハテナになるか全角ハテナになるのかを事前に判定したいのです。
(oracleの文字化けには「半角ハテナ」と「全角ハテナ」になるケースがあるがどちらになるか判定したい)
よろしくお願いします。

文字化けの例)
森鷗外の「鷗」 → 全角ハテナ(?)
ℓ(リットル) → 半角ハテナ(?)

判定したい目的)
文字化け後の文字がファイル名に使えるかどうか判定したいから
(半角ハテナはファイル名に使用不可、全角は使用可)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • YAmaGNZ

    2018/08/04 07:39 編集

    どのような処理順序なのか分かりませんが、DBに格納し文字化けOKのデータをファイル名として利用するなら、文字化け後の半角?を置き換えすればいいだけなのでは?

    キャンセル

  • sysjojo

    2018/08/04 08:25

    質問内容と異なるのでこちらにあげましたが、こういうことがやりたいわけではなくて、ですか? https://dobon.net/vb/dotnet/file/invalidpathchars.html

    キャンセル

  • koji2017

    2018/08/04 16:49

    ちょっと違いますね。oracleに入れた後文字化けするかを判定したいのです。

    キャンセル

回答 3

checkベストアンサー

0

ちょっと面白そうなので前回回答のあと色々と調べていたところ、同じクエリを発行してもクライアントによって結果が異なることに気づきました。
例えば、select '€' chr from dualというクエリをVB.NETから投げると'?'(半角)が返ってきますが、A5SQLから投げると'?'(全角)が返ってきます。
もしかしたらクライアント依存の部分があるのでは。

そこでVB.NETで全文字1文字ずつselectして試してみました。
以下検証コード。

Imports Oracle.ManagedDataAccess.Client
Public Class Form1
    Dim ds As New List(Of EncData)
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        For i = 0 To 55295
            Try
                Dim d As New EncData
                d.codep = i
                d.orig = Char.ConvertFromUtf32(i)
                ds.Add(d)
            Catch ex As Exception
            End Try
        Next
        ora_convert(ds)
        to_file(ds)
        DataGridView1.DataSource = ds
    End Sub
    Private Sub ora_convert(ByRef lds As List(Of EncData))
        Dim constr = "User Id=xxxx;Password=xxxx;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=XE)))"
        Dim conn = New OracleConnection(constr)
        conn.Open()
        Dim sql = "select :val from dual"
        Dim cmd = conn.CreateCommand
        cmd.Connection = conn
        cmd.CommandType = CommandType.Text
        cmd.CommandText = sql
        lds.ForEach(Sub(s)
                        cmd.Parameters.Clear()
                        cmd.Parameters.Add("val", s.orig)
                        Dim result = cmd.ExecuteScalar
                        s.convto = result.ToString
                    End Sub)
        conn.Close()
        conn.Dispose()
    End Sub
    Private Sub to_file(ByRef lds As List(Of EncData))
        Dim fp = My.Computer.FileSystem.OpenTextFileWriter("output.txt", False)
        For Each item In lds
            fp.Write(item.codep)
            fp.Write(vbTab)
            fp.Write(item.orig)
            fp.Write(vbTab)
            fp.Write(item.convto)
            fp.Write(vbTab)
            fp.Write(item.isWideOrSmallQs)
            fp.Write(vbTab)
            fp.WriteLine()
        Next
        fp.Close()
        fp.Dispose()
    End Sub
End Class
Public Class EncData
    Public Property codep As Integer
    Public Property orig As String
    Public Property convto As String
    Public ReadOnly Property isWideOrSmallQs As String
        Get
            If IsNothing(convto) Then
                Return "-"
            ElseIf convto = "?" Then
                Return "Wide"
            ElseIf convto = "?" Then
                Return "Small"
            Else
                Return "-"
            End If
        End Get
    End Property
End Class


結果は、U2FFF以下かつSJISにエンコードできない文字は半角クエスチョンに、U3000以上は全角クエスチョンになりました。全部試していませんがA5SQLからだとおそらくすべて全角クエスチョンになります。

つまり、変換できない文字がどのように扱われるかは環境依存となり、解決策は実環境で全文字変換してリストを作り、そのリストをもとに個別にどう扱うか検討する必要がある、ということでしょう。

なお、上のコードはOracle.ManagedDataAccessで実行した結果で、クライアント側のドライバが変わると結果が変わる可能性があるので、質問者さんのほうでも個別検証して結果を取得すべきと思います。

 8/4 追記を受けて

判定したい目的)
文字化け後の文字がファイル名に使えるかどうか判定したいから
(半角ハテナはファイル名に使用不可、全角は使用可)

という理由なら、本回答で例示した変換表をもって事前変換するか、処理の都度検証コードでも書いたselect :var from dualをOracle側に投げて変換後の文字列を事前取得。それをもってファイル名のバリデーションをかければいいのではないかと。
前述したとおりクライアントによって変換の仕様が異なるので試しに投げてみるのが一番だと考えます。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/04 16:55

    insertしなくてもselectだけで確認できるのですね。
    ありがとうございました!

    キャンセル

0

直接の回答ではありませんが、Oracleのテーブルに異なるキャラクタセットの文字列を入れたい でNCHARやNVARCHAR2データ型にutf-8 のデータを入れられるようですので、文字化けを避けられるか試してみては?

追記
以下のようにUnicodeは変更されます。
Unicode 各バージョンとその特徴 プログラム・コードできちんと対応できているユーザーはたぶんないでしょう。運用でカバーがほとんどかと。
もっと建設的な方向に労力を費やした方がよろしいかと。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/26 19:32

    ご回答ありがとうございます!
    文字化けを避けたいわけではないのです。
    どのように化けるか事前に判定したいのです。
    わかりにくくて申し訳ありません。

    キャンセル

  • 2018/07/26 22:40

    回答を追記しました。Unicodeは変更が付きまといますから、文字化けを事前に判定するのは難しいです。

    キャンセル

0

.NET側で文字列をSJISバイト配列へ変換→SJIS文字列に戻してやれば、少なくとも.NET(Windows)でSJISとして扱えない文字列が?になるので元の文字列と比較してやればわかります。

今実行できる環境がC#しかなかったためC#で書いていますがVB.NETでもほぼ同じ構文です。

using System.IO;
using System;
using System.Text;

class Program
{
    static void Main()
    {
        String target = "あいうえお㎖かきくけこ";  //㎖はUnicodeにはあるがsjisにはない
        Encoding enc = System.Text.Encoding.GetEncoding(932);
        String target_to = enc.GetString(enc.GetBytes(target));
        Console.WriteLine(target_to); // あいうえお?かきくけこ
    }
}

ただし、厳密にはOracleDBで扱うSJIS(正確にはJA16SJISTILDE)とWindowsのSJIS(MS932)は微妙に違うかもしれませんが申し訳ないですがうろおぼえです。簡易的な判定方法としてご紹介します。

実際にシステムで使用する文字をテストしてから導入してくださいね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/01 23:48

    ありがとうございます。
    しかしこの方法ではoracleに入れたときに全角ハテナになるかどうかは判定できないですね。

    キャンセル

  • 2018/08/02 07:14

    実際に全角クエスチョンマークに変換される文字を例示してください。
    どんな文字がありますか?

    キャンセル

  • 2018/08/02 13:18 編集

    koji2017様
    全角ハテナとは「?」のことですか、それとも「�」(U+FFFD)のことですか?
    あと、hope_mucci様ご指摘のように、どのような文字で全角ハテナに文字化けするかが分かれば、ある程度は傾向が見えてくるかも知れません。
    ただ、そもそも、文字化けの種類の判定が必要な理由は何なのでしょうか?

    キャンセル

  • 2018/08/04 07:27

    文字化けの例と判定が必要な理由を追記しました

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.53%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • VB.NET

    916questions

    Microsoft Visual Basic .NETのことで、Microsoft Visual Basic(VB6)の後継。 .NET環境向けのプログラムを開発することができます。 現在のVB.NETでは、.NET Frameworkを利用して開発を行うことが可能です。

  • Oracle

    601questions

    Oracleは、米オラクルが取り扱うリレーショナルデータベース管理システムです。メインフレームからPCまで、多様なプラットフォームに対応しています。