C# 使用文件流来读写ini文件

背景

  之前采用ini文件作为程序的配置文件,觉得这种结构简单明了,配置起来也挺方便。然后操作方式是通过WindowsAPI,然后再网上找到一个基于WindowsAPI封装的help类,用起来倒也顺手。用的多了,觉得还可以使用文件流来操作,后来就发现了EasyConfig。

  EasyConfig是一个纯C#的开源ini文件操作库,但是在使用上有诸多不便,只是个人感觉,于是个人将其改造了一下,是自己喜欢用的风格。

资源下载

  如果不清楚ini文件结构,请百度一下,这里贴一个示例文件。

 Ini文件示例
[Video]
#是否全屏
Fullscreen = true
#宽度
Width = 1280
#电视高度
#高度
Height = 720
[Level1]
NumberOfEnemies=2000#数值
Lives = 10
Timer = 999
EnemyNames = "Steve", "Sam", "Bill"
EnemyGuns = 13, 28, 43, 499
CanShoot = true, yes, on, no, false, off
Ini文件示例

  EasyConfig 原版

  EasyConfig 改写后

代码示例

  首先来看看改写后,怎么去使用她来读写Ini文件。

        static void Main(string[] args)
{
ConfigFile configFile = new ConfigFile("Test.ini"); //遍历Config文件
foreach (var group in configFile.SettingGroups)
{
Console.WriteLine("****************************");
Console.WriteLine(group.Key + ":");
Console.WriteLine(); foreach (var value in group.Value.Settings)
Console.WriteLine("{0} = {1} (Is Array? {2}),{3}", value.Key, value.Value.RawValue, value.Value.IsArray, value.Value.Desp); Console.WriteLine();
}
//读取值主要是在具体的配置项上进行读取,是首先定位到[Group],其次就是具体的项
//使用泛型读取值,并指定读取失败时的默认值
var fullScreen = configFile["Video"]["Fullscreen"].As<int>(-1);//失败
var bFullScreen = configFile["Video"]["Fullscreen"].AsBool();//成功
var arrCanShoot = configFile["Level1"]["CanShoot"].AsArray<bool>();
//读取时 该项不存在,不存在的组或者项会自动添加
var noexists = configFile["Video"]["xxxxxxxxxxx"].AsString();
var noexists2 = configFile["Video111111111"]["xxxxxxxxxxx"].AsString(); //写入值有2种方法,可以直接向某组下写入一项,也可以定位到某组某项,写入值
//写入值 该项不存在,组或者项会自动创建
configFile["Video"].WriteSetting("NewName", "EasyConfig");
configFile["Video"].WriteSetting("NewName", "EasyConfig2.0");
configFile["Video22222222"].WriteSetting("c1", "1");
//索引器不过是返回Setting
configFile["Video3333"]["UserName"].SetValue("admin");
configFile["Viedo4444"]["Sex"].SetValue("男", "女", "保密");
//写入值,该项不存在
configFile["Video222"].WriteSetting("NewName", "EasyConfig3.0"); Console.ReadKey(true); configFile.Save("TestConfig2.txt");
}

  基本上自己想要的效果,则是基于 ConfigFile["GroupName"]["Key"] 这样的方式来进行读写。

  另外附上一个基于WindowsAPI操作的封装类。

 IniFileHelp

/// <summary>
/// Provides methods for reading and writing to an INI file.
/// </summary>
public class IniFileHelp
{
/// <summary>
/// The maximum size of a section in an ini file.
/// </summary>
/// <remarks>
/// This property defines the maximum size of the buffers
/// used to retreive data from an ini file. This value is
/// the maximum allowed by the win32 functions
/// GetPrivateProfileSectionNames() or
/// GetPrivateProfileString().
/// </remarks>
public const int MaxSectionSize = 32767; // 32 KB

//The path of the file we are operating on.
private string m_path;

#region P/Invoke declares

/// <summary>
/// A static class that provides the win32 P/Invoke signatures
/// used by this class.
/// </summary>
/// <remarks>
/// Note: In each of the declarations below, we explicitly set CharSet to
/// Auto. By default in C#, CharSet is set to Ansi, which reduces
/// performance on windows 2000 and above due to needing to convert strings
/// from Unicode (the native format for all .Net strings) to Ansi before
/// marshalling. Using Auto lets the marshaller select the Unicode version of
/// these functions when available.
/// </remarks>
[System.Security.SuppressUnmanagedCodeSecurity]
private static class NativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer,
uint nSize,
string lpFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint GetPrivateProfileString(string lpAppName,
string lpKeyName,
string lpDefault,
StringBuilder lpReturnedString,
int nSize,
string lpFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint GetPrivateProfileString(string lpAppName,
string lpKeyName,
string lpDefault,
[In, Out] char[] lpReturnedString,
int nSize,
string lpFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetPrivateProfileString(string lpAppName,
string lpKeyName,
string lpDefault,
IntPtr lpReturnedString,
uint nSize,
string lpFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetPrivateProfileInt(string lpAppName,
string lpKeyName,
int lpDefault,
string lpFileName);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetPrivateProfileSection(string lpAppName,
IntPtr lpReturnedString,
uint nSize,
string lpFileName);

//We explicitly enable the SetLastError attribute here because
// WritePrivateProfileString returns errors via SetLastError.
// Failure to set this can result in errors being lost during
// the marshal back to managed code.
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool WritePrivateProfileString(string lpAppName,
string lpKeyName,
string lpString,
string lpFileName);

}
#endregion

/// <summary>
/// Initializes a new instance of the <see cref="IniFileHelp"/> class.
/// </summary>
/// <param name="path">The ini file to read and write from.</param>
public IniFileHelp(string path)
{
//Convert to the full path. Because of backward compatibility,
// the win32 functions tend to assume the path should be the
// root Windows directory if it is not specified. By calling
// GetFullPath, we make sure we are always passing the full path
// the win32 functions.
m_path = System.IO.Path.GetFullPath(path);
}

/// <summary>
/// Gets the full path of ini file this object instance is operating on.
/// </summary>
/// <value>A file path.</value>
public string Path
{
get
{
return m_path;
}
}

#region Get Value Methods

/// <summary>
/// Gets the value of a setting in an ini file as a <see cref="T:System.String"/>.
/// </summary>
/// <param name="sectionName">The name of the section to read from.</param>
/// <param name="keyName">The name of the key in section to read.</param>
/// <param name="defaultValue">The default value to return if the key
/// cannot be found.</param>
/// <returns>The value of the key, if found. Otherwise, returns
/// <paramref name="defaultValue"/></returns>
/// <remarks>
/// The retreived value must be less than 32KB in length.
/// </remarks>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> or <paramref name="keyName"/> are
/// a null reference (Nothing in VB)
/// </exception>
public string GetString(string sectionName,
string keyName,
string defaultValue)
{
if (sectionName == null)
throw new ArgumentNullException("sectionName");

if (keyName == null)
throw new ArgumentNullException("keyName");

StringBuilder retval = new StringBuilder(IniFileHelp.MaxSectionSize);

NativeMethods.GetPrivateProfileString(sectionName,
keyName,
defaultValue,
retval,
IniFileHelp.MaxSectionSize,
m_path);

return retval.ToString();
}

/// <summary>
/// Gets the value of a setting in an ini file as a <see cref="T:System.Int16"/>.
/// </summary>
/// <param name="sectionName">The name of the section to read from.</param>
/// <param name="keyName">The name of the key in section to read.</param>
/// <param name="defaultValue">The default value to return if the key
/// cannot be found.</param>
/// <returns>The value of the key, if found. Otherwise, returns
/// <paramref name="defaultValue"/>.</returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> or <paramref name="keyName"/> are
/// a null reference (Nothing in VB)
/// </exception>
public int GetInt16(string sectionName,
string keyName,
short defaultValue)
{
int retval = GetInt32(sectionName, keyName, defaultValue);

return Convert.ToInt16(retval);
}

/// <summary>
/// Gets the value of a setting in an ini file as a <see cref="T:System.Int32"/>.
/// </summary>
/// <param name="sectionName">The name of the section to read from.</param>
/// <param name="keyName">The name of the key in section to read.</param>
/// <param name="defaultValue">The default value to return if the key
/// cannot be found.</param>
/// <returns>The value of the key, if found. Otherwise, returns
/// <paramref name="defaultValue"/></returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> or <paramref name="keyName"/> are
/// a null reference (Nothing in VB)
/// </exception>
public int GetInt32(string sectionName,
string keyName,
int defaultValue)
{
if (sectionName == null)
throw new ArgumentNullException("sectionName");

if (keyName == null)
throw new ArgumentNullException("keyName");

return NativeMethods.GetPrivateProfileInt(sectionName, keyName, defaultValue, m_path);
}

/// <summary>
/// Gets the value of a setting in an ini file as a <see cref="T:System.Double"/>.
/// </summary>
/// <param name="sectionName">The name of the section to read from.</param>
/// <param name="keyName">The name of the key in section to read.</param>
/// <param name="defaultValue">The default value to return if the key
/// cannot be found.</param>
/// <returns>The value of the key, if found. Otherwise, returns
/// <paramref name="defaultValue"/></returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> or <paramref name="keyName"/> are
/// a null reference (Nothing in VB)
/// </exception>
public double GetDouble(string sectionName,
string keyName,
double defaultValue)
{
string retval = GetString(sectionName, keyName, "");

if (retval == null || retval.Length == 0)
{
return defaultValue;
}

return Convert.ToDouble(retval, CultureInfo.InvariantCulture);
}

#endregion

#region GetSectionValues Methods

/// <summary>
/// Gets all of the values in a section as a list.
/// </summary>
/// <param name="sectionName">
/// Name of the section to retrieve values from.
/// </param>
/// <returns>
/// A <see cref="List{T}"/> containing <see cref="KeyValuePair{T1, T2}"/> objects
/// that describe this section. Use this verison if a section may contain
/// multiple items with the same key value. If you know that a section
/// cannot contain multiple values with the same key name or you don't
/// care about the duplicates, use the more convenient
/// <see cref="GetSectionValues"/> function.
/// </returns>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> is a null reference (Nothing in VB)
/// </exception>
public List<KeyValuePair<string, string>> GetSectionValuesAsList(string sectionName)
{
List<KeyValuePair<string, string>> retval;
string[] keyValuePairs;
string key, value;
int equalSignPos;

if (sectionName == null)
throw new ArgumentNullException("sectionName");

//Allocate a buffer for the returned section names.
IntPtr ptr = Marshal.AllocCoTaskMem(IniFileHelp.MaxSectionSize);

try
{
//Get the section key/value pairs into the buffer.
int len = NativeMethods.GetPrivateProfileSection(sectionName,
ptr,
IniFileHelp.MaxSectionSize,
m_path);

keyValuePairs = ConvertNullSeperatedStringToStringArray(ptr, len);
}
finally
{
//Free the buffer
Marshal.FreeCoTaskMem(ptr);
}

//Parse keyValue pairs and add them to the list.
retval = new List<KeyValuePair<string, string>>(keyValuePairs.Length);

for (int i = 0; i < keyValuePairs.Length; ++i)
{
//Parse the "key=value" string into its constituent parts
//Cancel a string start with '#'
var item = keyValuePairs[i].Trim();
if (item.Length > 0 && !item.StartsWith("#"))
{
equalSignPos = keyValuePairs[i].IndexOf('=');
key = keyValuePairs[i].Substring(0, equalSignPos);

value = keyValuePairs[i].Substring(equalSignPos + 1,
keyValuePairs[i].Length - equalSignPos - 1);

retval.Add(new KeyValuePair<string, string>(key, value));
}
}

return retval;
}

/// <summary>
/// Gets all of the values in a section as a dictionary.
/// </summary>
/// <param name="sectionName">
/// Name of the section to retrieve values from.
/// </param>
/// <returns>
/// A <see cref="Dictionary{T, T}"/> containing the key/value
/// pairs found in this section.
/// </returns>
/// <remarks>
/// If a section contains more than one key with the same name,
/// this function only returns the first instance. If you need to
/// get all key/value pairs within a section even when keys have the
/// same name, use <see cref="GetSectionValuesAsList"/>.
/// </remarks>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> is a null reference (Nothing in VB)
/// </exception>
public Dictionary<string, string> GetSectionValues(string sectionName)
{
List<KeyValuePair<string, string>> keyValuePairs;
Dictionary<string, string> retval;

keyValuePairs = GetSectionValuesAsList(sectionName);

//Convert list into a dictionary.
retval = new Dictionary<string, string>(keyValuePairs.Count);

foreach (KeyValuePair<string, string> keyValuePair in keyValuePairs)
{
//Skip any key we have already seen.
if (!retval.ContainsKey(keyValuePair.Key))
{
retval.Add(keyValuePair.Key, keyValuePair.Value);
}
}

return retval;
}

#endregion

#region Get Key/Section Names

/// <summary>
/// Gets the names of all keys under a specific section in the ini file.
/// </summary>
/// <param name="sectionName">
/// The name of the section to read key names from.
/// </param>
/// <returns>An array of key names.</returns>
/// <remarks>
/// The total length of all key names in the section must be
/// less than 32KB in length.
/// </remarks>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> is a null reference (Nothing in VB)
/// </exception>
public string[] GetKeyNames(string sectionName)
{
int len;
string[] retval;

if (sectionName == null)
throw new ArgumentNullException("sectionName");

//Allocate a buffer for the returned section names.
IntPtr ptr = Marshal.AllocCoTaskMem(IniFileHelp.MaxSectionSize);

try
{
//Get the section names into the buffer.
len = NativeMethods.GetPrivateProfileString(sectionName,
null,
null,
ptr,
IniFileHelp.MaxSectionSize,
m_path);

retval = ConvertNullSeperatedStringToStringArray(ptr, len);
}
finally
{
//Free the buffer
Marshal.FreeCoTaskMem(ptr);
}

return retval;
}

/// <summary>
/// Gets the names of all sections in the ini file.
/// </summary>
/// <returns>An array of section names.</returns>
/// <remarks>
/// The total length of all section names in the section must be
/// less than 32KB in length.
/// </remarks>
public string[] GetSectionNames()
{
string[] retval;
int len;

//Allocate a buffer for the returned section names.
IntPtr ptr = Marshal.AllocCoTaskMem(IniFileHelp.MaxSectionSize);

try
{
//Get the section names into the buffer.
len = NativeMethods.GetPrivateProfileSectionNames(ptr,
IniFileHelp.MaxSectionSize, m_path);

retval = ConvertNullSeperatedStringToStringArray(ptr, len);
}
finally
{
//Free the buffer
Marshal.FreeCoTaskMem(ptr);
}

return retval;
}

/// <summary>
/// Converts the null seperated pointer to a string into a string array.
/// </summary>
/// <param name="ptr">A pointer to string data.</param>
/// <param name="valLength">
/// Length of the data pointed to by <paramref name="ptr"/>.
/// </param>
/// <returns>
/// An array of strings; one for each null found in the array of characters pointed
/// at by <paramref name="ptr"/>.
/// </returns>
private static string[] ConvertNullSeperatedStringToStringArray(IntPtr ptr, int valLength)
{
string[] retval;

if (valLength == 0)
{
//Return an empty array.
retval = new string[0];
}
else
{
//Convert the buffer into a string. Decrease the length
//by 1 so that we remove the second null off the end.
string buff = Marshal.PtrToStringAuto(ptr, valLength - 1);

//Parse the buffer into an array of strings by searching for nulls.
retval = buff.Split('\0');
}

return retval;
}

#endregion

#region Write Methods

/// <summary>
/// Writes a <see cref="T:System.String"/> value to the ini file.
/// </summary>
/// <param name="sectionName">The name of the section to write to .</param>
/// <param name="keyName">The name of the key to write to.</param>
/// <param name="value">The string value to write</param>
/// <exception cref="T:System.ComponentModel.Win32Exception">
/// The write failed.
/// </exception>
private void WriteValueInternal(string sectionName, string keyName, string value)
{
if (!NativeMethods.WritePrivateProfileString(sectionName, keyName, value, m_path))
{
throw new System.ComponentModel.Win32Exception();
}
}

/// <summary>
/// Writes a <see cref="T:System.String"/> value to the ini file.
/// </summary>
/// <param name="sectionName">The name of the section to write to .</param>
/// <param name="keyName">The name of the key to write to.</param>
/// <param name="value">The string value to write</param>
/// <exception cref="T:System.ComponentModel.Win32Exception">
/// The write failed.
/// </exception>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> or <paramref name="keyName"/> or
/// <paramref name="value"/> are a null reference (Nothing in VB)
/// </exception>
public void WriteValue(string sectionName, string keyName, string value)
{
if (sectionName == null)
throw new ArgumentNullException("sectionName");

if (keyName == null)
throw new ArgumentNullException("keyName");

if (value == null)
throw new ArgumentNullException("value");

WriteValueInternal(sectionName, keyName, value);
}

/// <summary>
/// Writes an <see cref="T:System.Int16"/> value to the ini file.
/// </summary>
/// <param name="sectionName">The name of the section to write to .</param>
/// <param name="keyName">The name of the key to write to.</param>
/// <param name="value">The value to write</param>
/// <exception cref="T:System.ComponentModel.Win32Exception">
/// The write failed.
/// </exception>
public void WriteValue(string sectionName, string keyName, short value)
{
WriteValue(sectionName, keyName, (int)value);
}

/// <summary>
/// Writes an <see cref="T:System.Int32"/> value to the ini file.
/// </summary>
/// <param name="sectionName">The name of the section to write to .</param>
/// <param name="keyName">The name of the key to write to.</param>
/// <param name="value">The value to write</param>
/// <exception cref="T:System.ComponentModel.Win32Exception">
/// The write failed.
/// </exception>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> or <paramref name="keyName"/> are
/// a null reference (Nothing in VB)
/// </exception>
public void WriteValue(string sectionName, string keyName, int value)
{
WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture));
}

/// <summary>
/// Writes an <see cref="T:System.Single"/> value to the ini file.
/// </summary>
/// <param name="sectionName">The name of the section to write to .</param>
/// <param name="keyName">The name of the key to write to.</param>
/// <param name="value">The value to write</param>
/// <exception cref="T:System.ComponentModel.Win32Exception">
/// The write failed.
/// </exception>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> or <paramref name="keyName"/> are
/// a null reference (Nothing in VB)
/// </exception>
public void WriteValue(string sectionName, string keyName, float value)
{
WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture));
}

/// <summary>
/// Writes an <see cref="T:System.Double"/> value to the ini file.
/// </summary>
/// <param name="sectionName">The name of the section to write to .</param>
/// <param name="keyName">The name of the key to write to.</param>
/// <param name="value">The value to write</param>
/// <exception cref="T:System.ComponentModel.Win32Exception">
/// The write failed.
/// </exception>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> or <paramref name="keyName"/> are
/// a null reference (Nothing in VB)
/// </exception>
public void WriteValue(string sectionName, string keyName, double value)
{
WriteValue(sectionName, keyName, value.ToString(CultureInfo.InvariantCulture));
}

#endregion

#region Delete Methods

/// <summary>
/// Deletes the specified key from the specified section.
/// </summary>
/// <param name="sectionName">
/// Name of the section to remove the key from.
/// </param>
/// <param name="keyName">
/// Name of the key to remove.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> or <paramref name="keyName"/> are
/// a null reference (Nothing in VB)
/// </exception>
public void DeleteKey(string sectionName, string keyName)
{
if (sectionName == null)
throw new ArgumentNullException("sectionName");

if (keyName == null)
throw new ArgumentNullException("keyName");

WriteValueInternal(sectionName, keyName, null);
}

/// <summary>
/// Deletes a section from the ini file.
/// </summary>
/// <param name="sectionName">
/// Name of the section to delete.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="sectionName"/> is a null reference (Nothing in VB)
/// </exception>
public void DeleteSection(string sectionName)
{
if (sectionName == null)
throw new ArgumentNullException("sectionName");

WriteValueInternal(sectionName, null, null);
}

#endregion
}

IniFileHelp

MSD_radix_sort

 

一、这次是在上一次尝试基础上进行的,预期是达到上次性能的9倍。

MSD的基本手法就是不断切片。
每一步都是把整体数据切割成256片,如上图所示,实际情况切片未必均匀,有的slice内可能一个元素也没有。

接下来对于每个切片怎么办呢?
答案是继续切,对于特殊数据来讲,切片过程可以很快结束,这样就可以实现比LSD更快的速度。

这里面最困难的地方就是如何存储每个slice的头和尾。
如果采用下述方式,应该是行不通的。
这个方式需要做数组元素插入,还要跟踪中间数据,因此没具体考虑。

我真正采用的是下表:


表中第一项表示第一个元素开启一个类别,紧跟的0表示此元素和上面的1是同一类。
至于2表明在切片过程中是一个孤立的元素,后续就没必要再切片了。
这个方式可以大大简化编码。

二、伪代码。

for each slice
if slice-tag == 2 continue;
if slice-tag == 1
slice it;
update bookkeeping
int main(){
HANDLE heap = NULL;
Bucket bucket[BUCKETSLOTCOUNT];
PageList * pageListPool;
int plpAvailable = 0;
int * pages = NULL;
int * pagesAvailable = NULL;
int * objIdx;
unsigned short * s;
__int8 * classifier = NULL; time_t timeBegin;
time_t timeEnd; heap = HeapCreate(HEAP_NO_SERIALIZE|HEAP_GENERATE_EXCEPTIONS, 1024*1024, 0);
if (heap != NULL){
pages = (int * )HeapAlloc(heap, 0, (TFSI/PAGEGRANULAR + BUCKETSLOTCOUNT + 8) * PAGEAMOUNT);
pageListPool = (PageList *)HeapAlloc(heap, 0, (TFSI/PAGEGRANULAR + 8) * sizeof(PageList));
s = (unsigned short *)HeapAlloc(heap, 0, TFSI*sizeof(unsigned short));
objIdx = (int *)HeapAlloc(heap, 0, TFSI * sizeof(int));
classifier = (__int8 *)HeapAlloc(heap, 0, (TFSI+8)*sizeof(__int8));
}
MakeSure(pages != NULL && pageListPool != NULL && objIdx != NULL && classifier != NULL); for(int i=0; i<TFSI; i++) objIdx[i]=i;
timeBegin = clock();
for (int i=0; i<TFSI; i++) s[i] = rand();
timeEnd = clock();
printf("\n%f(s) consumed in generating numbers", (double)(timeEnd-timeBegin)/CLOCKS_PER_SEC); SecureZeroMemory(classifier, TFSI*sizeof(__int8));
classifier[0] = 1;
classifier[TFSI] = 1; timeBegin = clock(); bool no_need_further_processing = false;
for (int t=sizeof(short)-1; t>=0; t--){
int bucketIdx;
int slice_pointer = 0;
int slice_base = 0;
int flagCounter = 0; if (no_need_further_processing) break; //classifier: 1 new catagory
//classifier: 2 completed catagory process
while (slice_pointer < TFSI){
if (classifier[slice_pointer] == 2){
slice_base = slice_pointer;
classifier[slice_base] = 0;
while (classifier[slice_pointer] == 0){
slice_pointer++;
flagCounter++;
}
classifier[slice_base] = 2; if (flagCounter == TFSI) no_need_further_processing = true;
continue;
} if (classifier[slice_pointer] == 1){
FillMemory(pages, (TFSI/PAGEGRANULAR + BUCKETSLOTCOUNT + 8) * PAGEAMOUNT, 0xff);
SecureZeroMemory(pageListPool, (TFSI/PAGEGRANULAR + 8) * sizeof(PageList));
pagesAvailable = pages;
plpAvailable = 0; for(int i=0; i<256; i++){
bucket[i].currentPagePtr = pagesAvailable;
bucket[i].offset = 0;
bucket[i].pl.PagePtr = pagesAvailable;
bucket[i].pl.next = NULL;
pagesAvailable += PAGEGRANULAR;
bucket[i].currentPageListItem = &(bucket[i].pl);
} slice_base = slice_pointer;
classifier[slice_base] = 0;
while (classifier[slice_pointer] == 0){
//for each slice element, push_back to pages;
unsigned char * cell = (unsigned char *)&s[objIdx[slice_pointer]];
bucketIdx = cell[t];
//save(bucketIdx, objIdx[i]);
bucket[bucketIdx].currentPagePtr[ bucket[bucketIdx].offset ] = objIdx[slice_pointer];
bucket[bucketIdx].offset++;
if (bucket[bucketIdx].offset == PAGEGRANULAR){
bucket[bucketIdx].currentPageListItem->next = &pageListPool[plpAvailable];
plpAvailable++;
bucket[bucketIdx].currentPageListItem->next->PagePtr = pagesAvailable;
bucket[bucketIdx].currentPageListItem->next->next = NULL; bucket[bucketIdx].currentPagePtr = pagesAvailable;
bucket[bucketIdx].offset = 0;
pagesAvailable += PAGEGRANULAR; bucket[bucketIdx].currentPageListItem = bucket[bucketIdx].currentPageListItem->next;
} slice_pointer++;
}
classifier[slice_base] = 1; //update classifier;
//update objIdx index
int start = slice_base;
for (int i=0; i<256; i++){
PageList * p;
p = &(bucket[i].pl);
//classifier: 1 new catagory
//classifier: 2 complete catagory process
classifier[start] = 1; int counters = 0;
while (p){
for (int t=0; t<PAGEGRANULAR; t++){
int idx = p->PagePtr[t];
if (idx != TERMINATOR){
objIdx[start] = idx;
start++;
counters++;
}
if (idx == TERMINATOR) break;
}
p = p->next;
}
if (counters == 1) classifier[start-1] = 2;
}
//update objIdx index
} //if (classifier[slice_pointer] == 1)
} //while (slice_pointer < TFSI)
} //for (int t=sizeof(short)-1; t>=0; t--) timeEnd = clock();
printf("\n%f(s) consumed in generating results", (double)(timeEnd-timeBegin)/CLOCKS_PER_SEC); //for(int i=0; i<TFSI; i++) printf("%d\n", s[objIdx[i]]); HeapFree(heap, 0, pages);
HeapFree(heap, 0, pageListPool);
HeapFree(heap, 0, s);
HeapFree(heap, 0, objIdx);
HeapFree(heap, 0, classifier);
HeapDestroy(heap); return 0;
}

三、测试

1024*1024*100 个短整型。

时间  5.438s

看到这里就知道杯具了,比LSD还慢。

如果应用到二维表,会更惨不忍睹。试了下果然如此。

四、讨论

如果哪位有更好的方法,欢迎讨论。

或者,基数排序只是一个花瓶?

 
 
分类: C/C++

读写ini文件的更多相关文章

  1. c# 利用动态库DllImport("kernel32")读写ini文件(提供Dmo下载)

    c# 利用动态库DllImport("kernel32")读写ini文件 自从读了设计模式,真的会改变一个程序员的习惯.我觉得嘛,经验也可以从一个人的习惯看得出来,看他的代码编写习 ...

  2. VB读写INI文件的四个函数以及相关API详细说明

    WritePrivateProfileString函数说明  来源:http://blog.csdn.net/wjb9921/article/details/2005000 在我们写的程序当中,总有一 ...

  3. C# 读写INI 文件

    INI 格式: [Section1] KeyWord1 = Value1 KeyWord2 = Value2 ... [Section2] KeyWord3 = Value3 KeyWord4 = V ...

  4. WIN32读写INI文件方法

      在程序中经常要用到设置或者其他少量数据的存盘,以便程序在下一次执行的时候可以使用,比如说保存本次程序执行时窗口的位置.大小.一些用户设置的 数据等等,在 Dos 下编程的时候,我们一般自己产生一个 ...

  5. 在 WinCe 平台读写 ini 文件

    在上篇文章开发 windows mobile 上的今日插件时,我发现 wince 平台上不支持例如 GetPrivateProfileString 等相关 API 函数.在网络上我并没有找到令我满意的 ...

  6. Windows中读写ini文件

    .ini 文件是Initialization File的缩写,即初始化文件,是windows的系统配置文件所采用的存储格式,来配置应用软件以实现不同用户的要求.配置文件有很多种如ini配置文件,XML ...

  7. C#中读写INI文件

    C#中读写INI文件 c#的类没有直接提供对ini文件的操作支持,可以自己包装win api的WritePrivateProfileString和GetPrivateProfileString函数实现 ...

  8. Qt读写ini文件

    一 背景 1 ini文件介绍 .ini 文件是Initialization File的缩写,即初始化文件. 除了windows现在很多其他操作系统下面的应用软件也有.ini文件,用来配置应用软件以实现 ...

  9. 【python-ini】python读写ini文件

    [python-ini]python读写ini文件 本文实例讲述了Python读写ini文件的方法.分享给大家供大家参考.具体如下: 比如有一个文件update.ini,里面有这些内容:   1 2 ...

随机推荐

  1. JS扩展 或 Jquery的扩展写法

    <script>//JS扩展String函数test,其它类推String.prototype.test = function(s){ alert(this+s);}var str = ' ...

  2. 经验28--相关时间戳,C#

    时间戳通常用于设置独特性质,保存图片之类的,到文件名后添加. 时间戳一般17地点. 1.获取的当前时间的时间戳. DateTime dtStart = TimeZone.CurrentTimeZone ...

  3. spring data jpa使用懒操作

    如果model对象的某属性使用lazy load,调用这个属性时会报错, failed to lazily initialize a collection of role could not init ...

  4. CSharp设计模式读书笔记(21):状态模式(学习难度:★★★☆☆,使用频率:★★★☆☆)

    模式角色与结构: 示例代码:(本示例在具体状态类中实现状态切换,也可以在环境类中实现状态切换.状态模式一定程度上违背开闭原则) using System; using System.Collectio ...

  5. 解决tomcat占用8080端口

    怎么解决tomcat占用8080端口问题图文教程           怎么解决tomcat占用8080端口问题 相信很多朋友都遇到过这样的问题吧,tomcat死机了,重启eclipse之后,发现 Se ...

  6. RPC和RMI的区别(Difference Between RPC and RMI)

    RPC和RMI的区别(Difference Between RPC and RMI) RPC vs RMI RPC (Remote Procedure Call) and RMI (Remote Me ...

  7. Java数据库编程、XML解析技术

    数据库编程 JDBC概述 是Java Database Connecive,即数据库连接技术的简称,它提供了连接各种常用数据库的能力. 是一种用于执行SQL语句的Java API,可以为多种关系数据库 ...

  8. FTP下载帮助类

    using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Net ...

  9. SQL语句分享[不定期更新]

    查询临时表 if object_id('')>0 查询表中的数据 select 'insert into ta1(col1,col2,col3) values('''+ltrim(列1)+''' ...

  10. jQuery多文件

    jQuery多文件下载 文件下载是一个Web中非常常用的功能,不过你是做内部管理系统还是做面向公众的互联网公司都会遇到这个问题,对于下载一般有点实际开发经验的都会自己解决,上周弄了一下多文件下载,业务 ...