Java Properties: How to keep non key=value lines?

放肆的年华 提交于 2019-12-02 03:34:59

I don't think it is possible. Note that properties also don't promise that the ordering will be the same from load() to store(), or from one store() to another. If it is possible, the javadoc for Properties will tell you how.

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("");
}

}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!