J'ai un problème lors de la lecture d'IniFiles avec différents encodages. Si je lis un fichier Unicode, GetPrivateProfileSectionNamesA semble trébucher sur la première ligne. ASCII ou ANSI fonctionne bien. J'ai écrit un petit programme pour illustrer mon problème. D'abord la sortie, puis le programme. Je ne me soucie pas vraiment de UTF7 et UTF32, mais ce que je ne comprends pas, c'est la partie UTF8. Dois-je utiliser une fonction différente pour lire Unicode IniFiles? Est-ce que je fais quelque chose de mal? quelqu'un L'espoir peut me aider, grâce Norbertkernel32.dll - GetPrivateProfileSectionNamesA
ce que je reçois:
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????????
programme:
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);
}
}
}
}
}
Réaction aux trois premières réponses:
Vous sont bien sûr bien. Je devrais utiliser GetPrivateProfileSectionNamesW pour les fichiers Unicode. J'ai inclus une méthode pour obtenir l'encodage de l'IniFile et utilisé A ou W en conséquence. Le problème reste le même. La fonction n'obtient pas la première section. Ci-dessous, voir le nouveau code uniquement pour UTF8.
ce que je reçois:
IniEntriesWithSectionInFirstLine
first section using System.Text.UTF8Encoding is SecondSection
programme:
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);
}
}
}
}
}
Vous avez bien sûr raison. Je devrais utiliser GetPrivateProfileSectionNamesW pour les fichiers Unicode. J'ai inclus une méthode pour obtenir l'encodage de l'IniFile et utilisé A ou W en conséquence. Le problème reste le même. La fonction n'obtient pas la première section. Voir les changements ci-dessus. –
Je suspecte toujours que la fonction API rencontre des problèmes pour traiter les marques d'ordre des octets au début du fichier. Essayez de ne pas en inclure dans votre éditeur de texte. Vous pouvez vérifier s'ils sont présents en ouvrant le fichier dans un éditeur hexadécimal. (Textpad peut ouvrir des fichiers texte en mode hexadécimal et vous permet de contrôler si des marques d'ordre d'octet sont incluses) – pipTheGeek