如何用java个人格式化属性文件?

如何用java个人格式化属性文件?,java,properties,Java,Properties,我正在使用java中的properties类为我的应用程序保存一些配置。这是我第一次使用属性,所以请对我温柔:) 我可以从属性中插入和检索数据,没有问题,但我希望插入数据,如下所示: #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.pa

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

我可以从属性中插入和检索数据,没有问题,但我希望插入数据,如下所示:

#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
#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
#server 1
url=xxx
port=123

#server 100
url=xxx
port=123

#server 5
url=xxx
port=123
      prop.setProperty("server1.url", host);
<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>
属性文件:

#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...
#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
这是我的代码:

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());
        }
}
编辑: @内森和我假装的不一样。生成的属性文件是:

#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
#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
#server 1
url=xxx
port=123

#server 100
url=xxx
port=123

#server 5
url=xxx
port=123
      prop.setProperty("server1.url", host);
<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>

我甚至不在乎顺序是否正确(如url上方的密码和端口下方的密码等),我只需要将它们分组,就像我现在的示例中那样。

我想我看到了您的问题…当您有:

#Server 1 configuration
url=192.168.1.1
port=6546

#Server 2 configuration
url=192.168.2.1
port=6454
仅url、端口等的最后一个值。。。将在属性文件中读取,因为每个后续文件都将覆盖上一个。我通常通过做以下事情来解决这个问题:

#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
#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
#server 1
url=xxx
port=123

#server 100
url=xxx
port=123

#server 5
url=xxx
port=123
      prop.setProperty("server1.url", host);
<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>
您还可以使用以下属性存储服务器总数:

number.of.servers=55
但这是假设服务器编号是连续的。在更一般的情况下,让我们假设它们不是这样,这样您就可以有如下内容:

#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
#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
#server 1
url=xxx
port=123

#server 100
url=xxx
port=123

#server 5
url=xxx
port=123
      prop.setProperty("server1.url", host);
<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>
正如@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
现在的问题是,哪些服务器号在我的属性文件中。只需迭代属性文件的键,然后做一些字符串功夫

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]));
  }
Properties p=myReadProperties();
设置键=p.键集();
Set serverNumbers=new Set();
迭代器i=keys.Iterator();
字符串str,strArray;
while(i.hasNext()){
str=i.next();
//如果不是为了简洁,正则表达式在这里会更好。
if(str.startsWith(“server.”)和&str.endsWith(“url”)){
strArray=str.split(“.”);
add(新整数(strArray[1]);
}

所以现在您有了一组服务器编号。您可以重新构造属性键以获得任何值。

属性文件并不是这样的层次结构。(还有其他格式,如YAML或XML,但不是此格式。)相反,每一行都是一个键-值对,其中键在整个文件中必须是唯一的。(Properties类是从Hashtable扩展而来的一种快速攻击。)更改属性文件中的键:

#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...
#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
然后将代码更改为类似以下内容:

#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
#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
#server 1
url=xxx
port=123

#server 100
url=xxx
port=123

#server 5
url=xxx
port=123
      prop.setProperty("server1.url", host);
<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>
因为属性扩展了Hashtable,而Hashtable为您提供了它们自己的键值对的内部顺序,所以当您从属性对象生成属性文件时,条目将变得混乱。因为您希望键值以任意顺序排序,所以排序也不容易。我将使用代码生成初始值属性文件的版本,然后按所需顺序移动内容,并继续使用该属性文件。如果需要以编程方式生成属性文件,则需要编写代码来写入该文件,以替代属性的操作方式

#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呢

比如:

#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
#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
#server 1
url=xxx
port=123

#server 100
url=xxx
port=123

#server 5
url=xxx
port=123
      prop.setProperty("server1.url", host);
<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>

1.
192.168.1.1
6546
最大值
123
2.
192.168.2.1
6454
伙计
123
您可以基于以下内容创建架构:

<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。我希望它能帮助您,或者至少能给您一个想法。祝您好运。

如果您使用FileOutputStream,您可以创建输出文件并以您要求的格式直接写入。但是,如果您使用Properties,您将无法重复相同的键。

问题是什么?我想您会这样做的想要在同一个属性文件中包含两台服务器的属性。我说得对吗?是的@sonic,你说得对。这就是问题,如何使之成为可能。stackoverflow应该拒绝所有不包含以
+1结尾的句子的问题,也希望看到“聪明的字符串匹配”的更多细节(我想自己加上,但已经好几年没做了:()@user2240409您不能生成如下所示的属性文件吗?问题是应用程序的用户不懂技术,因此手动编辑配置文件对他们来说将是一个混乱。我知道您在说什么,我遇到了类似的问题,我最后创建了一个友好的Swing GUI来编辑xml文件。也许您可以尝试编辑pro如我所述,以图形方式在文件中写入行将是一件痛苦的事情,但您将获得预期的结果。