分享
 
 
 

一个自写的XML读写/存取属性的Java工具类库

王朝java/jsp·作者佚名  2006-01-10
窄屏简体版  字體: |||超大  

Java 5中的Properties类现在可以使用XML存取,通过loadFromXML和storeToXML方法实现。假设有下面这个属性表:

windowSize: 400,400

windowLocation: 456,300

使用storeToXML后会得到这样的XML文件

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

<properties>

<comment>Comment</comment>

<entry key="windowLocation">400,400</entry>

<entry key="windowSize">456,300</entry>

</properties>

但是如果要获得更具层次感的属性文件,可以使用这里我写的一个Utility。它建立在一个读取和存储XML的类库上。这个类库采集于Columba Project的util包,并有所修改。

首先是XmlElement,用于表示XML文件里的一个entry

/*

* @(#)XmlElement.java

* Created on 2005-8-12

*/

package com.allenstudio.ir.util;

import java.util.Enumeration;

import java.util.Hashtable;

import java.util.Iterator;

import java.util.List;

import java.util.Observable;

import java.util.Vector;

/**

* The XmlElement is a generic containment class for elements within an XML

* file.

* <p>

*

* It extends Observable which should be used for gui elements which are

* interested in configuration changes.

* <p>

*

* Show interested in:

*

* <pre>

* xmlElement.addObserver(yourObserver);

* </pre>

*

* <p>

* When making bigger changes on XmlElement and probably its subnodes and/or a

* greater number of attributes at once, you should just change XmlElement

* directly and manually notify the Observers by calling:

* <p>

*

* <pre>

* xmlElement.setChanged();

* xmlElement.notifyObservers();

* </pre>

*

* <p>

* There a good introduction for the Observable/Observer pattern in

* Model/View/Controller based applications at www.javaworld.com: -

* {@link http://www.javaworld.com/javaworld/jw-10-1996/jw-10-howto.html}

*

* @author fdietz

*/

public class XmlElement extends Observable implements Cloneable {

String name;

String data;

Hashtable<String, String> attributes;

List<XmlElement> subElements;

XmlElement parent;

/**

*

*

* Constructor

*

*/

public XmlElement() {

subElements = new Vector<XmlElement>();

this.attributes = new Hashtable<String, String>(10);

}

/**

* **

*

* Constructor

*

* @param String

* Name

*

*/

public XmlElement(String name) {

this.name = name;

this.attributes = new Hashtable<String, String>(10);

subElements = new Vector<XmlElement>();

data = "";

}

/**

* **

*

* Constructor

*

* @param String

* Name

* @param Hashtable

* Attributes

*

*/

public XmlElement(String name, Hashtable<String, String> attributes) {

this.name = name;

this.attributes = attributes;

subElements = new Vector<XmlElement>();

}

/**

* **

*

* Constructor

*

* @param Name

* String

* @param Data

* String

*

*/

public XmlElement(String name, String data) {

this.name = name;

this.data = data;

subElements = new Vector<XmlElement>();

this.attributes = new Hashtable<String, String>(10);

}

/**

* Add attribute to this xml element.

*

* @param name

* name of key

* @param value

* new attribute value

* @return old attribute value

*

*/

public Object addAttribute(String name, String value) {

if ((value != null) && (name != null)) {

Object returnValue = attributes.put(name, value);

return returnValue;

}

return null;

}

/**

* **

*

* @return String

* @param String

* Name

*

*/

public String getAttribute(String name) {

return ((String) attributes.get(name));

}

public String getAttribute(String name, String defaultValue) {

if (getAttribute(name) == null) {

addAttribute(name, defaultValue);

}

return getAttribute(name);

}

/**

* **

*

* @return String

* @param String

* Name

*

*/

public Hashtable<String, String> getAttributes() {

return attributes;

}

/**

* **

*

*

* @param Attrs

* Hashtable to use as the attributes

*

*/

public void setAttributes(Hashtable<String, String> attrs) {

attributes = attrs;

}

/**

* **

*

* @return Enumeration

*

*/

public Enumeration getAttributeNames() {

return (attributes.keys());

}

/**

* **

*

* @return boolean

* @param XmlElement

* E

*

*/

public boolean addElement(XmlElement e) {

e.setParent(this);

return (subElements.add(e));

}

public XmlElement removeElement(XmlElement e) {

XmlElement child = null;

for (int i = 0; i < subElements.size(); i++) {

child = (XmlElement) subElements.get(i);

// FIXME -- This will most likely not work.

// You want the element removed if the contents are the same

// Not just if the element reference is the same.

if (child == e) {

subElements.remove(i);

}

}

return (child);

}

public XmlElement removeElement(int index) {

return (XmlElement) subElements.remove(index);

}

public void removeAllElements() {

subElements.clear();

}

/**

* convienience method for the TreeView

*

* this method is modeled after the DefaultMutableTreeNode-class

*

* DefaultMutableTreeNode wraps XmlElement for this purpose

*

*/

public void removeFromParent() {

if (parent == null) {

return;

}

parent.removeElement(this);

parent = null;

}

public void append(XmlElement e) {

e.removeFromParent();

addElement(e);

}

/**

*

* convienience method for the TreeView

*

* @param e

* @param index

*/

public void insertElement(XmlElement e, int index) {

e.removeFromParent();

subElements.add(index, e);

e.setParent(this);

}

/**

* **

*

* @return Vector

*

*/

public List getElements() {

return subElements;

}

public int count() {

return subElements.size();

}

/**

* Returns the element whose hierachy is indicated

* by <code>path</code>. The path is separated with

* periods(".").<br>

* <em>Note: if one node has more than one elements

* that have the same name, that is, if its subnodes

* have the same path, only the first one is returned.

* </em>

* @return the first element qualified with the path

* @param path the path string of the specified element

*/

public XmlElement getElement(String path) {

int i = path.indexOf('.');

String topName;

String subName;

if (i == 0) {

path = path.substring(1);

i = path.indexOf('.');

}

if (i > 0) {

topName = path.substring(0, i);

subName = path.substring(i + 1);

} else {

topName = path;

subName = null;

}

int j;

for (j = 0; j < subElements.size(); j++) {

if (((XmlElement) subElements.get(j)).getName().equals(topName)) {

if (subName != null) {

return (((XmlElement) subElements.get(j))

.getElement(subName));

} else {

return ((XmlElement) subElements.get(j));

}

}

}

return null;

}

public XmlElement getElement(int index) {

return (XmlElement) subElements.get(index);

}

/**

* Adds a sub element to this one. The path

* is separated with dots(".").

*

* @return the <code>XmlElement</code> added

* @param path The subpath of the sub element to add

*

*/

public XmlElement addSubElement(String path) {

XmlElement parent = this;

XmlElement child;

String name;

while (path.indexOf('.') != -1) {

name = path.substring(0, path.indexOf('.'));

path = path.substring(path.indexOf('.') + 1);

// if path startsWith "/" -> skip

if (name.length() == 0)

continue;

if (parent.getElement(name) != null) {

parent = parent.getElement(name);

} else {

child = new XmlElement(name);

parent.addElement(child);

parent = child;

}

}

child = new XmlElement(path);

parent.addElement(child);

return child;

}

/**

* Adds a sub element to this one

*

* @return XmlElement

* @param element

* The XmlElement to add

*

*/

public XmlElement addSubElement(XmlElement e) {

e.setParent(this);

subElements.add(e);

return e;

}

/**

* Adds a sub element to this one

*

* @return XmlElement

* @param Name

* The name of the sub element to add

* @param Data

* String Data for this element

*/

public XmlElement addSubElement(String name, String data) {

XmlElement e = new XmlElement(name);

e.setData(data);

e.setParent(this);

subElements.add(e);

return e;

}

/**

* Sets the parent element

*

* @param Parent

* The XmlElement that contains this one

*

*/

public void setParent(XmlElement parent) {

this.parent = parent;

}

/**

* Gives the XmlElement containing the current element

*

* @return XmlElement

*

*/

public XmlElement getParent() {

return parent;

}

/**

* Sets the data for this element

*

* @param D

* The String representation of the data

*

*/

public void setData(String d) {

data = d;

}

/**

* Returns the data associated with the current Xml element

*

* @return String

*

*/

public String getData() {

return data;

}

/**

* Returns the name of the current Xml element

*

* @return String

*

*/

public String getName() {

return name;

}

/**

* **

*

* @param out

* OutputStream to print the data to

*

*/

/*

* public void write(OutputStream out) throws IOException { PrintWriter PW =

* new PrintWriter(out); PW.println(" <?xml version=\"1.0\"

* encoding=\"UTF-8\"?>"); if (SubElements.size() > 0) { for (int i = 0; i <

* SubElements.size(); i++) { ((XmlElement)

* SubElements.get(i))._writeSubNode(PW, 4); } } PW.flush(); }

*/

/**

* Prints sub nodes to the given data stream

*

* @param out

* PrintWriter to use for printing

* @param indent

* Number of spaces to indent things

*

*/

/*

* private void _writeSubNode(PrintWriter out, int indent) throws

* IOException { _writeSpace(out, indent); out.print(" <" + Name); //if (

* Attributes.size()>1) out.print(" ");

*

* for (Enumeration e = Attributes.keys(); e.hasMoreElements();) { String K =

* (String) e.nextElement(); out.print(K + "=\"" + Attributes.get(K) + "\"

* b");

* } out.print(">");

*

* if (Data != null && !Data.equals("")) { if (Data.length() > 20) {

* out.println(""); _writeSpace(out, indent + 2); } out.print(Data); } if

* (SubElements.size() > 0) { out.println(""); for (int i = 0; i <

* SubElements.size(); i++) { ((XmlElement)

* SubElements.get(i))._writeSubNode( out, indent + 4); } _writeSpace(out,

* indent); } out.println(" </" + Name + ">");

* }

*/

/**

* Prints out a given number of spaces

*

* @param out

* PrintWriter to use for printing

* @param numSpaces

* Number of spaces to print

*

*/

/*

* private void _writeSpace(PrintWriter out, int numSpaces) throws

* IOException {

*

* for (int i = 0; i < numSpaces; i++) out.print(" "); }

*

* public static void printNode(XmlElement Node, String indent) { String

* Data = Node.getData(); if (Data == null || Data.equals("")) {

* System.out.println(indent + Node.getName()); } else {

* System.out.println(indent + Node.getName() + " = '" + Data + "'"); }

* Vector Subs = Node.getElements(); int i, j; for (i = 0; i < Subs.size();

* i++) { printNode((XmlElement) Subs.get(i), indent + " "); } }

*/

public static void printNode(XmlElement node, String indent) {

String data = node.getData();

if ((data == null) || data.equals("")) {

System.out.println(indent + node.getName());

} else {

System.out.println(indent + node.getName() + " = '" + data + "'");

}

// print attributes

for (Enumeration enumeration = node.getAttributes().keys(); enumeration

.hasMoreElements();) {

String key = (String) enumeration.nextElement();

String value = node.getAttribute(key);

System.out.println(indent + key + ":" + value);

}

List subs = node.getElements();

for (Iterator it = subs.iterator(); it.hasNext();) {

printNode((XmlElement) it.next(), indent + " ");

// for (i = 0; i < subs.size(); i++) {

// printNode((XmlElement) subs.get(i), indent + " ");

}

}

/** {@inheritDoc} */

@SuppressWarnings("unchecked")

@Override

public Object clone() {

try {

XmlElement clone = (XmlElement) super.clone(); // creates a shallow

// copy of this

// object

if (attributes != null) {

clone.setAttributes((Hashtable<String, String>) getAttributes().clone());

}

if (subElements != null) {

clone.subElements = new Vector();

List childs = getElements();

XmlElement child;

for (Iterator it = childs.iterator(); it.hasNext();) {

child = (XmlElement) it.next();

// for( int i=0; i<childs.size(); i++ ) {

// child = (XmlElement) childs.get(i);

clone.addSubElement((XmlElement) child.clone());

}

}

return clone;

} catch (CloneNotSupportedException cnse) {

throw new InternalError("Could not clone XmlElement: " + cnse);

}

}

/**

* Sets the name.

*

* @param name

* The name to set

*/

public void setName(String name) {

this.name = name;

}

/**

* Notify all Observers.

*

* @see java.util.Observable#notifyObservers()

*/

@Override

public void notifyObservers() {

setChanged();

super.notifyObservers();

}

/**

* Returns true if the specified objects are equal. They are equal if they

* are both null OR if the <code>equals()</code> method return true. (

* <code>obj1.equals(obj2)</code>).

*

* @param obj1

* first object to compare with.

* @param obj2

* second object to compare with.

* @return true if they represent the same object; false if one of them is

* null or the <code>equals()</code> method returns false.

*/

private boolean equals(Object obj1, Object obj2) {

boolean equal = false;

if ((obj1 == null) && (obj2 == null)) {

equal = true;

} else if ((obj1 != null) && (obj2 != null)) {

equal = obj1.equals(obj2);

}

return equal;

}

/** {@inheritDoc}

*Recursive comparison.

*/

@Override

public boolean equals(Object obj) {

boolean equal = false;

if ((obj != null) && (obj instanceof XmlElement)) {

XmlElement other = (XmlElement) obj;

if (equals(attributes, other.attributes)

&& equals(data, other.data) && equals(name, other.name)

&& equals(subElements, other.subElements)) {

equal = true;

}

}

return equal;

}

/** {@inheritDoc} */

@Override

public int hashCode() {

//Hashcode value should be buffered.

int hashCode = 23;

if (attributes != null) {

hashCode += (attributes.hashCode() * 13);

}

if (data != null) {

hashCode += (data.hashCode() * 17);

}

if (name != null) {

hashCode += (name.hashCode() * 29);

}

if (subElements != null) {

hashCode += (subElements.hashCode() * 57);

}

return hashCode;

}

}

然后是XmlIO,用于读写。

/*

* @(#)XmlIO.java

* Created on 2005-8-12

*/

package com.allenstudio.ir.util;

import java.io.BufferedWriter;

import java.io.CharArrayWriter;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.io.Writer;

import java.net.URL;

import java.util.Enumeration;

import java.util.Iterator;

import java.util.List;

import java.util.Vector;

import java.util.logging.Logger;

import javax.swing.JOptionPane;

import javax.xml.parsers.SAXParser;

import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.XMLReader;

import org.xml.sax.helpers.DefaultHandler;

/**

* XML IO reading and writing utility.

*

* @author fdietz

*/

public class XmlIO extends DefaultHandler {

private static final Logger LOG = Logger.getLogger("org.columba.core.xml");

private static final String ROOT_XML_ELEMENT_NAME = "__INSPIRENTO_XML_TREE_TOP__";

// List of sub-elements

@SuppressWarnings("unused")

private List<XmlElement> elements;

// Top level element (Used to hold everything else)

private XmlElement rootElement;

// The current element you are working on

private XmlElement currentElement;

// For writing out the data

// Indent for each level

private int writeIndent = 2;

// Maximum data to put on a "one liner"

private int maxOneLineData = 20;

// The SAX 2 parser...

@SuppressWarnings("unused")

private XMLReader xr;

// Buffer for collecting data from

// the "characters" SAX event.

private CharArrayWriter contents = new CharArrayWriter();

private URL url = null;

/*

// Default constructor

public XmlIO() {

}

*/

/*

// setup and load constructor

public XmlIO(String FilePath) {

currentElement = null;

}

*/

public XmlIO(URL url) {

super();

this.url = url;

}

// setup and load constructor

public XmlIO() {

currentElement = null;

}

// setup and load constructor

/**

* Creates a XmlIO object with the specified element at the top.

* @param element the element at the top.

*/

public XmlIO(XmlElement element) {

rootElement = new XmlElement(ROOT_XML_ELEMENT_NAME);

rootElement.addElement(element);

}

public void setURL(URL url) {

this.url = url;

}

public boolean load() {

//this.file = F;

return load(url);

}

// Load a file. This is what starts things off.

/**

* Loads from the InputStream into the root Xml Element.

* @param input the input stream to load from.

*/

public boolean load(InputStream input) {

elements = new Vector<XmlElement>();

rootElement = new XmlElement(ROOT_XML_ELEMENT_NAME);

currentElement = rootElement;

try {

// Create the XML reader...

// xr = XMLReaderFactory.createXMLReader();

SAXParserFactory factory = SAXParserFactory.newInstance();

// Set the ContentHandler...

// xr.setContentHandler( this );

SAXParser saxParser = factory.newSAXParser();

saxParser.parse(input, this);

} catch (javax.xml.parsers.ParserConfigurationException ex) {

LOG.severe("XML config error while attempting to read from the input stream \n'" + input + "'");

LOG.severe(ex.toString());

ex.printStackTrace();

return (false);

} catch (SAXException ex) {

// Error

LOG.severe("XML parse error while attempting to read from the input stream \n'" + input + "'");

LOG.severe(ex.toString());

ex.printStackTrace();

return (false);

} catch (IOException ex) {

LOG.severe("I/O error while attempting to read from the input stream \n'" + input + "'");

LOG.severe(ex.toString());

ex.printStackTrace();

return (false);

}

//XmlElement.printNode( getRoot(), "");

return (true);

}

/**

* Load a file. This is what starts things off.

* @param inputURL the URL to load XML from.

*/

public boolean load(URL inputURL) {

elements = new Vector<XmlElement>();

rootElement = new XmlElement(ROOT_XML_ELEMENT_NAME);

currentElement = rootElement;

try {

// Create the XML reader...

// xr = XMLReaderFactory.createXMLReader();

SAXParserFactory factory = SAXParserFactory.newInstance();

// Set the ContentHandler...

// xr.setContentHandler( this );

SAXParser saxParser = factory.newSAXParser();

saxParser.parse(inputURL.toString(), this);

} catch (javax.xml.parsers.ParserConfigurationException ex) {

LOG.severe("XML config error while attempting to read XML file \n'" + inputURL + "'");

LOG.severe(ex.toString());

ex.printStackTrace();

return (false);

} catch (SAXException ex) {

// Error

LOG.severe("XML parse error while attempting to read XML file \n'" + inputURL + "'");

LOG.severe(ex.toString());

ex.printStackTrace();

return (false);

} catch (IOException ex) {

LOG.severe("I/O error while attempting to read XML file \n'" + inputURL + "'");

LOG.severe(ex.toString());

ex.printStackTrace();

return (false);

}

//XmlElement.printNode( getRoot(), "");

return (true);

}

// Implement the content hander methods that

// will delegate SAX events to the tag tracker network.

@Override

public void startElement(String namespaceURI, String localName,

String qName, Attributes attrs) throws SAXException {

// Resetting contents buffer.

// Assuming that tags either tag content or children, not both.

// This is usually the case with XML that is representing

// data strucutures in a programming language independant way.

// This assumption is not typically valid where XML is being

// used in the classical text mark up style where tagging

// is used to style content and several styles may overlap

// at once.

try {

contents.reset();

String name = localName; // element name

if (name.equals("")) {

name = qName; // namespaceAware = false

}

XmlElement p = currentElement;

currentElement = currentElement.addSubElement(name);

currentElement.setParent(p);

if (attrs != null) {

for (int i = 0; i < attrs.getLength(); i++) {

String aName = attrs.getLocalName(i); // Attr name

if (aName.equals("")) {

aName = attrs.getQName(i);

}

currentElement.addAttribute(aName, attrs.getValue(i));

}

}

} catch (java.lang.NullPointerException ex) {

LOG.severe("Null!!!");

LOG.severe(ex.toString());

ex.printStackTrace();

}

}

@Override

public void endElement(String namespaceURI, String localName, String qName)

throws SAXException {

currentElement.setData(contents.toString().trim());

contents.reset();

currentElement = currentElement.getParent();

}

@Override

public void characters(char[] ch, int start, int length)

throws SAXException {

// accumulate the contents into a buffer.

contents.write(ch, start, length);

}

/**

* Returns the root for the XmlElement hiearchy.

* Note that this Xml Element will always have the name <code>__COLUMBA_XML_TREE_TOP__</code>.

* <p>

* Methods that want to retrieve elements from this root should use

* the {@link XmlElement#getElement(String)} in order to get the wanted

* element.

* @return a XmlElement if it has been loaded or initialized with it; null otherwise.

*/

public XmlElement getRoot() {

return (rootElement);

}

public void errorDialog(String Msg) {

JOptionPane.showMessageDialog(null, "Error: " + Msg);

}

public void warningDialog(String Msg) {

JOptionPane.showMessageDialog(null, "Warning: " + Msg);

}

public void infoDialog(String Msg) {

JOptionPane.showMessageDialog(null, "Info: " + Msg);

}

public void save() throws Exception {

write(new FileOutputStream(url.getPath()));

}

//

// Writer interface

//

public void write(OutputStream out) throws IOException {

BufferedWriter PW = new BufferedWriter(new OutputStreamWriter(out,

"UTF-8"));

PW.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");

if (rootElement.subElements.size() > 0) {

for (int i = 0; i < rootElement.subElements.size(); i++) {

_writeSubNode(PW, (XmlElement) rootElement.subElements.get(i), 0);

}

}

PW.flush();

}

private void _writeSubNode(Writer out, XmlElement element, int indent)

throws IOException {

_writeSpace(out, indent);

out.write("<");

out.write(element.getName());

for (Enumeration e = element.getAttributeNames(); e.hasMoreElements();) {

String K = (String) e.nextElement();

out.write(" " + K + "=\"" + InspirentoUtilities.escapeText(element.getAttribute(K)) + "\"");

}

out.write(">");

String data = element.getData();

if ((data != null) && !data.equals("")) {

if (data.length() > maxOneLineData) {

out.write("\n");

_writeSpace(out, indent + writeIndent);

}

out.write(InspirentoUtilities.escapeText(data));

}

List subElements = element.getElements();

if (subElements.size() > 0) {

out.write("\n");

for (Iterator it = subElements.iterator(); it.hasNext();) {

_writeSubNode(out, (XmlElement) it.next(), indent + writeIndent);

// for (int i = 0; i < subElements.size(); i++) {

// _writeSubNode(

// out,

// (XmlElement) subElements.get(i),

// indent + writeIndent);

}

_writeSpace(out, indent);

}

if (data.length() > maxOneLineData) {

out.write("\n");

_writeSpace(out, indent);

}

out.write("</" + InspirentoUtilities.escapeText(element.getName()) + ">\n");

}

private void _writeSpace(Writer out, int numSpaces)

throws IOException {

for (int i = 0; i < numSpaces; i++) {

out.write(" ");

}

}

}

下面是继承Properties的ConfigurationManager,其中的getProperty和setProperty方法已经被Overridden。

/*

* @(#)ConfigurationManager.java

* Created on 2005-8-10

*/

package com.allenstudio.ir.core;

import java.util.*;

import java.io.*;

import com.allenstudio.ir.util.*;

/**

* Manages the configuration for Inspirento.<br>

* This manager uses XML format to store information.

* The configuration file is, by default, saved in the

* "config" directory and named "config.xml". Clearly,

* this class should be a singleton, so we use

* {@link #getInstance()} to get an instance and call

* other instance methods to get the settings needed

* by Inspirento, such as "windowSize", "windowLocation",

* and etc.<br>

* The program first tries to get the configuration from

* this <code>ConfigurationManager</code>. If it fails to

* get any key, it uses the default settings presetted in

* the protected <code>default</code> field.

*

* @author Allen Chue

*/

public class ConfigurationManager extends Properties {

public static final String CONFIG_DIRECTORY = "config";

public static final String CONFIG_FILE = "config.xml";

public static final String COMMON_PREFIX = "Inspirento.";

private static ConfigurationManager instance = null;

private XmlIO xmlIO;

/**

* Private constructor for singleton use.

*/

private ConfigurationManager() {

initDefaultSettings();

readIn();

}

public static ConfigurationManager getInstance() {

if (instance != null) {

return instance;

} else {

instance = new ConfigurationManager();

return instance;

}

}

public void readIn() {

try {

File configFile = new File(

CONFIG_DIRECTORY +

System.getProperty("file.separator") +

CONFIG_FILE);//$NON-NLS-1$

if (configFile.exists()) {

FileInputStream configStream = new FileInputStream(configFile);

xmlIO = new XmlIO();

xmlIO.load(configStream);

configStream.close();

}

} catch (Exception e) {

System.out.println("Cannot load configuration file" +

" supposed to be at \"config\\config.xml\"" +

"\nDefault settings will be stored as the replacement.");//$NON-NLS-1$

writeDefaultsToFile();

e.printStackTrace();

}

}

public void writeBack() {

try {

FileOutputStream configFile = new FileOutputStream(

CONFIG_DIRECTORY +

System.getProperty("file.separator") +

CONFIG_FILE);

xmlIO.write(configFile);

configFile.close();

} catch (Exception e) {

System.out.println("Cannot write configuration file" +

" to \"config\\config.xml\"");//$NON-NLS-1$

e.printStackTrace();

}

}

/**

* Uses XML parser to get the specified property.

* If there is no such a key, the method returns

* <code>null</code>.

* @param key the key of the property

* @return the property value

*/

@Override

public synchronized String getProperty(String key) {

String value = xmlIO.getRoot().getElement(Constants.PROJECT_NAME +

"." + getPath(key)[0]).getAttribute(getPath(key)[1]);

if (value == null) {//Perhaps some element is lost in the file

value = defaults.getProperty(key);

setProperty(key, value);//null value has no side effect

new Thread(){

@Override

public void run() {

writeBack();

}

}.start();

}

return value;

}

@Override

public synchronized Object setProperty(String key, String value) {

xmlIO.getRoot().getElement(Constants.PROJECT_NAME +

"." + getPath(key)[0]).addAttribute(getPath(key)[1], value);

return value;

}

/**

* When the configuration file is lost, this method

* is used to write the default settings stored in

* the program itself to file.

*

*/

private void writeDefaultsToFile() {

Enumeration keys = defaults.keys();

XmlElement xe = new XmlElement(Constants.PROJECT_NAME);

xmlIO = new XmlIO(xe);

for (; keys.hasMoreElements(); ) {

String pathText = (String)keys.nextElement();

String[] path = getPath(pathText);

//Test if the element to be modified exists

XmlElement elementAdded = xe.getElement(path[0]);

if (elementAdded == null){

elementAdded = xe.addSubElement(path[0]);

}

elementAdded.addAttribute(path[1], defaults.getProperty(pathText));

}

try {

FileOutputStream configFile = new FileOutputStream(

CONFIG_DIRECTORY +

System.getProperty("file.separator") +

CONFIG_FILE);//$NON-NLS-1$

xmlIO.write(configFile);

configFile.close();

} catch (Exception e) {

System.out.println("Cannot write configuration file" +

" to \"config\\config.xml\"");//$NON-NLS-1$

e.printStackTrace();

}

}

/**

* Returns an string array of length 2.

* The parameter <code>pathText</code> is supposed to

* be a string separated with dots. For example,

* "Inspirento.window.location" is a valid parameter.

* This method puts the token after the last dot in

* the second position of the result array, and the

* remaining string(excluding the last dot) in the first

* position of the result array. It is a rivate helping method.

* <br>

* Example: getPath("Inspirento.window.location") returns

* the array {"Inspirento.window", "location"}.<br>

* <em>No format checking is done in this method! <code>

* ArrayOutOfBoundsException</code> will be thrown

* when no dots are found in the string.</em>

* @param pathText the path text to be processed

* @return an array containing the result

*/

private static String[] getPath(String pathText) {

int dotPos = pathText.lastIndexOf('.');

String[] result = new String[2];

result[0] = pathText.substring(0, dotPos);

result[1] = pathText.substring(dotPos + 1);

return result;

}

private void initDefaultSettings() {

String[] configDefaults = {

"window.location", "400,300",

"window.size", "450,300"

};

defaults = new Properties();

for(int i = 0, max = configDefaults.length; i < max; i += 2) {

String value = configDefaults[i + 1];

defaults.setProperty(configDefaults[i], value);

}

}

}

在上面的代码中,Inspirento是我的项目,可以根据情况修改。实际这个类是使用在整个程序的配置获取和修改的。如果用它处理前面的属性,可以得到这样的文件,可以看到它有层次感,更便于处理和阅读。

<?xml version="1.0" encoding="UTF-8"?>

<Inspirento>

<window location="202 ,179" size="532 ,455"></window>

</Inspirento>

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有