文字列が結合できない?

解決


ゆう  2003-05-29 02:58:06  No: 78070

GetPrivateProfileStringとWritePrivateProfileStringの
APIを使用して文字列をiniファイルから読み書きする
GetIniFileValueとWriteIniFileValueという関数があります。

この関数を利用してiniファイルから文字列を取得します。
そして取得後に文字列を結合しようとするとiniファイルから
取得した文字列が日本語のときに、文字列が結合できないという
現象が発生してしまいます。

実際は
  日本語 + aaa = 日本語
  aaa + 日本語 = aaa日本語

というように取得した文字が日本語だった場合にその後ろに文字列を
結合できなくなります。

長文ですいません。どうぞよろしくお願いします。
WinXP pro & VB.NET です。


oku  URL  2003-05-29 06:07:44  No: 78071

Netは知らないんですが、VB6で今試しましたが出来ましたよ。
INIファイル読むって、もちろん2回やってるんですよね?
単純に読めてないだけのような気がします。

WinXP Home    VB6.0SP5


nanashi  2003-05-29 09:59:10  No: 78072

> GetIniFileValueとWriteIniFileValueという関数があります。

これは自作の関数でしょうか?

XPは使ったことが無いので分かりませんが、
通常GetPrivateProfileStringを使ってString型の変数に取得すれば
日本語だろうがなんだろうが普通に文字列操作できます。
まずiniファイルのデータをキチンと取得できてるかどうか確認された方が良いでしょう。


ゆう  2003-05-29 17:56:10  No: 78073

>okuさん、nanashiさん  ありがとうございます。

チェックしましたが、iniファイルからデータは取れていると思います。
自作の関数が悪いのかと思いテストプログラムを作成してみました。

'iniファイル読込
Public Function getInifileValue( _
                   ByVal vstrFileName As String, _
                   ByVal vstrSec As String, _
                   ByVal vstrKey As String _
                   ) As String
'vstrFileName   :iniファイル名
'vstrSec        :セクション       
'vstrKey        :キー
    Dim strBuffer As String
    Dim iRet As Integer

    strBuffer = Space(256) 'バッファの初期化
    vstrFileName = getAppPath() & vstrFileName

    'INIファイルから情報を取得
    iRet = GetPrivateProfileString( _
            vstrSec, vstrKey, "Error", strBuffer, 256, vstrFileName)

    getInifileValue = Left(strBuffer, iRet)

End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As                               System.EventArgs) Handles Button1.Click
    Dim str1 As String
    Dim str2 As String
    Const con1 = "xxxxxx.ini"
    Const con2 = "String"
    Const con3_1 = "1"
    Const con3_2 = "2"
    
    str1 = getInifileValue(con1, con2, con3_1)
    str2 = getInifileValue(con1, con2, con3_2)
    
    Trace.Write("1+2:" & str1 & str2)
    Trace.Write("2+1:" & str2 & str1)          
End Sub

iniファイル
[String]
1=aaa
2=日本語

これを実行すると
1+2:aaa日本語
2+1:日本語
という結果になってしまいます。

自作の関数できちんとデータを取得できていないんでしょうか?
よろしくお願いします。


とろ  2003-05-29 18:16:20  No: 78074

恐らくこういうことだと思います。

あなたの自作した関数の戻り値では、
str1 = "日本語" & vbNullChar & "  "
str2 = "aaa"
がそれぞれにセットされます。

str1 & str2 = "aaa日本語" & vbNullChar & "  "
となり vbNullChar までの "aaa日本語" が返りますが、
str2 & str1 = "日本語" & vbNullChar & "  aaa"
となり vbNullChar までの "日本語" しか返ってこない。

Visual Basic では、 UNICODE なので、
    getInifileValue = Left(strBuffer, iRet)
というふうに、 GetPrivateProfileString の戻り値を使わずに、
strBuffer から vbNullChar の直前までの文字列を取得するようにしましょう。


とろ  2003-05-29 18:17:44  No: 78075

> str1 = "日本語" & vbNullChar & "  "
> str2 = "aaa"

逆でしたね。
str1 = "aaa"
str2 = "日本語" & vbNullChar & "  "


魔界の仮面弁士  2003-05-29 18:47:56  No: 78076

当方の環境で、提示されたコードを試して見ましたが、問題ありませんでしたよ。
  1+2:aaa日本語
  2+1:日本語aaa
という結果が出力されましたので。なお、こちらの環境は、以下の通りです。
  Visual Studio.NET 2003 日本語版 (Ver.7.1.3091)
  .NET Framework 1.1 (Ver.1.1.4322)
  Windows XP Service Pack 1無印 (Build 2600.xpsp2.021108-1929)
  Internet Explorer 6 Service Pack 1 (Ver.6.0.2800.1106.xpsp2.021108-1929)

ただし、実験前に以下のような修正を施してあります。

1) 結果の出力には、Trace.Write の代わりに Trace.WriteLine を利用しました。

2) 下記の部分で警告が出たため、それぞれに As String 宣言を施しました。
    Const con1 = "xxxxxx.ini"
    Const con2 = "String"
    Const con3_1 = "1"
    Const con3_2 = "2"

# 私は、VS.NET オプション設定にて、VBの『既定のプロジェクト設定』の
# 項目にある、Option Explicit と、Option Strict の両方を On に設定しています。

3) getAppPath() メソッドが未宣言エラーとなったため、vstrFileName に、
   直接 ini ファイルのフルパスを格納させて実験しました。

4) Left(strBuffer, iRet) の部分で、フォームのLeftプロパティと誤認されたので、
   以下のように名前空間を補足しました。
   getInifileValue = Microsoft.VisualBasic.Left(strBuffer, iRet) 

5) 一番肝心なPInvoke呼び出しの宣言部を書いて頂けなかったので、
   こちらで、以下のような宣言を施しました。

    <System.Runtime.InteropServices.DllImport("KERNEL32.DLL", _
    Charset:=Runtime.InteropServices.CharSet.Auto, ExactSpelling:=False)> _
    Public Shared Function GetPrivateProfileString( _
        ByVal lpAppName As String, _
        ByVal lpKeyName As String, _
        ByVal lpDefault As String, _
        ByVal lpReturnedString As String, _
        ByVal nSize As System.Int32, _
        ByVal lpFileName As String) As System.Int32
    End Function

# XP環境なので、実際にはWide系のエントリポイントが読み込まれていると思います。


ゆう  2003-05-29 23:12:12  No: 78077

>とろさん,魔界の仮面弁士さん
レスありがとうございます。

とろさんの言ったようにvbNullChar直前までの文字を取得したところ
うまくいきました。どうもありがとうございました。

>魔界の仮面弁士さん
API呼び出しはDeclareで宣言しています。
まだ.NET環境に慣れていないもので (^_^;;)


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加