2

我正在尝试使用属性修改 Java 中的配置文件。

我使用 Properties.store、load 和 setProperty 成功地读取、写入和修改了这些行,但我注意到在执行此类操作后,文件被覆盖,因此我松开了配置文件中不是键值对的所有行。即,我失去了评论。

有没有办法使用 java.util 保留这样的行?

在每一行中放置一个前缀不是问题。我知道如何“手动”逐行阅读;我要求的是另一种选择

4

2 回答 2

2

我不认为这是可能的。请注意,属性也不保证从 load() 到 store() 或从一个 store() 到另一个的顺序相同。如果可能,Properties 的 javadoc 会告诉您如何操作。

于 2013-08-23T12:47:08.240 回答
0
import java.io.*;
import java.util.*;

/**
 * The CommentedProperties class is an extension of java.util.Properties
 * to allow retention of comment lines and blank (whitespace only) lines
 * in the properties file.
 * 
 * Written for Java version 1.4
 */
public class CommentedProperties extends java.util.Properties {

/**
 * Use a Vector to keep a copy of lines that are a comment or 'blank'
 */
public Vector lineData = new Vector(0, 1);

/**
 * Use a Vector to keep a copy of lines containing a key, i.e. they are a property.
 */
public Vector keyData = new Vector(0, 1);

/**
 * Load properties from the specified InputStream. 
 * Overload the load method in Properties so we can keep comment and blank lines.
 * @param   inStream   The InputStream to read.
 */
public void load(InputStream inStream) throws IOException
{
    // The spec says that the file must be encoded using ISO-8859-1.
    BufferedReader reader =
    new BufferedReader(new InputStreamReader(inStream, "ISO-8859-1"));
    String line;

    while ((line = reader.readLine()) != null) {
        char c = 0;
        int pos = 0;
        // Leading whitespaces must be deleted first.
        while ( pos < line.length()
                && Character.isWhitespace(c = line.charAt(pos))) {
            pos++;
        }

        // If empty line or begins with a comment character, save this line
        // in lineData and save a "" in keyData.
        if (    (line.length() - pos) == 0
                || line.charAt(pos) == '#' || line.charAt(pos) == '!') {
            lineData.add(line);
            keyData.add("");
            continue;
        }

        // The characters up to the next Whitespace, ':', or '='
        // describe the key.  But look for escape sequences.
        // Try to short-circuit when there is no escape char.
        int start = pos;
        boolean needsEscape = line.indexOf('\\', pos) != -1;
        StringBuffer key = needsEscape ? new StringBuffer() : null;

        while ( pos < line.length()
                && ! Character.isWhitespace(c = line.charAt(pos++))
                && c != '=' && c != ':') {
            if (needsEscape && c == '\\') {
                if (pos == line.length()) {
                    // The line continues on the next line.  If there
                    // is no next line, just treat it as a key with an
                    // empty value.
                    line = reader.readLine();
                    if (line == null)
                        line = "";
                    pos = 0;
                    while ( pos < line.length()
                            && Character.isWhitespace(c = line.charAt(pos)))
                        pos++;
                } else {
                    c = line.charAt(pos++);
                    switch (c) {
                        case 'n':
                            key.append('\n');
                            break;
                        case 't':
                            key.append('\t');
                            break;
                        case 'r':
                            key.append('\r');
                            break;
                        case 'u':
                            if (pos + 4 <= line.length()) {
                                char uni = (char) Integer.parseInt
                                           (line.substring(pos, pos + 4), 16);
                                key.append(uni);
                                pos += 4;
                            }   // else throw exception?
                            break;
                        default:
                            key.append(c);
                            break;
                    }
                }
            } else if (needsEscape)
                key.append(c);
        }

        boolean isDelim = (c == ':' || c == '=');

        String keyString;
        if (needsEscape)
            keyString = key.toString();
        else if (isDelim || Character.isWhitespace(c))
            keyString = line.substring(start, pos - 1);
        else
            keyString = line.substring(start, pos);

        while ( pos < line.length()
                && Character.isWhitespace(c = line.charAt(pos)))
            pos++;

        if (! isDelim && (c == ':' || c == '=')) {
            pos++;
            while ( pos < line.length()
                    && Character.isWhitespace(c = line.charAt(pos)))
                pos++;
        }

        // Short-circuit if no escape chars found.
        if (!needsEscape) {
            put(keyString, line.substring(pos));
            // Save a "" in lineData and save this
            // keyString in keyData.
            lineData.add("");
            keyData.add(keyString);
            continue;
        }

        // Escape char found so iterate through the rest of the line.
        StringBuffer element = new StringBuffer(line.length() - pos);
        while (pos < line.length()) {
            c = line.charAt(pos++);
            if (c == '\\') {
                if (pos == line.length()) {
                    // The line continues on the next line.
                    line = reader.readLine();

                    // We might have seen a backslash at the end of
                    // the file.  The JDK ignores the backslash in
                    // this case, so we follow for compatibility.
                    if (line == null)
                        break;

                    pos = 0;
                    while ( pos < line.length()
                            && Character.isWhitespace(c = line.charAt(pos)))
                        pos++;
                    element.ensureCapacity(line.length() - pos +
                                           element.length());
                } else {
                    c = line.charAt(pos++);
                    switch (c) {
                        case 'n':
                            element.append('\n');
                            break;
                        case 't':
                            element.append('\t');
                            break;
                        case 'r':
                            element.append('\r');
                            break;
                        case 'u':
                            if (pos + 4 <= line.length()) {
                                char uni = (char) Integer.parseInt
                                           (line.substring(pos, pos + 4), 16);
                                element.append(uni);
                                pos += 4;
                            }   // else throw exception?
                            break;
                        default:
                            element.append(c);
                            break;
                    }
                }
            } else
                element.append(c);
        }
        put(keyString, element.toString());
        // Save a "" in lineData and save this
        // keyString in keyData.
        lineData.add("");
        keyData.add(keyString);
    }
}

/**
 * Write the properties to the specified OutputStream.
 * 
 * Overloads the store method in Properties so we can put back comment  
 * and blank lines.                                                   
 * 
 * @param out   The OutputStream to write to.
 * @param header Ignored, here for compatability w/ Properties.
 * 
 * @exception IOException
 */
public void store(OutputStream out, String header) throws IOException
{
    // The spec says that the file must be encoded using ISO-8859-1.
    PrintWriter writer
    = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1"));

    // We ignore the header, because if we prepend a commented header
    // then read it back in it is now a comment, which will be saved
    // and then when we write again we would prepend Another header...

    String line;
    String key;
    StringBuffer s = new StringBuffer ();

    for (int i=0; i<lineData.size(); i++) {
        line = (String) lineData.get(i);
        key = (String) keyData.get(i);
        if (key.length() > 0) {  // This is a 'property' line, so rebuild it
            formatForOutput (key, s, true);
            s.append ('=');
            formatForOutput ((String) get(key), s, false);
            writer.println (s);
        } else {  // was a blank or comment line, so just restore it
            writer.println (line);
        }
    } 
    writer.flush ();
}

/**
 * Need this method from Properties because original code has StringBuilder,
 * which is an element of Java 1.5, used StringBuffer instead (because
 * this code was written for Java 1.4)
 * 
 * @param str   - the string to format
 * @param buffer - buffer to hold the string
 * @param key   - true if str the key is formatted, false if the value is formatted
 */
private void formatForOutput(String str, StringBuffer buffer, boolean key)
{
    if (key) {
        buffer.setLength(0);
        buffer.ensureCapacity(str.length());
    } else
        buffer.ensureCapacity(buffer.length() + str.length());
    boolean head = true;
    int size = str.length();
    for (int i = 0; i < size; i++) {
        char c = str.charAt(i);
        switch (c) {
            case '\n':
                buffer.append("\\n");
                break;
            case '\r':
                buffer.append("\\r");
                break;
            case '\t':
                buffer.append("\\t");
                break;
            case ' ':
                buffer.append(head ? "\\ " : " ");
                break;
            case '\\':
            case '!':
            case '#':
            case '=':
            case ':':
                buffer.append('\\').append(c);
                break;
            default:
                if (c < ' ' || c > '~') {
                    String hex = Integer.toHexString(c);
                    buffer.append("\\u0000".substring(0, 6 - hex.length()));
                    buffer.append(hex);
                } else
                    buffer.append(c);
        }
        if (c != ' ')
            head = key;
    }
}

/**
 * Add a Property to the end of the CommentedProperties. 
 * 
 * @param   keyString    The Property key.
 * @param   value        The value of this Property.
 */
public void add(String keyString, String value)
{
    put(keyString, value);
    lineData.add("");
    keyData.add(keyString);
}

/**
 * Add a comment or blank line or comment to the end of the CommentedProperties. 
 * 
 * @param   line The string to add to the end, make sure this is a comment
 *             or a 'whitespace' line.
 */
public void addLine(String line)
{
    lineData.add(line);
    keyData.add("");
}

}

于 2013-08-23T13:33:57.043 回答