C# kernel32.dll-GetPrivateProfileSectionNamesA

C# kernel32.dll-GetPrivateProfileSectionNamesA,c#,unicode,ini,C#,Unicode,Ini,我在读取不同编码的文件时遇到问题。如果我读了一个Unicode文件,GetPrivateProfileSectionNamesA似乎在第一行上绊倒了。ASCII或ANSI工作正常。 我写了一个小程序来说明我的问题。首先是输出,然后是程序。 我并不真正关心UTF7和UTF32,但我没有得到的是UTF8部分。我必须使用不同的函数来读取Unicode文件吗?我做错什么了吗? 希望有人能帮助我, 谢谢 诺伯特 我得到的是: IniEntriesWithSectionInFirstLine first s

我在读取不同编码的文件时遇到问题。如果我读了一个Unicode文件,GetPrivateProfileSectionNamesA似乎在第一行上绊倒了。ASCII或ANSI工作正常。 我写了一个小程序来说明我的问题。首先是输出,然后是程序。 我并不真正关心UTF7和UTF32,但我没有得到的是UTF8部分。我必须使用不同的函数来读取Unicode文件吗?我做错什么了吗? 希望有人能帮助我, 谢谢 诺伯特

我得到的是:

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????????
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);

        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);
                }
            }
        }
    }
}
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);
                }
            }
        }
    }
}
该方案:

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);
                }
            }
        }
    }
}
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);
                }
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用System.Runtime.InteropServices;
使用系统文本;
名称空间测试头
{
内部课程计划
{
[DllImport(“kernel32.dll”,EntryPoint=“GetPrivateProfileSectionNamesA”)]
私有静态外部int GetSectionNamesListA(
字节[]lpszReturnBuffer,
内化,
字符串(文件名);
[DllImport(“kernel32”,EntryPoint=“GetPrivateProfileSectionNamesW”,CharSet=CharSet.Unicode)]
私有静态外部int GetSectionNames
(
[Marshallas(UnmanagedType.LPWStr)]字符串缓冲区,
英伦,
字符串文件名
);
私有静态只读字符串[]IniEntriesWithSectionInFirstLine={
“[FirstSectionInFirstLine]”,
“value=firsValue”,
"",
“[第二节]”,
“value=secondValue”,
"",
“[第三节]”,
“value=secondValue”,
""
};
私有静态void Main()
{
var fileInfo=newfileinfo(“test.ini”);
Console.WriteLine(“InEntriesWithSectionInfirstLine”);
测试代码(fileInfo,inEntries和sectioninfirstline);
控制台。写线(“”);
Console.ReadLine();
}
私有静态void测试编码(FileInfo FileInfo,IEnumerable)
{
TestEncoding(fileInfo、ini条目、Encoding.UTF8);
}
私有静态只读字符[]分隔符={'\0'};
私有静态void测试编码(FileInfo FileInfo,IEnumerable INIENTERIERS,编码)
{
CreateIniFile(文件信息、iniEntries、编码);
如果(fileInfo.Exists)
{
int len=(int)fileInfo.Length;
var buffer=新字符串('\0',len);
int nlen=GetSectionNames(缓冲区、len、fileInfo.FullName);

如果(nlenunicode文件的前几个字节可以包含字节顺序标记。您使用的任何文本编辑器都会保存unicode文件并包含字节顺序标记。这会混淆API函数

您是否尝试调用GetPrivateProfileSectionNamesW?(A表示API函数的ANSI版本,W表示宽表示Unicode版本)


或者,您可以将文本编辑器设置为不带字节顺序标记地保存文件。

unicode文件的前几个字节可以包含字节顺序标记。您使用的任何文本编辑器都会保存unicode文件并包含字节顺序标记。这会混淆API函数

您是否尝试调用GetPrivateProfileSectionNamesW?(A表示API函数的ANSI版本,W表示宽表示Unicode版本)

或者,您可以将文本编辑器设置为不带字节顺序标记地保存文件

  • 您是否尝试过
    GetPrivateProfileSectionNamesW

  • 能否确保ini文件以ASCII格式存储?请参阅MSDN文档:

    注意此功能仅用于与基于Windows的16位应用程序兼容

  • 与INI文件相比,这些文件的性能要优越得多。如果您没有编写与遗留系统互操作的内容,我强烈建议您使用新的方式

  • 您是否尝试过
    GetPrivateProfileSectionNamesW

  • 能否确保ini文件以ASCII格式存储?请参阅MSDN文档:

    注意此功能仅用于与基于Windows的16位应用程序兼容

  • 与INI文件相比,这些文件的性能要优越得多。如果您没有编写与遗留系统互操作的内容,我强烈建议您使用新的方式


  • 实际上,我也看到了同样的情况,但没有进行测试(我只是确保在ini文件的开头有一个空行)

    我最初是使用.NET框架中的IO函数编写InFILE,而当另一个程序在OLDFrameC++中读取时,第一行就丢失了。我最终将我的.NET代码改为使用ISO-859-1编码,这可能是Unicode之前的基本文本文件的编写方式。NET中的t编码是UTF8。 在许多情况下,Encodings.ASCII可能是可以的,但它只包括前127个字符

    在大多数情况下,我认为Encodings.Default会很好地使用,因为它表示runnning windows实例上使用的默认代码页,在我的情况下(可能在您的情况下),它映射到ISO-8859-1编码