RemObjects ma bibliotekę Delphi Prism o nazwie ShineOn, która dostarcza podobną klasę plików INI. Ale musisz mieć Delphi Prism, aby skompilować go dla .NET ze źródła, ponieważ nie jest jeszcze dostępny skompilowany zestaw. code.remobjects.com/p/shineon
Lex Li
1
Mam ten sam problem i stworzyłem własną bibliotekę do analizowania plików ini: github.com/rickyah/ini-parser Mam nadzieję, że to pomaga
Twórcy frameworka .NET chcą, abyś używał plików konfiguracyjnych opartych na XML, a nie plików INI. Więc nie, nie ma wbudowanego mechanizmu ich odczytu.
Chociaż prawdą jest, że pliki konfiguracyjne XML są właściwą drogą, nadal nie jest to odpowiedź na pytanie lub jest to VLQ tylko dla łącza.
Danny Beckett
6
@aloneguid Twierdziłbym, że duży zestaw dostępnych funkcji faktycznie przyczynił się do tego, że pliki konfiguracyjne .NET stały się dziwnymi behemotami z dużą ilością magii. Stały się „kodem w pliku konfiguracyjnym”, co prowadzi do dużej złożoności, dziwnych zachowań i utrudnia zarządzanie konfiguracją. (Patrzę na ciebie, „dostawców” bazy danych i parametry połączenia.) Pliki INI są więc również ogólnie lepsze do edycji nie ręcznej.
jpmc26
1
lubię starą metodę (P / Inovke) i możesz używać Unicode ze starą metodą, taką jak: File.WriteAllBytes (ścieżka, nowy bajt [] {0xFF, 0xFE});
sailfish009
2
Dobry pakiet, ale może być lepszy. Nie można całkowicie przeanalizować wartości zawierającej „=” lub „\ n”
Ahmad Behjati,
211
Przedmowa
Najpierw przeczytaj ten post na blogu MSDN na temat ograniczeń plików INI . Jeśli odpowiada Twoim potrzebom, czytaj dalej.
Jest to zwięzłe wdrożenie, które napisałem przy użyciu oryginalnego P / Invoke systemu Windows, więc jest obsługiwane przez wszystkie wersje systemu Windows z zainstalowanym programem .NET (tj. Windows 98 - Windows 10). Niniejszym udostępniam go w domenie publicznej - możesz swobodnie korzystać z niego w celach komercyjnych bez podawania źródła.
Mała klasa
Dodaj nową klasę IniFile.csdo swojego projektu:
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;// Change this to match your program's normal namespace
namespace MyProg{classIniFile// revision 11{stringPath;string EXE =Assembly.GetExecutingAssembly().GetName().Name;[DllImport("kernel32",CharSet=CharSet.Unicode)]staticexternlongWritePrivateProfileString(stringSection,stringKey,stringValue,stringFilePath);[DllImport("kernel32",CharSet=CharSet.Unicode)]staticexternintGetPrivateProfileString(stringSection,stringKey,stringDefault,StringBuilderRetVal,intSize,stringFilePath);publicIniFile(stringIniPath=null){Path=newFileInfo(IniPath?? EXE +".ini").FullName;}publicstringRead(stringKey,stringSection=null){varRetVal=newStringBuilder(255);GetPrivateProfileString(Section?? EXE,Key,"",RetVal,255,Path);returnRetVal.ToString();}publicvoidWrite(stringKey,stringValue,stringSection=null){WritePrivateProfileString(Section?? EXE,Key,Value,Path);}publicvoidDeleteKey(stringKey,stringSection=null){Write(Key,null,Section?? EXE);}publicvoidDeleteSection(stringSection=null){Write(null,null,Section?? EXE);}publicboolKeyExists(stringKey,stringSection=null){returnRead(Key,Section).Length>0;}}}
Jak tego użyć
Otwórz plik INI na jeden z 3 następujących sposobów:
// Creates or loads an INI file in the same directory as your executable// named EXE.ini (where EXE is the name of your executable)varMyIni=newIniFile();// Or specify a specific name in the current dirvarMyIni=newIniFile("Settings.ini");// Or specify a specific name in a specific dirvarMyIni=newIniFile(@"C:\Settings.ini");
Trochę się spóźniam, ale brakuje mi GetSections()metody.
stil
2
Być może bardziej tradycyjnym ustawieniem domyślnym byłyby pliki .ini dla aplikacji (nie dla zestawu) Path.GetFullPath(IniPath ?? Path.ChangeExtension(Application.ExecutablePath, ".ini")).
Eugene Ryabtsev
3
Naprawdę świetnie ! Umieścić to na github?
Emrys Myrooin
2
@ Danny Beckett, ładnie zrobione. Jest to prawie dokładnie to samo, co używane przez ostatnie lata .Net. Ulepszony ze starego kodu lata temu.
Damian
10
Teraz stary i, o ile szanuję Raymonda Chena, wiele ograniczeń w tym artykule dotyczyło ograniczeń konkretnej biblioteki INI w systemie Windows, a nie samego formatu INI. Inne, takie jak uprawnienia granularne, można łatwo ominąć za pomocą wielu plików. Urzędnik , zmodernizowana biblioteka INI byłyby najbardziej mile widziane, nawet dzisiaj.
Autor stworzył klasę C # „Ini”, która udostępnia dwie funkcje z KERNEL32.dll. Te funkcje to: WritePrivateProfileStringi GetPrivateProfileString. Potrzebne będą dwie przestrzenie nazw: System.Runtime.InteropServicesi System.Text.
Kroki korzystania z klasy Ini
W definicji przestrzeni nazw projektu dodaj
using INI;
Utwórz taki plik INIF
INIFile ini =newINIFile("C:\\test.ini");
Służy IniWriteValuedo zapisywania nowej wartości do określonego klucza w sekcji lub IniReadValuedo odczytu wartości z klucza w określonej sekcji.
Przez jakiś czas korzystałem z tego podejścia, ale ulepszenia zabezpieczeń, począwszy od Win7, prawie dla mnie to zabiły. Nadal możesz używać tego podejścia, ale będziesz przechowywać .ini w ProgramData i tam będzie zapisywać / zapisywać aplikację.
Jess,
Nie zapisuj plików ini konfiguracji aplikacji w ProgramData. Nie należą one ani do Rejestru, ani do ProgramData. Pliki konfiguracyjne powinny znajdować się w folderach LocalApplicationData.
using System;
using System.IO;
using System.Collections;publicclassIniParser{privateHashtable keyPairs =newHashtable();privateString iniFilePath;privatestructSectionPair{publicStringSection;publicStringKey;}/// <summary>/// Opens the INI file at the given path and enumerates the values in the IniParser./// </summary>/// <param name="iniPath">Full path to INI file.</param>publicIniParser(String iniPath){TextReader iniFile =null;String strLine =null;String currentRoot =null;String[] keyPair =null;
iniFilePath = iniPath;if(File.Exists(iniPath)){try{
iniFile =newStreamReader(iniPath);
strLine = iniFile.ReadLine();while(strLine !=null){
strLine = strLine.Trim().ToUpper();if(strLine !=""){if(strLine.StartsWith("[")&& strLine.EndsWith("]")){
currentRoot = strLine.Substring(1, strLine.Length-2);}else{
keyPair = strLine.Split(newchar[]{'='},2);SectionPair sectionPair;Stringvalue=null;if(currentRoot ==null)
currentRoot ="ROOT";
sectionPair.Section= currentRoot;
sectionPair.Key= keyPair[0];if(keyPair.Length>1)value= keyPair[1];
keyPairs.Add(sectionPair,value);}}
strLine = iniFile.ReadLine();}}catch(Exception ex){throw ex;}finally{if(iniFile !=null)
iniFile.Close();}}elsethrownewFileNotFoundException("Unable to locate "+ iniPath);}/// <summary>/// Returns the value for the given section, key pair./// </summary>/// <param name="sectionName">Section name.</param>/// <param name="settingName">Key name.</param>publicStringGetSetting(String sectionName,String settingName){SectionPair sectionPair;
sectionPair.Section= sectionName.ToUpper();
sectionPair.Key= settingName.ToUpper();return(String)keyPairs[sectionPair];}/// <summary>/// Enumerates all lines for given section./// </summary>/// <param name="sectionName">Section to enum.</param>publicString[]EnumSection(String sectionName){ArrayList tmpArray =newArrayList();foreach(SectionPair pair in keyPairs.Keys){if(pair.Section== sectionName.ToUpper())
tmpArray.Add(pair.Key);}return(String[])tmpArray.ToArray(typeof(String));}/// <summary>/// Adds or replaces a setting to the table to be saved./// </summary>/// <param name="sectionName">Section to add under.</param>/// <param name="settingName">Key name to add.</param>/// <param name="settingValue">Value of key.</param>publicvoidAddSetting(String sectionName,String settingName,String settingValue){SectionPair sectionPair;
sectionPair.Section= sectionName.ToUpper();
sectionPair.Key= settingName.ToUpper();if(keyPairs.ContainsKey(sectionPair))
keyPairs.Remove(sectionPair);
keyPairs.Add(sectionPair, settingValue);}/// <summary>/// Adds or replaces a setting to the table to be saved with a null value./// </summary>/// <param name="sectionName">Section to add under.</param>/// <param name="settingName">Key name to add.</param>publicvoidAddSetting(String sectionName,String settingName){AddSetting(sectionName, settingName,null);}/// <summary>/// Remove a setting./// </summary>/// <param name="sectionName">Section to add under.</param>/// <param name="settingName">Key name to add.</param>publicvoidDeleteSetting(String sectionName,String settingName){SectionPair sectionPair;
sectionPair.Section= sectionName.ToUpper();
sectionPair.Key= settingName.ToUpper();if(keyPairs.ContainsKey(sectionPair))
keyPairs.Remove(sectionPair);}/// <summary>/// Save settings to new file./// </summary>/// <param name="newFilePath">New file path.</param>publicvoidSaveSettings(String newFilePath){ArrayList sections =newArrayList();String tmpValue ="";String strToSave ="";foreach(SectionPair sectionPair in keyPairs.Keys){if(!sections.Contains(sectionPair.Section))
sections.Add(sectionPair.Section);}foreach(String section in sections){
strToSave +=("["+ section +"]\r\n");foreach(SectionPair sectionPair in keyPairs.Keys){if(sectionPair.Section== section){
tmpValue =(String)keyPairs[sectionPair];if(tmpValue !=null)
tmpValue ="="+ tmpValue;
strToSave +=(sectionPair.Key+ tmpValue +"\r\n");}}
strToSave +="\r\n";}try{TextWriter tw =newStreamWriter(newFilePath);
tw.Write(strToSave);
tw.Close();}catch(Exception ex){throw ex;}}/// <summary>/// Save settings back to ini file./// </summary>publicvoidSaveSettings(){SaveSettings(iniFilePath);}}
+1 do przesunięcia powyżej downvote. Na co tak naprawdę narzekasz? Powiedział, że ZNALEZIŁ. Czy zlekceważysz go za to, że nie znalazł takiego z typowymi akcesoriami i narzędziem do budowania ciągów?
Tormod
1
@Tormod: Chciałbym głosować za komentarzem. To forum techniczne, kiedy głosujemy na rozwiązania, a nie (oczywiście pozytywnie). Gdyby rozwiązanie opublikowane przez samego Knutha miało wady, należałoby - i należy - wskazać. Nie ma znaczenia, czy rozwiązanie zostało znalezione, czy napisane przez plakat.
23
7
Myślę, że rozszerzasz definicję „wady”. Jeśli rozwiązanie nie podkreśla twoich wrażliwości, po prostu nie głosuj pozytywnie. Właśnie zostawiłem notatkę z informacją, że już zlekceważyłem jego opinię, aby pozostali 7 facetów, którzy głosowali mój komentarz, nie zrobiliby tego sami.
Tormod
21
Kod w odpowiedzi joerage jest inspirujący.
Niestety zmienia obudowę znaków klawiszy i nie obsługuje komentarzy. Napisałem więc coś, co powinno być wystarczająco solidne, aby odczytać (tylko) bardzo brudne pliki INI i pozwala odzyskać klucze takimi, jakie są.
Korzysta z LINQ, zagnieżdżonego słownika ciągów bez rozróżniania wielkości liter, do przechowywania sekcji, kluczy i wartości oraz odczytywania pliku za jednym razem.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;classIniReader{Dictionary<string,Dictionary<string,string>> ini =newDictionary<string,Dictionary<string,string>>(StringComparer.InvariantCultureIgnoreCase);publicIniReader(string file){var txt =File.ReadAllText(file);Dictionary<string,string> currentSection =newDictionary<string,string>(StringComparer.InvariantCultureIgnoreCase);
ini[""]= currentSection;foreach(var line in txt.Split(new[]{"\n"},StringSplitOptions.RemoveEmptyEntries).Where(t =>!string.IsNullOrWhiteSpace(t)).Select(t => t.Trim())){if(line.StartsWith(";"))continue;if(line.StartsWith("[")&& line.EndsWith("]")){
currentSection =newDictionary<string,string>(StringComparer.InvariantCultureIgnoreCase);
ini[line.Substring(1, line.LastIndexOf("]")-1)]= currentSection;continue;}var idx = line.IndexOf("=");if(idx ==-1)
currentSection[line]="";else
currentSection[line.Substring(0, idx)]= line.Substring(idx +1);}}publicstringGetValue(string key){returnGetValue(key,"","");}publicstringGetValue(string key,string section){returnGetValue(key, section,"");}publicstringGetValue(string key,string section,string@default){if(!ini.ContainsKey(section))return@default;if(!ini[section].ContainsKey(key))return@default;return ini[section][key];}publicstring[]GetKeys(string section){if(!ini.ContainsKey(section))returnnewstring[0];return ini[section].Keys.ToArray();}publicstring[]GetSections(){return ini.Keys.Where(t => t !="").ToArray();}}
i dziękuję, że tego catch (Exception ex) { throw ex; }nie
umieściłeś
1
Dobry! Konieczne są przynajmniej niektóre zmiany, aby działały lepiej. Wiersz 16: ini [""] = currentSection; Do: // ini [""] = currentSection; Należy to usunąć, ponieważ za każdym razem pierwszy element [0] będzie pustym segmentem z powodu tej inicjalizacji. Linia 36: currentSection [line.Substring (0, idx)] = line.Substring (idx + 1); Do: currentSection [line.Substring (0, idx) .Trim ()] = line.Substring (idx + 1) .Trim (); Klucz i wartości należy przycinać niezależnie, nie tylko na linii Przytnij. W plikach konfiguracyjnych podobnych do INI zwykle osoby, które dodają pary K-> V, mają tendencję do wyrównywania tych równości w sekcjach. Dziękuję Ci!
LXSoft
Byłem długo. Wielkie dzięki za sugestie. Wszystkie mają sens i zasługują na ten kod, aby mieć dobre odświeżenie.
Larry,
13
Chcę wprowadzić bibliotekę IniParser, którą utworzyłem całkowicie w języku c #, więc nie zawiera żadnych zależności w żadnym systemie operacyjnym, co czyni ją kompatybilną z Mono. Open Source z licencją MIT - więc można go używać w dowolnym kodzie.
Jeśli potrzebujesz tylko dostępu do odczytu, a nie dostępu do zapisu i używasz Microsoft.Extensions.Confiuration(domyślnie jest dostarczany w pakiecie z programem ASP.NET Core, ale działa również ze zwykłymi programami), możesz użyć pakietu NuGet Microsoft.Extensions.Configuration.Inido importowania plików ini do ustawień konfiguracji.
Wystarczy dodać, że otrzymujesz klucze za pomocąConfiguration["keyname"]
kofifus
@ scott Mam problem z jakiegokolwiek powodu, że IIS nie rozpoznaje go, gdy aplikacja jest uruchomiona. jest wdrożony i tam, ale nie jest konsumowany. HTTP 500.30 powrócił, a dziennik aplikacji IIS mówi „plik konfiguracyjny nie został znaleziony i nie jest opcjonalny”.
one.beat.consumer
3
Zwykle podczas tworzenia aplikacji przy użyciu C # i środowiska .NET nie używa się plików INI. Bardziej powszechne jest przechowywanie ustawień w pliku konfiguracyjnym opartym na XML lub w rejestrze. Jeśli jednak oprogramowanie współdzieli ustawienia ze starszą aplikacją, może być łatwiej użyć pliku konfiguracyjnego, niż powielać informacje w innym miejscu.
.NET Framework nie obsługuje bezpośredniego korzystania z plików INI. Możesz jednak używać funkcji Windows API z Platform Invocation Services (P / Invoke) do zapisu i odczytu z plików. W tym linku tworzymy klasę, która reprezentuje pliki INI i używa funkcji Windows API do manipulowania nimi. Proszę przejść przez poniższy link.
Trzymaj się z dala od rejestru! Dane konfiguracji aplikacji nie powinny być zapisywane w rejestrze.
deegee
3
Jeśli chcesz tylko prosty czytnik bez sekcji i innych bibliotek DLL, oto proste rozwiązanie:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Tool{publicclassConfig{Dictionary<string,string> values;publicConfig(string path){
values =File.ReadLines(path).Where(line =>(!String.IsNullOrWhiteSpace(line)&&!line.StartsWith("#"))).Select(line => line.Split(newchar[]{'='},2,0)).ToDictionary(parts => parts[0].Trim(), parts => parts.Length>1?parts[1].Trim():null);}publicstringValue(string name,stringvalue=null){if(values!=null&& values.ContainsKey(name)){return values[name];}returnvalue;}}}
Przykład użycia:
file =newTool.Config(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)+"\\config.ini");
command = file.Value("command");
action = file.Value("action");stringvalue;//second parameter is default value if no key found with this namevalue= file.Value("debug","true");this.debug =(value.ToLower()=="true"||value=="1");value= file.Value("plain","false");this.plain =(value.ToLower()=="true"||value=="1");
Tymczasem konfiguruj zawartość pliku (jak widzisz obsługuje # symbol komentarza do linii):
#command to run
command = php
#default script
action = index.php
#debug mode#debug = true#plain text mode#plain = false#icon = favico.ico
PeanutButter.INI jest Nuget zapakowane klasa dla plików INI manipulacji. Obsługuje odczyt / zapis, w tym komentarze - komentarze są zapisywane podczas zapisu. Wydaje się być dość popularny, jest przetestowany i łatwy w użyciu. Jest również całkowicie darmowy i open source.
Jestem spóźniony, aby dołączyć do imprezy, ale miałem dzisiaj ten sam problem i napisałem następującą implementację:
using System.Text.RegularExpressions;staticbool match(thisstring str,string pat,outMatch m)=>(m =Regex.Match(str, pat,RegexOptions.IgnoreCase)).Success;staticvoidMain(){Dictionary<string,Dictionary<string,string>> ini =newDictionary<string,Dictionary<string,string>>();string section ="";foreach(string line inFile.ReadAllLines(.........))// read from file{string ln =(line.Contains('#')? line.Remove(line.IndexOf('#')): line).Trim();if(ln.match(@"^[ \t]*\[(?<sec>[\w\-]+)\]",outMatch m))
section = m.Groups["sec"].ToString();elseif(ln.match(@"^[ \t]*(?<prop>[\w\-]+)\=(?<val>.*)",out m)){if(!ini.ContainsKey(section))
ini[section]=newDictionary<string,string>();
ini[section][m.Groups["prop"].ToString()]= m.Groups["val"].ToString();}}// access the ini file as follows:string content = ini["section"]["property"];}
Należy zauważyć, że ta implementacja nie obsługuje sekcji ani właściwości, które nie zostały znalezione. Aby to osiągnąć, powinieneś rozszerzyć Dictionary<,>klasę o obsługę nieuzasadnionych kluczy.
Aby serializować wystąpienie Dictionary<string, Dictionary<string, string>>pliku .ini-file, używam następującego kodu:
string targetpath =.........;Dictionary<string,Dictionary<string,string>> ini =........;StringBuilder sb =newStringBuilder();foreach(string section in ini.Keys){
sb.AppendLine($"[{section}]");foreach(string property in ini[section].Keys)
sb.AppendLine($"{property}={ini[section][property]");}File.WriteAllText(targetpath, sb.ToString());
W przypadku, gdy nie jest to oczywiste, patrząc na najwyższy poziom biblioteki (nie było to dla mnie oczywiste!), Klasa IniDcoument i inni są w ComLib.IO.
Tim Keating
2
Dla każdego, kto patrzy na tę trasę, CommonLibrary.NET nie wydaje się przestrzegać konwencji .INI. Używa dwukropka „:” jako separatora zamiast znaku równości i nie obsługuje komentarzy (rozpoczęcie linii znakiem średnika lub funta spowoduje błąd analizy).
jmmr
2
Oto moja własna wersja, wykorzystująca wyrażenia regularne. Ten kod zakłada, że nazwa każdej sekcji jest unikalna - jeśli jednak nie jest to prawdą - sensowne jest zastąpienie słownika Listą. Ta funkcja obsługuje komentowanie plików .ini, zaczynając od „;” postać. Sekcja zaczyna się normalnie [sekcja], a pary klucz-wartość również mają normalnie „klucz = wartość”. Takie samo założenie jak dla sekcji - nazwa klucza jest unikalna.
/// <summary>/// Loads .ini file into dictionary./// </summary>publicstaticDictionary<String,Dictionary<String,String>> loadIni(String file){Dictionary<String,Dictionary<String,String>> d =newDictionary<string,Dictionary<string,string>>();String ini =File.ReadAllText(file);// Remove comments, preserve linefeeds, if end-user needs to count line number.
ini =Regex.Replace(ini,@"^\s*;.*$","",RegexOptions.Multiline);// Pick up all lines from first section to another sectionforeach(Match m inRegex.Matches(ini,"(^|[\r\n])\\[([^\r\n]*)\\][\r\n]+(.*?)(\\[([^\r\n]*)\\][\r\n]+|$)",RegexOptions.Singleline)){String sectionName = m.Groups[2].Value;Dictionary<String,String> lines =newDictionary<String,String>();// Pick up "key = value" kind of syntax.foreach(Match l inRegex.Matches(ini,@"^\s*(.*?)\s*=\s*(.*?)\s*$",RegexOptions.Multiline)){String key = l.Groups[1].Value;Stringvalue= l.Groups[2].Value;// Open up quotation if any.value=Regex.Replace(value,"^\"(.*)\"$","$1");if(!lines.ContainsKey(key))
lines[key]=value;}if(!d.ContainsKey(sectionName))
d[sectionName]= lines;}return d;}
Ta funkcja nie działa, dla mnie: Zapomina jedną sekcję na dwie części. Próbowałem przed i bez pustych linii przed [Sekcją].
iksess
czy możesz skopiować przykład swojego pliku .ini, który nie działa?
TarmoPikaro
-3
Oto moja klasa, działa jak urok:
publicstaticclassIniFileManager{[DllImport("kernel32")]privatestaticexternlongWritePrivateProfileString(string section,string key,string val,string filePath);[DllImport("kernel32")]privatestaticexternintGetPrivateProfileString(string section,string key,string def,StringBuilder retVal,int size,string filePath);[DllImport("kernel32.dll")]privatestaticexternintGetPrivateProfileSection(string lpAppName,byte[] lpszReturnBuffer,int nSize,string lpFileName);/// <summary>/// Write Data to the INI File/// </summary>/// <PARAM name="Section"></PARAM>/// Section name/// <PARAM name="Key"></PARAM>/// Key Name/// <PARAM name="Value"></PARAM>/// Value NamepublicstaticvoidIniWriteValue(string sPath,stringSection,stringKey,stringValue){WritePrivateProfileString(Section,Key,Value, sPath);}/// <summary>/// Read Data Value From the Ini File/// </summary>/// <PARAM name="Section"></PARAM>/// <PARAM name="Key"></PARAM>/// <PARAM name="Path"></PARAM>/// <returns></returns>publicstaticstringIniReadValue(string sPath,stringSection,stringKey){StringBuilder temp =newStringBuilder(255);int i =GetPrivateProfileString(Section,Key,"", temp,255, sPath);return temp.ToString();}
}
Użycie jest obviouse, ponieważ jest to klasa statyczna, wystarczy wywołać IniFileManager.IniWriteValue do odczytu sekcji lub IniFileManager.IniReadValue do odczytu sekcji.
To podejście zostało już wykazane i wyjaśnione w innej odpowiedzi . Co dodaje twoja odpowiedź, której nie obejmuje?
Palec
Uważaj, że to działa tylko wtedy, gdy plik .ini jest zapisany w UNICODE (16bit LE). Użyj Notepad ++, aby przekonwertować tekst na Unicode, ponieważ jeśli zapiszesz go w UTF-8, nie zadziała. Akceptowany jest również ANSI, ale nie można czytać liter akcentowanych
użytkownik2991288
-6
Powinieneś czytać i zapisywać dane z plików xml, ponieważ możesz zapisać cały obiekt do xml, a także możesz wypełnić obiekt z zapisanego xml. Lepiej jest łatwo manipulować obiektami.
Zalecane są linki do zasobów zewnętrznych, ale dodaj kontekst wokół linku, aby inni użytkownicy mieli pojęcie, co to jest i dlaczego. Zawsze podawaj najistotniejszą część ważnego linku, na wypadek gdyby strona docelowa była nieosiągalna lub została trwale wyłączona.
davejal
Uważam, że tytuły linków są bardzo jasne na temat odniesień / kontekstu. Jeśli uważasz, że to za mało, możesz go edytować.
Odpowiedzi:
Twórcy frameworka .NET chcą, abyś używał plików konfiguracyjnych opartych na XML, a nie plików INI. Więc nie, nie ma wbudowanego mechanizmu ich odczytu.
Dostępne są jednak rozwiązania innych firm.
źródło
Przedmowa
Najpierw przeczytaj ten post na blogu MSDN na temat ograniczeń plików INI . Jeśli odpowiada Twoim potrzebom, czytaj dalej.
Jest to zwięzłe wdrożenie, które napisałem przy użyciu oryginalnego P / Invoke systemu Windows, więc jest obsługiwane przez wszystkie wersje systemu Windows z zainstalowanym programem .NET (tj. Windows 98 - Windows 10). Niniejszym udostępniam go w domenie publicznej - możesz swobodnie korzystać z niego w celach komercyjnych bez podawania źródła.
Mała klasa
Dodaj nową klasę
IniFile.cs
do swojego projektu:Jak tego użyć
Otwórz plik INI na jeden z 3 następujących sposobów:
Możesz napisać kilka takich wartości:
Aby utworzyć taki plik:
Aby odczytać wartości z pliku INI:
Opcjonalnie możesz ustawić
[Section]
:Aby utworzyć taki plik:
Możesz także sprawdzić, czy istnieje taki klucz:
Możesz usunąć klucz w ten sposób:
Możesz również usunąć całą sekcję (w tym wszystkie klucze) w następujący sposób:
Skomentuj wszelkie ulepszenia!
źródło
GetSections()
metody.Path.GetFullPath(IniPath ?? Path.ChangeExtension(Application.ExecutablePath, ".ini"))
.Ten artykuł na temat CodeProject „ Klasa obsługi plików INI przy użyciu C # ” powinna pomóc.
Autor stworzył klasę C # „Ini”, która udostępnia dwie funkcje z KERNEL32.dll. Te funkcje to:
WritePrivateProfileString
iGetPrivateProfileString
. Potrzebne będą dwie przestrzenie nazw:System.Runtime.InteropServices
iSystem.Text
.Kroki korzystania z klasy Ini
W definicji przestrzeni nazw projektu dodaj
Utwórz taki plik INIF
Służy
IniWriteValue
do zapisywania nowej wartości do określonego klucza w sekcji lubIniReadValue
do odczytu wartości z klucza w określonej sekcji.Uwaga: jeśli zaczynasz od zera, możesz przeczytać ten artykuł MSDN : Porady: dodawanie plików konfiguracji aplikacji do projektów w języku C # . To lepszy sposób na skonfigurowanie aplikacji.
źródło
Znalazłem tę prostą implementację:
http://bytes.com/topic/net/insights/797169-reading-parsing-ini-file-c
Działa dobrze na to, czego potrzebuję.
Oto jak z niego korzystasz:
Oto kod:
źródło
Kod w odpowiedzi joerage jest inspirujący.
Niestety zmienia obudowę znaków klawiszy i nie obsługuje komentarzy. Napisałem więc coś, co powinno być wystarczająco solidne, aby odczytać (tylko) bardzo brudne pliki INI i pozwala odzyskać klucze takimi, jakie są.
Korzysta z LINQ, zagnieżdżonego słownika ciągów bez rozróżniania wielkości liter, do przechowywania sekcji, kluczy i wartości oraz odczytywania pliku za jednym razem.
źródło
catch (Exception ex) { throw ex; }
nieChcę wprowadzić bibliotekę IniParser, którą utworzyłem całkowicie w języku c #, więc nie zawiera żadnych zależności w żadnym systemie operacyjnym, co czyni ją kompatybilną z Mono. Open Source z licencją MIT - więc można go używać w dowolnym kodzie.
Możesz sprawdzić źródło w GitHub , jest ono również dostępne jako pakiet NuGet
Jest wysoce konfigurowalny i bardzo prosty w użyciu .
Przepraszam za bezwstydną wtyczkę, ale mam nadzieję, że może pomóc każdemu, kto zmieni tę odpowiedź.
źródło
Jeśli potrzebujesz tylko dostępu do odczytu, a nie dostępu do zapisu i używasz
Microsoft.Extensions.Confiuration
(domyślnie jest dostarczany w pakiecie z programem ASP.NET Core, ale działa również ze zwykłymi programami), możesz użyć pakietu NuGetMicrosoft.Extensions.Configuration.Ini
do importowania plików ini do ustawień konfiguracji.źródło
Configuration["keyname"]
Zwykle podczas tworzenia aplikacji przy użyciu C # i środowiska .NET nie używa się plików INI. Bardziej powszechne jest przechowywanie ustawień w pliku konfiguracyjnym opartym na XML lub w rejestrze. Jeśli jednak oprogramowanie współdzieli ustawienia ze starszą aplikacją, może być łatwiej użyć pliku konfiguracyjnego, niż powielać informacje w innym miejscu.
.NET Framework nie obsługuje bezpośredniego korzystania z plików INI. Możesz jednak używać funkcji Windows API z Platform Invocation Services (P / Invoke) do zapisu i odczytu z plików. W tym linku tworzymy klasę, która reprezentuje pliki INI i używa funkcji Windows API do manipulowania nimi. Proszę przejść przez poniższy link.
Odczytywanie i zapisywanie plików INI
źródło
Jeśli chcesz tylko prosty czytnik bez sekcji i innych bibliotek DLL, oto proste rozwiązanie:
Przykład użycia:
Tymczasem konfiguruj zawartość pliku (jak widzisz obsługuje # symbol komentarza do linii):
źródło
Wypróbuj tę metodę:
Tworzy słownik, w którym klucz to „-”. Możesz załadować w następujący sposób:
źródło
PeanutButter.INI jest Nuget zapakowane klasa dla plików INI manipulacji. Obsługuje odczyt / zapis, w tym komentarze - komentarze są zapisywane podczas zapisu. Wydaje się być dość popularny, jest przetestowany i łatwy w użyciu. Jest również całkowicie darmowy i open source.
Oświadczenie: Jestem autorem PeanutButter.INI.
źródło
Jestem spóźniony, aby dołączyć do imprezy, ale miałem dzisiaj ten sam problem i napisałem następującą implementację:
Należy zauważyć, że ta implementacja nie obsługuje sekcji ani właściwości, które nie zostały znalezione. Aby to osiągnąć, powinieneś rozszerzyć
Dictionary<,>
klasę o obsługę nieuzasadnionych kluczy.Aby serializować wystąpienie
Dictionary<string, Dictionary<string, string>>
pliku.ini
-file, używam następującego kodu:źródło
W CommonLibrary.NET dostępny jest Ini Parser
Ma to różne bardzo wygodne przeciążenia do uzyskiwania przekrojów / wartości i jest bardzo lekki.
źródło
Oto moja własna wersja, wykorzystująca wyrażenia regularne. Ten kod zakłada, że nazwa każdej sekcji jest unikalna - jeśli jednak nie jest to prawdą - sensowne jest zastąpienie słownika Listą. Ta funkcja obsługuje komentowanie plików .ini, zaczynając od „;” postać. Sekcja zaczyna się normalnie [sekcja], a pary klucz-wartość również mają normalnie „klucz = wartość”. Takie samo założenie jak dla sekcji - nazwa klucza jest unikalna.
źródło
Oto moja klasa, działa jak urok:
}
Użycie jest obviouse, ponieważ jest to klasa statyczna, wystarczy wywołać IniFileManager.IniWriteValue do odczytu sekcji lub IniFileManager.IniReadValue do odczytu sekcji.
źródło
Powinieneś czytać i zapisywać dane z plików xml, ponieważ możesz zapisać cały obiekt do xml, a także możesz wypełnić obiekt z zapisanego xml. Lepiej jest łatwo manipulować obiektami.
Oto jak to zrobić: Zapisz dane obiektu do pliku XML: https://msdn.microsoft.com/en-us/library/ms172873.aspx Odczytaj dane obiektu z pliku XML: https://msdn.microsoft. com / en-us / library / ms172872.aspx
źródło