1

エンコーディングが異なる IniFile の読み取りに問題があります。Unicode ファイルを読み取ると、GetPrivateProfileSectionNamesA は最初の行でつまずくようです。ASCII または ANSI は問題なく動作します。私の問題を説明するために小さなプログラムを書きました。最初に出力、次にプログラム。UTF7 と UTF32 はあまり気にしませんが、得られないのは UTF8 の部分です。Unicode IniFiles を読み取るには、別の関数を使用する必要がありますか? 私は何か間違ったことをしていますか?誰かが私を助けてくれることを願っています、ノーバートに感謝します

私が得るもの:

IniEntriesWithSectionInFirstLine
first section using System.Text.ASCIIEncoding is FirstSectionInFirstLine
first section using System.Text.Latin1Encoding is FirstSectionInFirstLine
first section using System.Text.UTF7Encoding is
first section using System.Text.UTF8Encoding is SecondSection
first section using System.Text.UTF32Encoding is SecondSectio????????????

IniEntriesWithFirstLineEmpty
first section using System.Text.ASCIIEncoding is FirstSectionInSecondLine
first section using System.Text.Latin1Encoding is FirstSectionInSecondLine
first section using System.Text.UTF7Encoding is
first section using System.Text.UTF8Encoding is FirstSectionInSecondLine
first section using System.Text.UTF32Encoding is FirstSectionInSecondLin????????

プログラム:

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

namespace TestIniRead
{
    internal class Program
    {
        [DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileSectionNamesA")]
        private static extern int GetSectionNamesListA(
            byte[] lpszReturnBuffer,
            int nSize,
            string lpFileName);

        private static readonly string[] IniEntriesWithSectionInFirstLine = {
                                                            "[FirstSectionInFirstLine]",
                                                            "value=firsValue",
                                                            "",
                                                            "[SecondSection]",
                                                            "value=secondValue",
                                                            "",
                                                            "[ThirdSection]",
                                                            "value=secondValue",
                                                            ""
                                                        };
        private static readonly string[] IniEntriesWithFirstLineEmpty = {
                                                            "",
                                                            "[FirstSectionInSecondLine]",
                                                            "value=firsValue",
                                                            "",
                                                            "[SecondSection]",
                                                            "value=secondValue",
                                                            "",
                                                            "[ThirdSection]",
                                                            "value=secondValue",
                                                            ""
                                                        };

        private static void Main()
        {
            var fileInfo = new FileInfo("test.ini");
            Console.WriteLine("IniEntriesWithSectionInFirstLine");
            TestEncodings(fileInfo, IniEntriesWithSectionInFirstLine);
            Console.WriteLine("");
            Console.WriteLine("IniEntriesWithFirstLineEmpty");
            TestEncodings(fileInfo, IniEntriesWithFirstLineEmpty);
            Console.ReadLine();
        }

        private static void TestEncodings(FileInfo fileInfo, IEnumerable<string> iniEntries)
        {
            TestEncoding(fileInfo, iniEntries, Encoding.ASCII);
            TestEncoding(fileInfo, iniEntries, Encoding.GetEncoding("ISO-8859-1"));
            TestEncoding(fileInfo, iniEntries, Encoding.UTF7);
            TestEncoding(fileInfo, iniEntries, Encoding.UTF8);
            TestEncoding(fileInfo, iniEntries, Encoding.UTF32);
        }

        private static void TestEncoding(FileInfo fileInfo, IEnumerable<string> iniEntries, Encoding encoding)
        {
            CreateIniFile(fileInfo, iniEntries, encoding);
            if (fileInfo.Exists)
            {
                var buffer = new byte[fileInfo.Length];
                GetSectionNamesListA(buffer, (int) fileInfo.Length, fileInfo.FullName);
                String s = encoding.GetString(buffer);
                String[] names = s.Split('\0');

                Console.WriteLine("first section using {0} is {1}", encoding, names[0]);
            }
        }

        private static void CreateIniFile(FileSystemInfo fileInfo, IEnumerable<string> iniEntries, Encoding encoding)
        {
            using (var sw = new StreamWriter(File.Open(fileInfo.FullName, FileMode.Create), encoding))
            {
                foreach (string line in iniEntries)
                {
                    sw.WriteLine(line);
                }
            }
        }
    }
}

最初の 3 つの回答に対する反応:

あなたはもちろん正しいです。Unicode ファイルには GetPrivateProfileSectionNamesW を使用する必要があります。IniFile のエンコーディングを取得するメソッドを含め、それに応じて A または W を使用しました。問題は同じままです。関数は最初のセクションを取得しません。以下は、UTF8 のみの新しいコードです。

私が得るもの:

IniEntriesWithSectionInFirstLine
first section using System.Text.UTF8Encoding is SecondSection

プログラム:

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

namespace TestIniRead
{
    internal class Program
    {
        [DllImport("kernel32.dll", EntryPoint = "GetPrivateProfileSectionNamesA")]
        private static extern int GetSectionNamesListA(
                byte[] lpszReturnBuffer,
                int nSize,
                string lpFileName);

        [DllImport("kernel32", EntryPoint = "GetPrivateProfileSectionNamesW", CharSet = CharSet.Unicode)]
        private static extern int GetSectionNames
            (
            [MarshalAs(UnmanagedType.LPWStr)] string szBuffer,
            int nlen,
            string filename
            );

        private static readonly string[] IniEntriesWithSectionInFirstLine = {
                                                                "[FirstSectionInFirstLine]",
                                                                "value=firsValue",
                                                                "",
                                                                "[SecondSection]",
                                                                "value=secondValue",
                                                                "",
                                                                "[ThirdSection]",
                                                                "value=secondValue",
                                                                ""
                                                        };

        private static void Main()
        {
            var fileInfo = new FileInfo("test.ini");
            Console.WriteLine("IniEntriesWithSectionInFirstLine");
            TestEncodings(fileInfo, IniEntriesWithSectionInFirstLine);
            Console.WriteLine("");
            Console.ReadLine();
        }

        private static void TestEncodings(FileInfo fileInfo, IEnumerable<string> iniEntries)
        {
            TestEncoding(fileInfo, iniEntries, Encoding.UTF8);
        }

        private static readonly char[] separator = { '\0' };

        private static void TestEncoding(FileInfo fileInfo, IEnumerable<string> iniEntries, Encoding encoding)
        {
            CreateIniFile(fileInfo, iniEntries, encoding);
            if (fileInfo.Exists)
            {
                int len = (int)fileInfo.Length;
                var buffer = new string('\0', len);
                int nlen = GetSectionNames(buffer, len, fileInfo.FullName);
                if (nlen <= 0)
                {
                    Environment.Exit(nlen);
                }

                String[] names = buffer.Substring(0, nlen).Split(separator);
                Console.WriteLine("first section using {0} is {1}", encoding, names[0]);
            }
        }

        private static void CreateIniFile
            (
            FileSystemInfo fileInfo, 
            IEnumerable<string> iniEntries, 
            Encoding encoding)
        {
            using (var sw = new StreamWriter(File.Open(fileInfo.FullName, FileMode.Create), encoding))
            {
                foreach (string line in iniEntries)
                {
                    sw.WriteLine(line);
                }
            }
        }
    }
}
4

3 に答える 3

1

Unicodeファイルの最初の数バイトには、バイト順マークを含めることができます。使用しているテキストエディタが何であれ、Unicodeファイルを保存し、バイト順マークを含めます。これらは、API関数を混乱させます。

代わりにGetPrivateProfileSectionNamesWを呼び出してみましたか?(AはAPI機能のANSIバージョンを示し、ワイドのWはUnicodeバージョンを示します)

または、バイト順マークなしでファイルを保存するようにテキストエディタを設定することもできます。

于 2009-07-22T11:29:37.993 に答える
0
  1. 試しましたGetPrivateProfileSectionNamesWか?

  2. iniファイルがASCIIで保存されていることを確認できますか?MSDNドキュメントから:

    この機能は、16ビットのWindowsベースのアプリケーションとの互換性のためにのみ提供されています。

  3. .NET設定ファイルはINIファイルよりもはるかに優れています。レガシーシステムと相互運用するために何かを書いているのでなければ、新しい方法を使用することを強くお勧めします。

于 2009-07-22T11:30:50.567 に答える
0

私は実際に同じことを見ましたが、あなたが持っているテストを行わずに (ini ファイルの先頭に空の行があることを確認しました)。

私は元々、.NET Framework の IO 関数を使用して inifile を作成していましたが、旧式の C++ で作成された別のプログラムがそれを読み取っていたときに、最初の行が欠落していました。最終的に、.NET コードを ISO-8859-1 エンコーディングを使用するように変更しました。これはおそらく、Unicode が登場する前の基本的なテキスト ファイルの書き込み方法に最も近いものです....NET のデフォルトのエンコーディングは UTF8 です。多くの場合、Encodings.ASCII はおそらく問題ありませんが、これには最初の 127 文字しか含まれていません。

ほとんどの場合、Encodings.Default を使用するとよいと思います。これは、実行中の Windows インスタンスで使用されるデフォルトのコードページを表し、私の場合 (そしておそらくあなたの場合) は ISO-8859-1 エンコーディングにマップされるためです。世界の他の地域では、ISO-8859 標準の他のサブセットにマップされます。

于 2009-07-22T11:34:24.647 に答える