Java属性:如何保持非key = value行?

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

我使用Properties.store,load和setProperty成功读取,编写和修改了行,但是我注意到在执行此类操作后,文件被覆盖,因此我放弃了配置文件中不是键值对的行。 也就是说,我放弃了评论。

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

在每行中放置前缀不是问题。 我知道如何逐行“手动”阅读; 我要求替代方案

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

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

}