如何在java中亲自格式化属性文件?

时间:2013-04-03 12:48:15

标签: java properties

我正在使用java中的属性类为我的应用程序保存一些配置。这是我第一次使用房产,所以请温柔地对待我:)

我可以从属性中插入和检索数据,没问题,但我想将数据插入如下:

属性文件:

#Header generated by java ~ this is fine, I don't care

#Server 1 configuration
url=192.168.1.1
port=6546
username=max
password=123

#Server 2 configuration
url=192.168.2.1
port=6454
username:dude
password:123

#And so on...

这是我的代码:

public void setProp(String host, String port, String user, String pass, 
                           String host2, String port2, String user2, String pass2)
{
        try{
            prop.setProperty("host", host);
            prop.setProperty("port", porto);
            prop.setProperty("username", user);
            prop.setProperty("password", pass);

            prop.setProperty("host2", host2);
            prop.setProperty("port2", porto2);
            prop.setProperty("username2", user2);
            prop.setProperty("password2", pass2);

            config.store(new FileOutputStream("configuration.properties"), "Server 1 Configuration");

        }catch (Exception e) {
            JOptionPane.showMessageDialog(null,"Error: "+e.getMessage());
        }
}

编辑: @Nathan不接近我假装的东西。生成的属性文件是:

#Wed Apr 03 14:03:57 BST 2013 
server1.url=192.168.1.1 
server1.port=80 
server2.password=qqq 
server1.user=root 
server2.port=88 
server2.user=dude 
server1.pass=123 
server2.url=192.168.2.1

我会寻找类似的东西:

#Wed Apr 03 14:03:57 BST 2013 
#Server 1 details
server1.url=192.168.1.1 
server1.port=80 
server1.user=root 
server1.pass=123 

#Server 2 details:
server2.password=qqq 
server2.port=88 
server2.user=dude 
server2.url=192.168.2.1

我甚至不关心订单是否正确(如密码在网址上方和端口下等)我只需将它们分组,就像我现在的例子一样。

4 个答案:

答案 0 :(得分:5)

属性文件不像那样分层。 (还有其他格式,如YAML或XML,但不是这一种。)而是每一行都是一个键值对,其中键必须在整个文件中是唯一的。 (Properties类是从Hashtable扩展的快速入侵。)更改属性文件中的键:

#Server 1 Configuration
server1.url=192.168.1.1
server1.port=6546
server1.username=max
server1.password=123

#Server 2 configuration
server2.url=192.168.2.1
server2.port=6454
server2.username:dude
server2.password:123

然后将代码更改为:

      prop.setProperty("server1.url", host);

因为Properties扩展了Hashtable,并且哈希表为它们提供了它们自己的键值对的内部排序,所以当你从Properties对象生成属性文件时,条目将全部混乱。由于您希望键处于任意顺序,因此排序也不容易。我将使用代码生成属性文件的初始版本,然后按照您想要的顺序移动东西,并使用该属性文件继续。如果您需要以编程方式生成属性文件,那么您将需要编写代码来写入文件而不是属性如何。

答案 1 :(得分:4)

我想我看到了你的问题...当你有:

#Server 1 configuration
url=192.168.1.1
port=6546

#Server 2 configuration
url=192.168.2.1
port=6454

只有url,port等的最后一个值才会在属性文件中读取,因为后续每个值都会覆盖前一个值。我通常通过做类似的事情来解决这个问题:

#Server 1 configuration
server.1.url=192.168.1.1
server.1.port=6546

#Server 2 configuration
server.2.url=192.168.2.1
server.2.port=6454

....

#Server n configuration
server.n.url=192.168.2.1
server.n.port=6454

您还可以使用以下属性存储服务器总数:

number.of.servers=55

但这是假设服务器编号是顺序的。在更一般的情况下,假设它们不是这样,你可以有类似的东西:

#server 1
url=xxx
port=123

#server 100
url=xxx
port=123

#server 5
url=xxx
port=123

正如@Nathan Hughes简明地指出属性是键值对,每个重复键都会吹掉前一个键。我没有使用YAML,但我更喜欢JSON而不是XML。但是你仍然可以坚持使用属性。

如前所述,你可以这样做:

#server 1
server.1.url=xxx
server.1.port=123

#server 100
server.100.url=xxx
server.100.port=123

#server 5
server.5.url=xxx
server.5.port=123

现在问题就变成了,我的属性文件中有哪些服务器号。只需迭代属性文件的键,然后做一些String kung fu。

Properties p = myReadProperties();
Set<String> keys = p.keySet();
Set<Integer> serverNumbers = new Set<Integer>();
Iterator<String> i = keys.iterator();
String str, strArray;
while(i.hasNext()) {
  str = i.next();
  //A regex would be better here, but for brevity.
  if(str.startsWith("server.") && str.endsWith(".url")) {
    strArray = str.split(".");
    serverNumbers.add(new Integer(strArray[1]));
  }

所以现在你有了一组服务器号码。您可以重建属性键以获取任何值。

答案 2 :(得分:1)

#Server 1 configuration
url=192.168.1.1
port=6546
username=max
password=123

#Server 2 configuration
url=192.168.2.1
port=6454
username:dude
password:123

因此,如果我理解,您想要创建这样的配置文件。你可以做什么来格式化它是一旦保存,打开文件并插入你想要的行,这将是一个非常痛苦的工作。如果你想要一个结构良好的配置文件,那你为什么不尝试使用xml和jaxb?

类似的东西:

<servers>
<server>
<id>1</id>
<url>192.168.1.1</url>
<port>6546</port>
<username>max</username>
<password>123</password>
</server>

<server>
<id>2</id>
<url>192.168.2.1</url>
<port>6454</port>
<username>dude</username>
<password>123</password>
</server>
</servers>

您可以基于此创建架构:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="servers">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="server" maxOccurs="unbounded" minOccurs="0">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:byte" name="id"/>
              <xs:element type="xs:string" name="url"/>
              <xs:element type="xs:short" name="port"/>
              <xs:element type="xs:string" name="username"/>
              <xs:element type="xs:byte" name="password"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

然后根据您的目的使用JAXB。我希望它可以帮助你,或者至少可以给你一个想法。最好的问候。

答案 3 :(得分:0)

如果您使用FileOutputStream,您可以创建输出文件并以您立即询问的格式写入。但是,如果您使用属性,那么您将无法重复相同的键。