- PR -

漢字のフォルダパスとファイルパスがつながらない。

投稿者投稿内容
Blue
大ベテラン
会議室デビュー日: 2005/09/12
投稿数: 230
お住まい・勤務地: 知っている人は知っている
投稿日時: 2007-01-29 12:15
ちなみに、StringBuilderクラスを使えば格納文字数を気にしないでも、
ToStringメソッドが勝手に文字列を切り出してくれます。

参考:IT > Insider.NET > .NET TIPS > INIファイルを読み書きするには?
http://www.atmarkit.co.jp/fdotnet/dotnettips/039inifile/inifile.html

# KIさんから同様のレスがついていました。
えんぴつ
常連さん
会議室デビュー日: 2006/12/27
投稿数: 23
投稿日時: 2007-01-29 16:40
KIさんのコードにより無事結合できました。
Blueさんより
引用:
>rctIni.strSysSeverDir = strReturnValue.Substring(0, intLength)
を再考(VB6のときはvbNullCharを探して文字列を分割したけど)するか、

ちなみに、StringBuilderクラスを使えば格納文字数を気にしないでも、
ToStringメソッドが勝手に文字列を切り出してくれます。


StringBuilderを使うことによって文字列を切り出すコード、rctIni.strSysSeverDir = strReturnValue.Substring(0, intLength)
が必要なくなり、GetPrivateProfileStringWにする必要もなくなったと考えていいんですよね?
自分の中ではMarshalが必要なくなった意味があまりよくわかりません。
GetPrivateProfileStringAにしろ、GetPrivateProfileStringWにしろ、型の違いを調整するMarshalは必要な気がするのですが、、。

Jittaさんより
引用:
VBなのに 円マーク をエスケープしているから


円マーク をエスケープしているとはどのようなことでしょうか?

Blue
大ベテラン
会議室デビュー日: 2005/09/12
投稿数: 230
お住まい・勤務地: 知っている人は知っている
投稿日時: 2007-01-29 17:06
引用:

自分の中ではMarshalが必要なくなった意味があまりよくわかりません。
GetPrivateProfileStringAにしろ、GetPrivateProfileStringWにしろ、型の違いを調整するMarshalは必要な気がするのですが、、。


あまり詳しいことはわからないのですが、String型に対してMarshalAs〜を指定しないと
<MarshalAs(UnmanagedType.LPStr)>を指定したことになるようです。
(もしかしたら〜Aに対応するときはLPStrに〜Wに対応するときはLPWStrになるのかもしれないけど)
# 自分だったら明確化するためにも省略しないとおもう。

この指定はマーシャラでLPStrつまり CP932の文字列を受け取って、String型に入れるときに
Unicodeに変換するという動きになります。
ここで問題なのは、GetPrivateProfileStringAの戻り値なんですが、CP932のバイト数を
Unicodeの文字数に変換するということまでマーシャラはやってくれないので、
格納された文字列とGetPrivateProfileStringAの戻り値がずれているような結果になります。

StringBuilderを使わないでString型でやり取りして戻り値で切り出すということをやりたいのであれば、
GetPrivateProfileStringWを使い、<MarshalAs(UnmanagedType.LPWStr)>を指定します。
ここでGetPrivateProfileStringWの戻り値はGetPrivateProfileStringAと違って
Unicodeの文字数なので格納された文字列を切り出すことが可能になります。
(ここは対応づいている)
# GetPrivateProfileStringAの戻り値をどうしても使いたいのであれば、コード変換が起こらない型
# たとえばメモリを用意したIntPtr型で受けて、Byte配列に変換して戻り値で切り出して、
# EncodingクラスでUnicode変換させるてなことになるのかな?

ところで、StringBuilderの場合なぜ戻り値を見なくてもよいか?ということですが
おそらくToStringメソッドの内部で、文字列の終端(vbNullChar)が出現するまでを文字列とするように
なっているからではないでしょうか。
(つまり、SubString+ToStringを内部で行っているような感じ)

[ メッセージ編集済み 編集者: Blue 編集日時 2007-01-29 17:18 ]
KI
大ベテラン
会議室デビュー日: 2007/01/10
投稿数: 239
投稿日時: 2007-01-29 18:30
引用:

Blueさんの書き込み (2007-01-29 17:06) より:
StringBuilderを使わないでString型でやり取りして戻り値で切り出すということをやりたいのであれば、
GetPrivateProfileStringWを使い、<MarshalAs(UnmanagedType.LPWStr)>を指定します。
ここでGetPrivateProfileStringWの戻り値はGetPrivateProfileStringAと違って
Unicodeの文字数なので格納された文字列を切り出すことが可能になります。




MarshalAs指定するにせよしないにせよ、APIの関数に戻り値を受け取る文字列のバッファを渡すときは、
StringBuilderを使わないとダメだったと記憶しています。
Stringでも動作させることができるのでしょうか?
えんぴつ
常連さん
会議室デビュー日: 2006/12/27
投稿数: 23
投稿日時: 2007-01-29 20:02
KIさんの書き込みより
引用:
MarshalAs指定するにせよしないにせよ、APIの関数に戻り値を受け取る文字列のバッファを渡すときは、
StringBuilderを使わないとダメだったと記憶しています。
Stringでも動作させることができるのでしょうか?


GetPrivateProfileStringWの場合はStringBuilderを使用しなくても正常に動作しました。

Blueさんの書き込みより
引用:
格納された文字列とGetPrivateProfileStringAの戻り値がずれているような結果になります。
GetPrivateProfileStringWの戻り値はGetPrivateProfileStringAと違って
Unicodeの文字数なので格納された文字列を切り出すことが可能になります。


やはり、GetPrivateProfileStringWでStringBuilderを使用するのが一番使い勝手がいいですね。

みなさん、協力、指導ありがとうございました。
コードを記述しておきます。
---
'API関数
Public Declare Unicode Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringW" ( _
<MarshalAs(UnmanagedType.LPWStr)> ByVal IpApplicationName As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal IpKeyName As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal IpDefault As String, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal IpReturnedString As Text.StringBuilder, _
ByVal nSize As Integer, _
<MarshalAs(UnmanagedType.LPWStr)> ByVal IpFileName As String _
) As Integer
---
Dim intLength As Integer
Dim strReturnValue As New Text.StringBuilder(100)
intLength = GetPrivateProfileString("SESTEM", "ServerDataDir", Nothing,             strReturnValue, strReturnValue.Capacity, "inifile.ine")
strServerDataDir = strReturnValue.ToString
---

自分の中ではこれで完成ですが、まだおかしなところがあれば指摘してもらえるとありがたいです。


ちゃっぴ
ぬし
会議室デビュー日: 2004/12/10
投稿数: 873
投稿日時: 2007-01-29 21:00
関係ないことですが、9x 系の OS が完全に support 切れした現在 Win32 (この呼び方も適切じゃなくなるかな?) を呼び出す場合、基本的に Unicode 版を呼び出すべきだと思います。

9x をどうしても support しなければならない場合を除いて。

[追記]
あと、Windows で path を扱う場合にはここに一度目を通しておいたほうがいいと思う。

[8-1.] Windowsパス名の落とし穴
Naming a File
[/追記]

[ メッセージ編集済み 編集者: ちゃっぴ 編集日時 2007-01-29 21:08 ]
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2007-01-29 22:06
 VSS のキーワードを、実行ファイルから切り出そうと思ったのですが、C# で、
const string = "$ID:$";
とした文字列は、「5文字、$ID:$」と、格納されていますね。その為、「null が出てくるまで」という検索の仕方は、出来ませんでした。
 StringBuilder も、「何文字使用中」と、マークしていると思います(私は IL 覗いたりしていないから、違うかもよぉ〜)。Length を 0 にすると、ToString の結果も空文字列ですし。


> 円マーク をエスケープしているとはどのようなことでしょうか?
引用:

iniファイル内に入っているフォルダパス
C:¥¥¥¥図ファイル¥¥¥¥


と書かれているので、コード上に "C:¥¥図ファイル" と書いてあると思いました。C 言語系の言語では円マークは、例えば "¥n" は改行コードであるなど、特別な意味を持つため、円マークそれ自身を表すには "¥¥" としなければなりません。C 言語系の言語では、これで円マーク1つ分です。しかし、VB では円マークは円マークでしかなく、"¥" で円マーク1つ分です。この辺のことじゃないかなぁ、、、と、思いました。

 Path.Combine は、試されていたんですね。これは、"C:¥図ファイル" + "絵.tiff" としたときでも、"C:¥図ファイル¥絵.tiff" と連結してくれます。また、ディレクトリ区切り記号が円マーク(バックスラッシュ)以外になっても、コードの変更は必要がないというおまけ付き。
_________________
えんぴつ
常連さん
会議室デビュー日: 2006/12/27
投稿数: 23
投稿日時: 2007-01-30 09:17
ちゃっぴさんの書き込みより
引用:
あと、Windows で path を扱う場合にはここに一度目を通しておいたほうがいいと思う。


Cで書かれていますが意味は同じなので勉強になります。ありがとうございます。

引用:
コード上に "C:¥¥図ファイル" と書いてあると思いました。


すいませんでした。書き込みを半角の円マークで行っていたためにおかしなことになっていました。正しくは"C:¥図ファイル"です。半角の円マークはプレビューするとバックスラッシュになる上に、本文内では数が2倍になるんですね  (^^;)

スキルアップ/キャリアアップ(JOB@IT)