|
|
It solved my problem and useful article..
|
|
|
|
|
It solved my problem and useful article..
|
|
|
|
|
this Cod is perfect .. Thx a lot
|
|
|
|
|
|
|
///
/// see IniWriteValue, but write an integer
///
public void IniWriteInt(string section, string key, int value)
{
String s = Convert.ToString(value);
IniWriteValue(section, key, s);
}
///
/// see IniReadValue, but read as an integer.
///
public int IniReadInt(string section, string key)
{
String s= IniReadValue(section,key);
String exceptionMsg = "string could not be converted to an int";
int value;
try
{
value = Convert.ToInt32(s);
}
catch (FormatException ex)
{
throw new IniFileException(exceptionMsg, ex);
}
catch (OverflowException ex)
{
throw new IniFileException(exceptionMsg, ex);
}
return value;
}
public class IniFileException : Exception
{
//TODO put this class in it's own file.
public IniFileException(String message)
: base(message)
{
}
public IniFileException(string message, Exception ex)
: base(message, ex)
{
}
}
|
|
|
|
|
This is way overcomplicated. Try this instead:
public class IniFile
{
public string path;
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section, string key, string val, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
public IniFile(string INIPath)
{
path = INIPath;
}
public void IniWriteValue(string Section, string Key, string Value)
{
WritePrivateProfileString(Section, Key, Value, this.path);
}
public string IniReadValue(string Section,string Key, string Def)
{
StringBuilder temp = new StringBuilder(255);
int i = GetPrivateProfileString(Section, Key, (def != null ? def : string.Empty), temp, 255, this.path);
return temp.ToString();
}
public void IniWriteValue(string Section, string Key, int Value)
{
IniWriteValue(Section, Key, Value.ToString());
}
public int IniReadValue(string section, string key, int? def)
{
string s = ReadValue(section, key, (def != null ? def.ToString() : null));
int i = 0;
if (int.TryParse(s, out i))
return i;
else
throw new IniFileException("Tried to retrieve invalid value type from ini.");
}
}
public class IniFileException : Exception
{
public IniFileException(string Message)
: base(Message)
{
}
}
Your stack trace will now have everything you need, and you can get rid of the messy try...catch...throw. There's no need to include an InnerException as part of the newly thrown IniFileException, as no other Exception has been generated yet.
You have room for a default value now, and you're using overloads instead of multiple alternately named, similar functions. This is a more standardized method for this sort of endeavor.
An int.TryParse is just a hair slower than a Convert.ToInt32 but the overhead this method will save you on failure is well worth it. Additionally, it's the preferred method for conversion.
|
|
|
|
|
Hi md5sum, thx for your insight here!
Allthough the methodes I posted
do what they supposed to, I agree
with overloading, the methods you posted.
I made changes accordingly. However I am not sure
about using tryparse. if reading from ini would fail because
the number is too high to be parsed or there is an invalid
format, then you can't distinqush between those cases from
iniexception anymore.
|
|
|
|
|
I suppose if you need that much granularity in your error reporting, then it would be necessary to report it that way. However, I would probably instead change:
throw new IniFileException("Tried to retrieve invalid value type from ini.");
to:
throw new IniFileException(string.Format("Tried to retrieve invalid value type from ini. Tried to convert \"{0}\" to int.", s));
in order to introduce the same level of reporting the cause of the error without the granularity of exception types generated through the alternate, multiple catch method. I can't imagine an instance where I would need (for myself or my users) to have more than a single exception generated from this block of code. In general though, if you absolutely want to keep the InnerException and specifically NOT use a TryParse, I would limit it to simply:
try
{
i = Convert.ToInt32(s);
}
catch (Exception ex)
{
throw new IniFileException("Tried to retrieve invalid value type from ini.", ex);
}
and add the following constructor back to the IniFileException class:
public IniFileException(string Message, Exception ex)
: base(Message, ex)
{
}
This will keep your granularity in exception types, rethrowing the wrapped exception with an appropriate InnerException. I just can't imagine why you would want that in this particular case.
modified on Friday, January 7, 2011 2:38 PM
|
|
|
|
|
good class
but where is the ReadValue() method??
EDIT:
is IniReadValue()
Thanks for the code!!
|
|
|
|
|
You can add GetPrivateProfileSectionNames method in the class. I find it really usefull.
[DllImport("kernel32")]
private static extern uint GetPrivateProfileSectionNames(byte[] lpszReturnBuffer,
int nSize, string lpFileName);
public List<String> IniSectionNames()
{
byte[] buff = new byte[1024];
GetPrivateProfileSectionNames(buff, buff.Length, this._path);
String s = Encoding.Default.GetString(buff);
String[] names = s.Split('\0');
return names.Where(n => n != string.Empty).ToList();
}
|
|
|
|
|
The code will only be able to retrieve strings that are 254 characters or less (to fit in a null-terminated buffer of 255 characters), otherwise they will be truncated.
int i = GetPrivateProfileString(Section,Key,"",temp, 255, this.path);
|
|
|
|
|
Found the same problem. May be the author should easy fix this bug?
|
|
|
|
|
don't explain exactly where tu put the items. nice help, but to those who has some knoledge in C# already
|
|
|
|
|
The solution work fine with one time input.
But problem come when read/write multiple line to the ini.
Every new record only replace the previous record.
Any solution to solve it?
|
|
|
|
|
CAN BE DONE THROUGH
FILE.Writeallline()
and can be read through file.readallline
file is beeter than stream read and stream write because stream write is used once if we used more than once it overwrite thats file is beeter option because it does not overwrite and there is no use of close0, flush in file .
|
|
|
|
|
Can you elaborate on this?
How would we implement File.WriteAllLines with the class?
|
|
|
|
|
Hey, nice job. I just posted an implementation I wrote a while ago on my site. It doesn't provide an interface to write to the Ini though just read from it. Take a look at it and let me know what you think.
http://www.crowsprogramming.com/archives/95
|
|
|
|
|
I added a IniGetCategories() and IniGetKeys() functions to the class based on a post I read at How to access INI Files in C# .NET - By Gerhard Stephan[^]
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Collections.Generic;
namespace Ini
{
public class IniFile
{
public string path;
[DllImport("KERNEL32.DLL", EntryPoint = "GetPrivateProfileStringW",
SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
private static extern int GetPrivateProfileString(
string lpAppName,
string lpKeyName,
string lpDefault,
string lpReturnString,
int nSize,
string lpFilename);
[DllImport("KERNEL32.DLL", EntryPoint="WritePrivateProfileStringW",
SetLastError=true,
CharSet=CharSet.Unicode, ExactSpelling=true,
CallingConvention=CallingConvention.StdCall)]
private static extern int WritePrivateProfileString(
string lpAppName,
string lpKeyName,
string lpString,
string lpFilename);
public IniFile(string INIPath)
{
path = INIPath;
}
public void IniWriteValue(string Section,string Key,string Value)
{
WritePrivateProfileString(Section,Key,Value,this.path);
}
public string IniReadValue(string Section,string Key)
{
string result = new string(' ', 255);
GetPrivateProfileString(Section, Key, "", result, 255, this.path);
return result;
}
public List<string> IniGetCategories()
{
string returnString = new string(' ', 65536);
GetPrivateProfileString(null,null,null,returnString,65536,this.path);
List<string> result = new List<string>(returnString.Split('\0'));
result.RemoveRange(result.Count - 2, 2);
return result;
}
public List<string> IniGetKeys(string category)
{
string returnString = new string(' ', 32768);
GetPrivateProfileString(category, null, null, returnString, 32768, this.path);
List<string> result = new List<string>(returnString.Split('\0'));
result.RemoveRange(result.Count-2,2);
return result;
}
}
}
Hope someone finds this useful!
Ben Ethington
|
|
|
|
|
I thought i would write a quick conversion from INI to Xml based on your additions to this class.
Here is what i came up with
public static void ConvertIni2Xml(string IniFileName, string XmlOutputFileName)
{
if (string.IsNullOrEmpty(XmlOutputFileName))
{
XmlOutputFileName = Path.Combine(Path.GetDirectoryName(IniFileName), String.Format("{0}.xml", Path.GetFileNameWithoutExtension(IniFileName)));
}
IniFile iniFile = new IniFile(IniFileName);
XmlTextWriter xw = null;
try
{
xw = new XmlTextWriter(XmlOutputFileName, Encoding.UTF8);
xw.WriteStartDocument();
xw.WriteStartElement("configuration");
foreach (string categoryName in iniFile.IniGetCategories())
{
xw.WriteStartElement("category");
xw.WriteAttributeString("name", categoryName);
foreach (string keyName in iniFile.IniGetKeys(categoryName))
{
xw.WriteStartElement("setting");
xw.WriteAttributeString("name", keyName);
xw.WriteAttributeString("value", iniFile.IniReadValue(categoryName, keyName));
xw.WriteEndElement();
}
xw.WriteEndElement();
}
xw.WriteEndElement();
xw.WriteEndDocument();
}
catch (Exception)
{
throw;
}
finally
{
if (xw != null)
{
xw.Close();
}
}
}
modified on Tuesday, August 4, 2009 2:35 PM
|
|
|
|
|
Adding to Ben's changes.. here's a method for fetching all the keys and their values together. (e.g. SourceFolder=C:\Windows\Temp, DestinationFolder=E:\Audit\Archives)
public List<string> GetKeysAndValues(string section)
{
List<string> result = new List<string>();
foreach (string key in GetKeys(section))
{
result.Add(key + "=" + ReadValue(section, key));
}
return result;
}
|
|
|
|
|
This is a nice class.
I'm a C# newbie and tried to add some additional methods useful for a project of mine.
public int IniReadValue(string Section, string Key, int DefaultValue)
{
string sTemp = IniReadValue(Section, Key, "");
if (sTemp.Length == 0)
{
return DefaultValue;
}
return Int32.Parse(sTemp);
}
public ulong IniReadValue(string Section, string Key, ulong DefaultValue)
{
string sTemp = IniReadValue(Section, Key, "");
if (sTemp.Length == 0)
{
return DefaultValue;
}
return ulong.Parse(sTemp);
}
public double IniReadValue(string Section, string Key, double DefaultValue)
{
string sTemp = IniReadValue(Section, Key, "");
if (sTemp.Length == 0)
{
return DefaultValue;
}
return double.Parse(sTemp, CultureInfo.GetCultureInfo("en-US").NumberFormat);
}
public bool IniReadValue(string Section, string Key, bool DefaultValue)
{
bool RetVal = DefaultValue;
string sTemp = IniReadValue(Section, Key, "");
if (sTemp.Length == 0)
{
return DefaultValue;
}
if (!bool.TryParse(sTemp, out RetVal))
{
return (Int32.Parse(sTemp) == 0) ? false : true;
}
return RetVal;
}
|
|
|
|
|
But you defined no method to accept third parameter as string: IniReadValue(Section, Key, "")
|
|
|
|
|
It could be accomplished by modifying the original IniReadValue() method and adding a third parameter to provide a default string to be used when the searched key cannot be found.
|
|
|
|
|