Работа с ini на C#


Наверно это не самый лучший стиль программирования, но настройки большинства своих программ я привык хранить в их теле. Или вообще делать их неизменяемыми – так как изначально затачивать под конкретного человека. Но вот в одном заказе (программа для приема в печать для одной фотостудии) клиент попросил вынести настройки приложения в отдельный файл – ini. Ну что ж, раз надо – сделаем.



На самом деле я был несколько удивлен, не найдя готовых решений, уже встроенных в .NET. Оказывается, макрософт вообще не рекмоендует ини файлы, а вместо этого предлагает использовать реестр или xml. Но нам наплевать на рекомендации майкрософта, нам главное – удовлетворить заказчика. Итак, пишем свой код для работы с ini-файлами. Работать будет от XP и до Window 10:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;

namespace Foto
{
    class IniFiles
    {

         string Path; //Имя файла.

        [DllImport("kernel32", CharSet = CharSet.Auto)] // Подключаем kernel32.dll и описываем его функцию WritePrivateProfilesString
        static extern long WritePrivateProfileString(string Section, string Key, string Value, string FilePath);

        [DllImport("kernel32", CharSet = CharSet.Auto)] // Еще раз подключаем kernel32.dll, а теперь описываем функцию GetPrivateProfileString
        static extern int GetPrivateProfileString(string Section, string Key, string Default, StringBuilder RetVal, int Size, string FilePath);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        static extern uint GetPrivateProfileSection(string lpAppName, IntPtr lpReturnedString, uint nSize, string lpFileName);
        // С помощью конструктора записываем пусть до файла и его имя.
        public IniFiles(string IniPath)
        {
            Path = new FileInfo(IniPath).FullName.ToString();
        }

        //Читаем ini-файл и возвращаем значение указного ключа из заданной секции.
        public string ReadINI(string Section, string Key)
        {
            var RetVal = new StringBuilder(255);
            GetPrivateProfileString(Section, Key, "", RetVal, 255, Path);
            return RetVal.ToString();
        }
        //Записываем в ini-файл. Запись происходит в выбранную секцию в выбранный ключ.
        public void Write(string Section, string Key, string Value)
        {
            WritePrivateProfileString(Section, Key, Value, Path);
        }

        //Удаляем ключ из выбранной секции.
        public void DeleteKey(string Key, string Section = null)
        {
            Write(Section, Key, null);
        }
        //Удаляем выбранную секцию
        public void DeleteSection(string Section = null)
        {
            Write(Section, null, null);
        }
        //Проверяем, есть ли такой ключ, в этой секции
        public bool KeyExists(string Section, string Key)
        {
            return ReadINI(Section, Key).Length > 0;
        }

        //читаем в массив все пары ключей-значнией в данной секции
       public bool GetPrivateProfileSection(string appName, string fileName, out string[] section)
        {
            section = null;

            if (!System.IO.File.Exists(fileName))
                return false;

            const uint MAX_BUFFER = 32767;

            IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER * sizeof(char));

            uint bytesReturned = GetPrivateProfileSection(appName, pReturnedString, MAX_BUFFER, fileName);

            if ((bytesReturned == MAX_BUFFER - 2) || (bytesReturned == 0))
            {
                Marshal.FreeCoTaskMem(pReturnedString);
                return false;
            }
            string returnedString = Marshal.PtrToStringAuto(pReturnedString, (int)(bytesReturned - 1));

            section = returnedString.Split('\0');

            Marshal.FreeCoTaskMem(pReturnedString);
            return true;
        }
    }
    }
	
Работать со всем этим проще простого. Например, прочитать значение (размер шрифта):

IniFiles INI = new IniFiles("config.ini");
font_raz = Convert.ToInt32(INI.ReadINI("Общие настройки", "Шрифт"));
Узнать, сколько значений в секции:

string file = Path.GetFullPath("config.ini");
string section = "Типы бумаги";
if (INI.GetPrivateProfileSection(section, file, out bumag))
{
MessageBox.Show(bumag.Length.ToString());
}
Структура файла у нас такая:



Стоит обратить внимание на кодировки программы и файла ini – в случае несовпадения могут быть проблемы с кириллицей. Ну а у нас проблем нет:

Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, си шарп, ini, хранение настроек программы




Отправляя сообщение я подтверждаю, что ознакомлен и согласен с политикой конфиденциальности данного сайта.




Алгоритм Евклида на C#
Две семьи
Функциональное программирование