📄 properties.java
字号:
/**
* $RCSfile: Properties.java,v $
* $Revision: 1.1.1.1 $
* $Date: 2004/01/07 05:06:28 $
*
* Copyright (C) 2003 ICSS, Inc. All rights reserved.
*
* This software is the proprietary information of ICSS, Inc.
* Use is subject to license terms.
*/
/*
* modified by Andy
* 添加了对中文的支持
*/
package com.gctech.misc.util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
/**
* The <code>Properties</code> class represents a persistent set of properties.
* The <code>Properties</code> can be saved to a stream or loaded from a
* stream. Each key and its corresponding value in the property list is a
* string. <p>
*
* A property list can contain another property list as its "defaults"; this
* second property list is searched if the property key is not found in the
* original property list. <p>
*
* Because <code>Properties</code> inherits from <code>Hashtable</code>, the
* <code>put</code> and <code>putAll</code> methods can be applied to a <code>Properties</code>
* object. Their use is strongly discouraged as they allow the caller to insert
* entries whose keys or values are not <code>Strings</code>. The <code>setProperty</code>
* method should be used instead. If the <code>store</code> or <code>save</code>
* method is called on a "compromised" <code>Properties</code> object that
* contains a non-<code>String</code> key or value, the call will fail. <p>
*
* <a name="encoding"></a> When saving properties to a stream or loading them
* from a stream, the ISO 8859-1 character encoding is used. For characters
* that cannot be directly represented in this encoding, <a
* href="http://java.sun.com/docs/books/jls/html/3.doc.html#100850">Unicode
* escapes</a> are used; however, only a single 'u' character is allowed in an
* escape sequence. The native2ascii tool can be used to convert property files
* to and from other character encodings.
*
*@author Arthur van Hoff
*@author Michael McCloskey
*@see <a href="../../../tooldocs/solaris/native2ascii.html">native2ascii
* tool for Solaris</a>
*@see <a href="../../../tooldocs/windows/native2ascii.html">native2ascii
* tool for Windows</a>
*@version 1.64, 06/26/00
*@since JDK1.0
*/
public class Properties extends Hashtable {
/**
* use serialVersionUID from JDK 1.1.X for interoperability
*/
private final static long serialVersionUID = 4112578634029874840L;
/**
* A property list that contains default values for any keys not found in
* this property list.
*
*@serial
*/
protected Properties defaults;
/**
* Creates an empty property list with no default values.
*/
public Properties() {
this(null);
}
/**
* Creates an empty property list with the specified defaults.
*
*@param defaults the defaults.
*/
public Properties(Properties defaults) {
this.defaults = defaults;
}
/**
* Calls the <tt>Hashtable</tt> method <code>put</code>. Provided for
* parallelism with the <tt>getProperty</tt> method. Enforces use of strings
* for property keys and values. The value returned is the result of the <tt>
* Hashtable</tt> call to <code>put</code>.
*
*@param key the key to be placed into this property list.
*@param value the value corresponding to <tt>key</tt> .
*@return the previous value of the specified key in this property
* list, or <code>null</code> if it did not have one.
*@see #getProperty
*@since 1.2
*/
public synchronized Object setProperty(String key, String value) {
return put(key, value);
}
private final static String keyValueSeparators = "=: \t\r\n\f";
private final static String strictKeyValueSeparators = "=:";
private final static String specialSaveChars = "=: \t\r\n\f#!";
private final static String whiteSpaceChars = " \t\r\n\f";
/**
* Reads a property list (key and element pairs) from the input stream. The
* stream is assumed to be using the ISO 8859-1 character encoding. <p>
*
* Every property occupies one line of the input stream. Each line is
* terminated by a line terminator (<code>\n</code> or <code>\r</code> or
* <code>\r\n</code>). Lines from the input stream are processed until end of
* file is reached on the input stream. <p>
*
* A line that contains only whitespace or whose first non-whitespace
* character is an ASCII <code>#</code> or <code>!</code> is ignored (thus,
* <code>#</code> or <code>!</code> indicate comment lines). <p>
*
* Every line other than a blank line or a comment line describes one
* property to be added to the table (except that if a line ends with \, then
* the following line, if it exists, is treated as a continuation line, as
* described below). The key consists of all the characters in the line
* starting with the first non-whitespace character and up to, but not
* including, the first ASCII <code>=</code>, <code>:</code>, or whitespace
* character. All of the key termination characters may be included in the
* key by preceding them with a \. Any whitespace after the key is skipped;
* if the first non-whitespace character after the key is <code>=</code> or
* <code>:</code>, then it is ignored and any whitespace characters after it
* are also skipped. All remaining characters on the line become part of the
* associated element string. Within the element string, the ASCII escape
* sequences <code>\t</code>, <code>\n</code>, <code>\r</code>, <code>\\</code>
* , <code>\"</code>, <code>\'</code>, <code>\  </code>  (a backslash
* and a space), and <code>\u</code><i>xxxx</i> are recognized and
* converted to single characters. Moreover, if the last character on the
* line is <code>\</code>, then the next line is treated as a continuation of
* the current line; the <code>\</code> and line terminator are simply
* discarded, and any leading whitespace characters on the continuation line
* are also discarded and are not part of the element string. <p>
*
* As an example, each of the following four lines specifies the key <code>"Truth"</code>
* and the associated element value <code>"Beauty"</code>: <p>
*
* <pre>
* Truth = Beauty
* Truth:Beauty
* Truth :Beauty
* </pre> As another example, the following three lines specify a single
* property: <p>
*
* <pre>
* fruits apple, banana, pear, \
* cantaloupe, watermelon, \
* kiwi, mango
* </pre> The key is <code>"fruits"</code> and the associated element is: <p>
*
* <pre>"apple, banana, pear, cantaloupe, watermelon, kiwi, mango"</pre> Note
* that a space appears before each <code>\</code> so that a space will
* appear after each comma in the final result; the <code>\</code>, line
* terminator, and leading whitespace on the continuation line are merely
* discarded and are <i>not</i> replaced by one or more other characters. <p>
*
* As a third example, the line: <p>
*
* <pre>cheeses
* </pre> specifies that the key is <code>"cheeses"</code> and the associated
* element is the empty string.<p>
*
*
*
*@param inStream the input stream.
*@exception IOException if an error occurred when reading from the input
* stream.
*/
public synchronized void load(InputStream inStream) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
while (true) {
// Get next line
String line = in.readLine();
if (line == null) {
return;
}
if (line.length() > 0) {
// Continue lines that end in slashes if they are not comments
char firstChar = line.charAt(0);
if ((firstChar != '#') && (firstChar != '!')) {
while (continueLine(line)) {
String nextLine = in.readLine();
if (nextLine == null) {
nextLine = "";
}
String loppedLine = line.substring(0, line.length() - 1);
// Advance beyond whitespace on new line
int startIndex = 0;
for (startIndex = 0; startIndex < nextLine.length(); startIndex++) {
if (whiteSpaceChars.indexOf(nextLine.charAt(startIndex)) == -1) {
break;
}
}
nextLine = nextLine.substring(startIndex, nextLine.length());
line = new String(loppedLine + nextLine);
}
// Find start of key
int len = line.length();
int keyStart;
for (keyStart = 0; keyStart < len; keyStart++) {
if (whiteSpaceChars.indexOf(line.charAt(keyStart)) == -1) {
break;
}
}
// Blank lines are ignored
if (keyStart == len) {
continue;
}
// Find separation between key and value
int separatorIndex;
for (separatorIndex = keyStart; separatorIndex < len; separatorIndex++) {
char currentChar = line.charAt(separatorIndex);
if (currentChar == '\\') {
separatorIndex++;
}
else if (keyValueSeparators.indexOf(currentChar) != -1) {
break;
}
}
// Skip over whitespace after key if any
int valueIndex;
for (valueIndex = separatorIndex; valueIndex < len; valueIndex++) {
if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1) {
break;
}
}
// Skip over one non whitespace key value separators if any
if (valueIndex < len) {
if (strictKeyValueSeparators.indexOf(line.charAt(valueIndex)) != -1) {
valueIndex++;
}
}
// Skip over white space after other separators if any
while (valueIndex < len) {
if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1) {
break;
}
valueIndex++;
}
String key = line.substring(keyStart, separatorIndex);
String value = (separatorIndex < len) ? line.substring(valueIndex, len) : "";
// Convert then store key and value
key = loadConvert(key);
value = loadConvert(value);
put(key, value);
}
}
}
}
/*
* Returns true if the given line is a line that must
* be appended to the next line
*/
/**
* Description of the Method
*
*@param line Description of the Parameter
*@return Description of the Return Value
*/
private boolean continueLine(String line) {
int slashCount = 0;
int index = line.length() - 1;
while ((index >= 0) && (line.charAt(index--) == '\\')) {
slashCount++;
}
return (slashCount % 2 == 1);
}
/*
* Converts encoded \uxxxx to unicode chars
* and changes special saved chars to their original forms
*/
/**
* Description of the Method
*
*@param theString Description of the Parameter
*@return Description of the Return Value
*/
private String loadConvert(String theString) {
char aChar;
int len = theString.length();
StringBuffer outBuffer = new StringBuffer(len);
for (int x = 0; x < len;) {
aChar = theString.charAt(x++);
if (aChar == '\\') {
aChar = theString.charAt(x++);
if (aChar == 'u') {
// Read the xxxx
int value = 0;
for (int i = 0; i < 4; i++) {
aChar = theString.charAt(x++);
switch (aChar) {
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
value = (value << 4) + aChar - '0';
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -