Page 1 of 1

Reading and Writing INI files

Posted: Thu Jun 22, 2006 9:23 am
by Maugrim_The_Reaper
I started work a few days back on a Settings class group for a project (another developer requested it to do some work on a separate area that required working with Settings). Anyways, the structure is simple enough as are the classes. My main question relates to the INI format which I've never worked with much in the past.

Are there any special special requirements to working with INI files other than the basics? What sort of data are INI files good and bad at storing? The current class seems to work okay for the moment, but my knowledge of INI syntax quirks is non existent.

Code: Select all

abstract class Parth_Settings {

	protected $settings = array();

	protected function __construct() {}

	public function get($var) {
		$pieces = explode('.', $var);
		switch(count($pieces))
		{
			case 2:
				return $this->settings[$pieces[0]][$pieces[1]];
				break;
			case 1:
				return $this->settings[$pieces[0]];
				break;
			default:
				return null;
		}
	}

	public function set($var, $value) {
		$pieces = explode('.', $var);
		switch(count($pieces))
		{
			case 2:
				$this->settings[$pieces[0]][$pieces[1]] = $value;
				break;
			case 1:
				$this->settings[$pieces[0]] = $value;
				break;
		}
	}

	public abstract function import($data);

	public abstract function export();

	protected function define_phpeol() {
		if (!defined('PHP_EOL'))
		{
			switch (strtoupper(substr(PHP_OS, 0, 3)))
				{
				case 'WIN':
					define('PHP_EOL', "\r\n"); // Windows
					break;
				case 'DAR':
					define('PHP_EOL', "\r"); // Mac OS
					break;
				default:
					define('PHP_EOL', "\n"); // *nix
			}
		}
	}

}

class Parth_INISettings extends Parth_Settings  {

	public function __construct() {}

	public function import($file) {
		if(!file_exists($file))
		{
			return false;
		}
		$this->settings = parse_ini_file($file, true);
	}

	public function export() {
		$this->define_phpeol();
		$ini_nosections = '';
		$ini_sections = '';
		foreach ($this->settings as $key=>$elem)
		{
			if(is_array($elem))
			{
				$ini_sections .= PHP_EOL . PHP_EOL . "[" . $key . "]" . PHP_EOL;
				foreach($elem as $name=>$value)
				{
					$ini_sections .= PHP_EOL . $name . ' = ' . $value;
				}
			}
			else
			{
				$ini_nosections .= PHP_EOL . $key . ' = ' . $elem;
			}
		}
		$file_content = $ini_nosections . $ini_sections;
		return $file_content;
	}

}
Unit Tests:

settings.ini

Code: Select all

; Sample INI file for Unit Testing of Parth_INISettings class

; name has no section [], added to settings array directly

name = partholan
type = framework

; app is a section, and forms a new sub array of settings array

[app]
type = library

Code: Select all

class Test_INIArraySettings extends UnitTestCase {

	private $inifile;

	public function __construct() {
		$this->UnitTestCase('INISettings Test');
		$this->inifile = TESTROOT . 'Other/settings.ini';
	}

	public function testBasics() {
		$settings = new Parth_INISettings();
		$settings->import($this->inifile);
		$this->assertEqual($settings->get('name'), 'partholan');
		$this->assertEqual($settings->get('app.type'), 'library');
		$settings->set('app.author', 'me');
		$settings->set('user', 'meagain');
		$this->assertEqual($settings->get('app.author'), 'me');
		$this->assertEqual($settings->get('user'), 'meagain');
		$export = $settings->export();
		$this->assertEqual(implode('', explode(PHP_EOL, $export)), $this->expectedExport());
	}

	// expected export file contents with all newlines removed
	private function expectedExport() {
		$ini = "name = partholantype = frameworkuser = meagain[app]type = libraryauthor = me";
		return $ini;
	}

}

Posted: Thu Jun 22, 2006 10:43 am
by alex.barylski
Incase you haven't looked at it yet :)

http://en.wikipedia.org/wiki/INI_file

Posted: Thu Jun 22, 2006 3:27 pm
by johno

Posted: Thu Jun 22, 2006 3:54 pm
by Maugrim_The_Reaper
[quote=Maugrim_The_Reaper]

Code: Select all

public function import($file) {
                if(!file_exists($file))
                {
                        return false;
                }
                $this->settings = parse_ini_file($file, true);
        }
[/quote]

Got the PHP function ;)

I was just uncertain about the syntax supported by INI, and couldn't find a specification anywhere. Seems it's just informal (kind of odd). Hockey's link to Wikipedia had two unofficial specs, so I'm looking at those instead.

Posted: Thu Jun 22, 2006 5:49 pm
by alex.barylski
Seems it's just informal (kind of odd)
Yea...it's alot like CSV...but considering the age of the file formats...it should come at no surprise...

I have bad memories of tinkering with INI files and not being able to get anything working after that...and having to reinstall :?

Unlike XML, CSV and INI were introduced at a time when cross platform wasn't really an issue and standards weren't a big deal...

Also, XML was invented for a reason, whereas I would bet that CSV and INI were just kind of adhoc hacks...

Stranger things have happened :P

Cheers :)

Posted: Thu Jun 22, 2006 5:54 pm
by timvw
A couple of years ago i read 'The art of Unix Programming'...

The following section talks about a couple of alternatives: http://www.catb.org/esr/writings/taoup/ ... 05s02.html

Posted: Fri Jun 23, 2006 2:37 am
by Maugrim_The_Reaper
Thanks to everyone who helped create XML :).