/* * Copyright (c) 2002-2003, William Denniss * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the Tank Software nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package net.jtank.io; import java.util.*; import java.io.*; /** *

Ini reading package that can read the common Ini file format. * The Ini file format is a text format which is divided into sections * and attributes. Each section can have many attributes however they must * have unique names, likewise an Ini can have many * sections but they too must have unique names. In situtations were a list * is needed, using the multiline attribute (see below) or a different file * format such as XML is recommended.

* * The ini file looks like this: *
 * [ASection]
 * attributevalue=false
 * list=Number2
 * text={
 * Some random text
 * }
 * 
 * [AnotherSection]
 * morevalues=yes
 *
 * 
* * @author William Denniss * @version 2.3, 12th October 2003 */ public class Ini { private String iniName =""; private Map sections = new HashMap(); /** * Creates an empty Ini. */ public Ini () { } /** * Creates an empty Ini file with a recorded iniName. * Note this doesn't load any data from that iniName. * * @see #readIni(BufferedReader) */ public Ini (String iniName) { this.iniName = iniName; } /** * Returns the subsection with the given title * * @param title The name of the subsection to retrieve. * @return The subsection with the passed title */ public IniSection getSection (String title) { return (IniSection) sections.get(title); } /** * Adds a section to an Ini file. */ public void addSection (IniSection iniSub) { sections.put(iniSub.getTitle(), iniSub); } /** * Gets the name of this Ini. * * @return the name of this ini. */ public String getName () { return iniName; } /** * Sets the name of this Ini * * @param iniName the new name of this Ini */ public void setName (String iniName) { this.iniName = iniName; } /** * Helper to set an attribute. One can also do this by using getSection(String name) and * setAttribute. If no section exits a new one will be created. * * @param section The name of the subsection. * @param key The attribute key * @param value the value to set the key. */ public void setSectionAttribute (String section, String key, String value) { IniSection sub = getSection(section); if (sub == null) { sub = new IniSection(section); addSection(sub); } sub.setAttribute(key, value); } /** * Helper to get an attribute value. One can also do this with getSection and getAttribute. * * @param section The name of the section * @param key The name of the attribute key * @return The value of the given attribute or null if the attribute or section doesn't exist */ public String getSectionAttribute (String section, String key) { IniSection sub = getSection(section); if (sub == null) return null; return sub.getAttribute(key); } /** * Like getSectionAttribute except that instead of returning null if the section or * attribute does not exist, it returns the default and casts the value as a boolean. * * @param section The name of the section * @param key The name of the attribute key * @param def The default value for this attribute * @return the boolean value of the given attribute */ public boolean getSectionAttributeBool (String section, String key, boolean def) { IniSection sub = getSection(section); if (sub == null) return def; return sub.getAttribute(key, def+"").equalsIgnoreCase("yes") || sub.getAttribute(key, def+"").equalsIgnoreCase("true"); } /** * Like getSectionAttribute except that instead of returning null if the section or * attribute does not exist, it returns the default. * * @param section The name of the section * @param key The name of the attribute key * @param def The default value for this attribute * @return the String value of the given attribute */ public String getSectionAttributeStr (String section, String key, String def) { IniSection sub = getSection(section); if (sub == null) return def; return sub.getAttribute(key, def); } /** * Like getSectionAttribute except that instead of returning null if the section or * attribute does not exist (or is not a valid number), it returns the default and casts the value as an int. * * @param section The name of the section * @param key The name of the attribute key * @param def The default value for this attribute * @return the int value of the given attribute */ public int getSectionAttributeInt (String section, String key, int def) { IniSection sub = getSection(section); if (sub == null) return def; try { int toReturn = Integer.parseInt(sub.getAttribute(key, def+"")); return toReturn; } catch (NumberFormatException e) { return def; } } /** * String representation of the Ini file. Used mainly for debugging. * * @return String representation of the Ini file. */ public String toString () { String toReturn = ""; Object [] values = sections.keySet().toArray(); for (int i = 0; i < values.length; i++) { toReturn += getSection((String) values[i]).toString() + "\n"; } return toReturn; } /** * Writes the contents of the INI file to the given Writer. * The Writer can be anything from a BufferedWriter, FileWriter, * StringWriter etc. */ public void writeIni (Writer w) throws IOException { w.write(toString()); w.close(); } /** * Parses the data from the Reader into this Ini file. Typically * The BufferedReader would be connected to a file, string * or URL. * * @param br The source of the data. */ public void readIni (BufferedReader br) throws IOException { String line = ""; line = br.readLine(); IniSection csub = null; String currentComment = ""; while (line != null) { if (line.length() > 0) { // Creates a new section if found if (line.charAt(0) == '[') { csub = new IniSection(line.substring(1, line.lastIndexOf("]"))); csub.setComment(currentComment); addSection(csub); currentComment = ""; } else { // Ignores comments if (line.charAt(0) == ';' || line.charAt(0) == '#') { currentComment += line + "\n"; // Reads the key/value pair } else { // extracts the key value parts String pKey = line.substring(0, line.indexOf("=")); String pValue = line.substring(line.indexOf("=")+1); // Extracts the value, catering for the multi-line {} attribute if (pValue.length() > 0) { if (pValue.charAt(0) == '{') { line = br.readLine(); pValue = ""; boolean end = false; if (line.length() != 0) { end = line.charAt(0) == '}'; } while (!end) { if (!pValue.equals("")) pValue += "\n"; pValue += line; line = br.readLine(); if (line.length() != 0) { end = line.charAt(0) == '}'; } } } } // Adds the attribute to the current section csub.setAttribute(pKey, pValue, currentComment); currentComment = ""; } } } else { currentComment += "\n"; } // reads the next line line = br.readLine(); } } }