仔细看一下看似完全相同的这两个属性文件:
除了它们确实不完全相同:
(屏幕截图来自Notepad ++)
由于保留了尾随空格,lastName因此"Smith"在第一种情况下和"Smith "第二种情况下的值都是。
这很少是用户期望的,并且只能推测为什么这是Properties类的默认行为。但是,创建Properties此问题的增强版很容易。下面的类TrimmedProperties就是这样做的。它是标准Properties类的直接替代。
import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.util.Map.Entry; import java.util.Properties; /** * Properties class where values are trimmed for trailing whitespace if the * properties are loaded from a file. * * <p> * In the standard {@link java.util.Properties Properties} class trailing * whitespace is always preserved. When loading properties from a file such * trailing whitespace is almost always <i>unintentional</i>. This class fixes * this problem. The trimming of trailing whitespace only takes place if the * source of input is a file and only where the input is line oriented (meaning * that for example loading from XML file is <i>not</i> changed by this class). * For this reason this class is almost in all cases a safe drop-in replacement * for the standard <tt>Properties</tt> * class. * * <p> * Whitespace is defined here as any of space (U+0020) or tab (U+0009). * * */ public class TrimmedProperties extends Properties { /** * Reads a property list (key and element pairs) from the input byte stream. * * <p>Behaves exactly as {@link java.util.Properties#load(java.io.InputStream) } * with the exception that trailing whitespace is trimmed from property values * if <tt>inStream</tt> is an instance of <tt>FileInputStream</tt>. * * @see java.util.Properties#load(java.io.InputStream) * @param inStream the input stream. * @throws IOException if an error occurred when reading from the input stream. */ @Override public void load(InputStream inStream) throws IOException { if (inStream instanceof FileInputStream) { // 首先使用标准方式读入临时道具 Properties tempProps = new Properties(); tempProps.load(inStream); // 现在修剪并放入目标 trimAndLoad(tempProps); } else { super.load(inStream); } } /** * Reads a property list (key and element pairs) from the input character stream in a simple line-oriented format. * * <p>Behaves exactly as {@link java.util.Properties#load(java.io.Reader)} * with the exception that trailing whitespace is trimmed on property values * if <tt>reader</tt> is an instance of <tt>FileReader</tt>. * * @see java.util.Properties#load(java.io.Reader) } * @param reader the input character stream. * @throws IOException if an error occurred when reading from the input stream. */ @Override public void load(Reader reader) throws IOException { if (reader instanceof FileReader) { // 首先使用标准方式读入临时道具 Properties tempProps = new Properties(); tempProps.load(reader); // 现在修剪并放入目标 trimAndLoad(tempProps); } else { super.load(reader); } } private void trimAndLoad(Properties p) { for (Entry<Object, Object> entry : p.entrySet()) { if (entry.getValue() instanceof String) { put(entry.getKey(), trimTrailing((String) entry.getValue())); } else { put(entry.getKey(), entry.getValue()); } } } /** * Trims trailing space or tabs from a string. * * @param str * @return */ public static String trimTrailing(String str) { if (str != null) { // 从尾部读取str,直到char不再为空格 for (int i = str.length() - 1; i >= 0; i--) { if ((str.charAt(i) != ' ') && (str.charAt(i) != '\t')) { return str.substring(0, i + 1); } } } return str; } }