我在阅读具有不同编码的 IniFiles 时遇到问题。如果我阅读一个 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);
}
}
}
}
}
对前三个答案的反应:
你当然是对的。对于 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);
}
}
}
}
}