旧问题(2009 年 1 月)的另一个答案(2018 年 1 月)。
Java 属性文件的规范在java.util.Properties.load(java.io.Reader)
. 一个问题是规范比我们可能的第一印象有点复杂。另一个问题是这里的一些答案任意添加了额外的规范 - 例如,;
被'
视为注释行的开始,但它们不应该是。属性值周围的双引号/单引号被删除,但它们不应该被删除。
以下是需要考虑的要点。
- 线有两种,自然线和逻辑线。
- 自然行以
\n
、\r
或\r\n
流的结尾终止。
- 通过使用反斜杠字符转义行终止符序列,可以将逻辑行分散到多个相邻的自然行中
\
。
- 逻辑行中第二个和后续自然行开头的任何空白都将被丢弃。
- 空格是空格 (
, \u0020
)、制表符 ( \t
, \u0009
) 和换页 ( \f
, \u000C
)。
- 正如规范中明确指出的那样,“仅检查行终止符序列之前的字符来确定行终止符是否被转义是不够的;行终止符必须有奇数个连续的反斜杠才能被转义。由于输入是从左到右处理的,在转义处理后,行终止符(或其他地方)编码 n 个反斜杠之前的非零偶数 2n 个连续反斜杠。”
=
用作键和值之间的分隔符。
:
也用作键和值之间的分隔符。
- 键和值之间的分隔符可以省略。
- 注释行具有
#
or!
作为其第一个非空白字符,这意味着在#
or之前的前导空白!
是允许的。
- 注释行不能扩展到下一个自然行,即使它的行终止符前面是
\
.
- 正如规范中明确指出的那样,如果用反斜杠转义
=
,:
和空格可以嵌入到键中。
- 甚至可以使用
\r
和\n
转义序列包含行终止符。
- 如果省略值,则使用空字符串作为值。
\uxxxx
用于表示 Unicode 字符。
- 无效转义字符之前的反斜杠字符不被视为错误;它被默默地丢弃。
因此,例如,如果test.properties
具有以下内容:
# A comment line that starts with '#'.
# This is a comment line having leading white spaces.
! A comment line that starts with '!'.
key1=value1
key2 : value2
key3 value3
key\
4=value\
4
\u006B\u0065\u00795=\u0076\u0061\u006c\u0075\u00655
\k\e\y\6=\v\a\lu\e\6
\:\ \= = \\colon\\space\\equal
它应该被解释为以下键值对。
+------+--------------------+
| KEY | VALUE |
+------+--------------------+
| key1 | value1 |
| key2 | value2 |
| key3 | value3 |
| key4 | value4 |
| key5 | value5 |
| key6 | value6 |
| : = | \colon\space\equal |
+------+--------------------+
PropertiesLoader
Authlete.Authlete NuGet 包中的类可以解释规范的格式。下面的示例代码:
using System;
using System.IO;
using System.Collections.Generic;
using Authlete.Util;
namespace MyApp
{
class Program
{
public static void Main(string[] args)
{
string file = "test.properties";
IDictionary<string, string> properties;
using (TextReader reader = new StreamReader(file))
{
properties = PropertiesLoader.Load(reader);
}
foreach (var entry in properties)
{
Console.WriteLine($"{entry.Key} = {entry.Value}");
}
}
}
}
将生成此输出:
key1 = value1
key2 = value2
key3 = value3
key4 = value4
key5 = value5
key6 = value6
: = = \colon\space\equal
Java中的一个等效示例如下:
import java.util.*;
import java.io.*;
public class Program
{
public static void main(String[] args) throws IOException
{
String file = "test.properties";
Properties properties = new Properties();
try (Reader reader = new FileReader(file))
{
properties.load(reader);
}
for (Map.Entry<Object, Object> entry : properties.entrySet())
{
System.out.format("%s = %s\n", entry.getKey(), entry.getValue());
}
}
}
源代码PropertiesLoader.cs
可以在authlete-csharp中找到。xUnit测试PropertiesLoader
是用PropertiesLoaderTest.cs
.