C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: UnicodeのINIファイルの読み込みについて


(過去ログ 27 を表示中)

[トピック内 9 記事 (1 - 9 表示)]  << 0 >>

■12911 / inTopicNo.1)  UnicodeのINIファイルの読み込みについて
  
□投稿者/ Nao (1回)-(2008/01/20(Sun) 22:04:58)

分類:[C#] 

2008/01/20(Sun) 22:07:23 編集(投稿者)
2008/01/20(Sun) 22:07:14 編集(投稿者)

C#にて、Unicodeで記述されたINIファイルから、値を取得したいと思っております。
以下では、SJISで記述されたINIファイルを指定した場合では正常に動作するのですが、
Unicodeで記述されたINIファイルでは、値が取得できません。
Unicodeで記述されたINIファイルから値を取得する方法を、ご教授ください。

class IniFileHandler
{
private const int BUFF_LEN = 256; // 256文字

[DllImport("Kernel32.dll")]
public static extern uint GetPrivateProfileString(
string lpApplicationName,
string lpKeyName,
string lpDefault,
System.Text.StringBuilder StringBuilder,
uint nSize,
string lpFileName
);

// INIファイルから指定したキーに対する項目値を取得する。
public static string GetIniString(string lpszSection, string lpszEntry, string lpszDefault, string m_strIniFileName)
{
StringBuilder sb = new StringBuilder(BUFF_LEN);
uint ret = GetPrivateProfileString(lpszSection, lpszEntry,
lpszDefault, sb, Convert.ToUInt32(sb.Capacity), m_strIniFileName);
return sb.ToString();
}
}
引用返信 編集キー/
■12912 / inTopicNo.2)  Re[1]: UnicodeのINIファイルの読み込みについて
□投稿者/ 魔界の仮面弁士 (582回)-(2008/01/21(Mon) 00:04:36)
No12911 (Nao さん) に返信
> C#にて、Unicodeで記述されたINIファイルから、値を取得したいと思っております。
その場合、ファイルは「UTF-16」である必要がありますが、その点は大丈夫でしょうか?

> [DllImport("Kernel32.dll")]
属性指定の部分を、
  [DllImport("Kernel32.dll", CharSet=CharSet.Unicode, EntryPoint="GetPrivateProfileStringW")]
に変更してみてください。

引用返信 編集キー/
■12913 / inTopicNo.3)  Re[2]: UnicodeのINIファイルの読み込みについて
□投稿者/ Blue (358回)-(2008/01/21(Mon) 01:16:03)
2008/01/21(Mon) 01:18:56 編集(投稿者)

>[DllImport("Kernel32.dll", CharSet=CharSet.Unicode, EntryPoint="GetPrivateProfileStringW")]
GetPrivateProfileStringWを使ってもUnicodeのINIファイルを読めるわけではないのでは?
(ファイル系の〜Wは単に取得したもののコードをなんにするかで、取得先のコードを指定するものではない。)

というかINIファイルって、Unicodeのファイルも該当するんでしたっけ?
引用返信 編集キー/
■12915 / inTopicNo.4)  Re[3]: UnicodeのINIファイルの読み込みについて
□投稿者/ 魔界の仮面弁士 (583回)-(2008/01/21(Mon) 01:23:22)
No12913 (Blue さん) に返信
> (〜Wは単に取得したもののコードをなんにするかで、取得先のコードを指定するものではない。)
本題は、Auto モードではなく、Unicode モードにする必要がある、という点かな。

> というかINIファイルって、Unicodのファイルも該当するんでしたっけ?
Win98 は駄目だと思いますが、NT 系なら対応していますよ。UTF-16 限定ですけれども。

実際、Shift_JIS に無い文字、たとえば中文の「ニイハオ」(2文字)なども取得できましたし。
引用返信 編集キー/
■12916 / inTopicNo.5)  Re[4]: UnicodeのINIファイルの読み込みについて
□投稿者/ Blue (359回)-(2008/01/21(Mon) 01:35:15)
2008/01/21(Mon) 01:41:19 編集(投稿者)
2008/01/21(Mon) 01:38:56 編集(投稿者)
2008/01/21(Mon) 01:35:49 編集(投稿者)

<削除>
>実際、Shift_JIS に無い文字、たとえば中文の「ニイハオ」(2文字)なども取得できましたし。
これはUTF-8コードのものということでしょうか?


ちょっと疑問なのですが、
GetPrivateProfileStringWで2バイト文字でShift_JISにもUTF-8にもある文字を読んだときはどうなるのでしょうか?

UTF-8の場合GetPrivateProfileStringAでByte型で取得して、自前でEncodingクラスでUTF-8で変換しないと
取得できるとは思わないのですが、なにかおおきな勘違いをしていますかね?
</削除>

追記

もしかして、NT系の場合、BOMを見てコードを変換しているのか、、

ってか、すみませんよくみたらUTF-8ではなく、UTF-16は可能ということでしたね。orz
引用返信 編集キー/
■12917 / inTopicNo.6)  Re[5]: UnicodeのINIファイルの読み込みについて
□投稿者/ 魔界の仮面弁士 (584回)-(2008/01/21(Mon) 01:47:32)
2008/01/21(Mon) 01:54:15 編集(投稿者)
No12916 (Blue さん) に返信
> >実際、Shift_JIS に無い文字、たとえば中文の「ニイハオ」(2文字)なども取得できましたし。
> これはUTF-8コードのものということでしょうか?
ですから、UTF-16 だと書いているでは無いですか。(^^; <No12912,No12915


> GetPrivateProfileStringWで2バイト文字でShift_JISにもUTF-8にもある文字を読んだときはどうなるのでしょうか?
「2バイト文字」というのは、具体的には何を意味していますか?

たとえば、「α」の文字は、Shift_JIS でも UTF-8 でも UTF-16 でも『2 バイト』ですが、
「A」の文字は、Shift_JIS や UTF-8 だと『1 バイト』、UTF-16 では『2 バイト』で、
「阿」の文字は、Shift_JIS や UTF-16 だと『2 バイト』、UTF-8 では『3 バイト』ですね。


> UTF-8の場合GetPrivateProfileStringAでByte型で取得して、自前でEncodingクラスでUTF-8で変換しないと
> 取得できるとは思わないのですが、なにかおおきな勘違いをしていますかね?
ここで「UTF-8」が出てきた理由がわかりませんが、Windows は UTF-8 形式の ini ファイルを
サポートしていなかったはずです。(元質問者の方も、UTF-8 という言葉は使っていませんよね?)


とりあえずサンプル。


using System;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;

class Sample
{
    static void Main(string[] args)
    {
        string fileName = @"C:\sample.ini";
        using (StreamWriter sw = new StreamWriter(fileName, false, Encoding.Unicode))
        {
            sw.WriteLine("[SAMPLE]");
            sw.WriteLine("中文=\u4f60好");
            sw.WriteLine("日本語=こんにちは");
            sw.Close();
        }

        string a = IniFile.GetIniStringW("SAMPLE", "中文", "HELLO", fileName);
        string b = IniFile.GetIniString ("SAMPLE", "中文", "HELLO", fileName);
        string c = IniFile.GetIniStringW("SAMPLE", "日本語", "HELLO", fileName);
        string d = IniFile.GetIniString ("SAMPLE", "日本語", "HELLO", fileName);

    }
}

class IniFile
{
    [DllImport("Kernel32.dll")]
    private static extern uint GetPrivateProfileString(
        string section,
        string key,
        string defaultText,
        StringBuilder buffer,
        uint size,
        string file
    );

    [DllImport("Kernel32.dll", CharSet=CharSet.Unicode)]
    private static extern uint GetPrivateProfileStringW(
        string section,
        string key,
        string defaultText,
        StringBuilder buffer,
        uint size,
        string file
    );

    public static string GetIniString(string section, string key, string defaultText, string fileName)
    {
        StringBuilder sb = new StringBuilder(300);
        uint ret = GetPrivateProfileString(section, key, defaultText, sb, 300U, fileName);
        return sb.ToString();
    }

    public static string GetIniStringW(string section, string key, string defaultText, string fileName)
    {
        StringBuilder sb = new StringBuilder(300);
        uint ret = GetPrivateProfileStringW(section, key, defaultText, sb, 300U, fileName);
        return sb.ToString();
    }
}


> ■No12916
> 2008/01/21(Mon) 01:41:19 編集(投稿者)
> 2008/01/21(Mon) 01:38:56 編集(投稿者)
> 2008/01/21(Mon) 01:35:49 編集(投稿者)
> <削除>
# ありゃ、入れ違っちゃったか。投稿前にリロードしておけばよかったかな…。

引用返信 編集キー/
■12918 / inTopicNo.7)  Re[6]: UnicodeのINIファイルの読み込みについて
□投稿者/ Blue (360回)-(2008/01/21(Mon) 02:01:35)
2008/01/21(Mon) 02:35:55 編集(投稿者)

ちょっと疑問なんですが、まったくファイルがない時にUnicodeのiniファイルを作るときはどうするんでしょうかね?


試してみた結果

・ファイルなし
→WritePrivateProfileStringWでUnicodeにしかない文字を書いてもShift_JISのファイルになった。

・WritePrivateProfileStringWの前に新規ファイルを作り、手動でBOMをつけて保存
→WritePrivateProfileStringWでもWritePrivateProfileStringAでもUTF-16のファイルになった。

引用返信 編集キー/
■12922 / inTopicNo.8)  Re[4]: UnicodeのINIファイルの読み込みについて
□投稿者/ 魔界の仮面弁士 (585回)-(2008/01/21(Mon) 02:38:08)
No12915 (魔界の仮面弁士) に返信
>>(〜Wは単に取得したもののコードをなんにするかで、取得先のコードを指定するものではない。)
> 本題は、Auto モードではなく、Unicode モードにする必要がある、という点かな。

あぁ、勘違いしてたかも。実際には Auto 指定でも問題無いですね。
Charset 省略時は Auto ではなく、Ansi 扱いになっているようで。
http://msdn2.microsoft.com/ja-jp/library/system.runtime.interopservices.charset%28VS.80%29.aspx
http://msdn2.microsoft.com/ja-jp/library/system.runtime.interopservices.dllimportattribute.charset.aspx

VB の Declare にしろ、VB/C# の DllImport にしろ、この場合は Auto 指定を付けておけば良いのかな。
http://www5b.biglobe.ne.jp/~yone-ken/VBNET/Reference/ref2_GetPrivateProfileString.html
引用返信 編集キー/
■12923 / inTopicNo.9)  Re[7]: UnicodeのINIファイルの読み込みについて
□投稿者/ 魔界の仮面弁士 (586回)-(2008/01/21(Mon) 03:37:07)
No12918 (Blue さん) に返信
> ちょっと疑問なんですが、まったくファイルがない時にUnicodeのiniファイルを作るときはどうするんでしょうかね?
> 試してみた結果

物理ファイルの代わりに、レジストリ マッピングを試してみました。
CharSet.Auto の指定があれば、Unicode データでも問題なく読み書きできるようです。


static void Main(string[] args)
{
    // マッピング先のレジストリ エントリ
    using (RegistryKey Orator = Registry.CurrentUser.CreateSubKey(@"Software\Orator"))
    using (RegistryKey Hoge = Orator.CreateSubKey("Hoge"))
    {
    }

    // Hoge.ini をマッピング
    using (RegistryKey IniFileMapping = Registry.LocalMachine.OpenSubKey(
          @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping", true))
    using (RegistryKey HogeIni = IniFileMapping.CreateSubKey("Hoge.ini"))
    {
        HogeIni.SetValue(null, @"USR:Software\Orator\Hoge");
    }

    // ★ WritePrivateProfileString API による書きこみ ★
    WritePrivateProfileString("entry", "key", "立法メートル「\u33a5」", "Hoge.ini");
    WritePrivateProfileString(null, null, null, "Hoge.ini");

    // GetPrivateProfileString API による読込
    string result1 = null;
    {
        StringBuilder sb = new StringBuilder(100);
        uint ret = GetPrivateProfileString("entry", "key", "test", sb, sb.Capacity, "Hoge.ini");
        result1 = sb.ToString();
    }

    // レジストリからの読み込み
    string result2 = null;
    using (RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\Orator\Hoge\entry"))
    {
        result2 = (string)key.GetValue("key");
    }

    Console.WriteLine(result1 == result2);
}

[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool WritePrivateProfileString(
    string section,
    string key,
    string newText,
    string file
);

[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
private static extern uint GetPrivateProfileString(
    string section,
    string key,
    string defaultText,
    StringBuilder buffer,
    int size,
    string file
);

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -