2010-09-01 31 views
13

Tôi cần đọc tệp thuộc tính và tạo một lớp Thuộc tính trong Java. Tôi làm như vậy bằng cách sử dụng:Cách đọc tệp thuộc tính trong java theo thứ tự ban đầu

Properties props = new Properties(); 
props.load(new FileInputStream(args[0])); 
for (Enumeration e = props.propertyNames(); e.hasMoreElements();) { 
} 

Tuy nhiên, các thuộc tính được trả về bởi props.propertyName không theo thứ tự của tệp thuộc tính gốc. Tôi hiểu rằng Thuộc tính chỉ là phiên bản cũ, không được tổng hợp Hashtables. Tôi đang tìm một công việc xung quanh. Bất kỳ ý tưởng? Cảm ơn bạn!

+0

Bất kỳ lý do cụ thể mà các vấn đề trật tự? – Powerlord

+0

Tôi cần thực hiện các lớp dựa trên thứ tự trong tệp thuộc tính. – wen

+0

Nó thực sự được mở rộng, như là 'Hashtable ' (có một câu hỏi là tại sao đó là một nơi nào đó). –

Trả lời

6

Bạn có thể muốn triển khai lớp Thuộc tính của riêng mình với các chức năng tương tự. Bạn sẽ không thể nhận được đơn đặt hàng kể từ khi bạn đã chỉ ra, nó sử dụng Hashtable.

+7

Liên kết bị hỏng cho đề xuất. –

+0

Liên kết bị hỏng. hoặc là một quảng cáo –

2

Thực tế chúng được thể hiện dưới dạng Hashtable dưới mui xe có nghĩa là thứ tự của chúng không được giữ trong bất kỳ thời trang nào.

Tôi khuyên bạn nên đọc trình đọc thuộc tính "cuộn của riêng bạn" nếu bạn tuyệt đối tuyệt vọng cho chức năng này.

+2

Không có gì "dưới mui xe" về việc sử dụng 'Hashtable' -' Thuộc tính mở rộng Hashtable '. –

0

Thuộc tính lớp con để ghi nhớ thứ tự đọc và tạo một liệt kê sử dụng danh sách khóa đã đặt hàng?

13

Bạn có thể mở rộng Thuộc tính và ủy quyền tất cả phương thức bản đồ thành LinkedHashMap để giữ lại thứ tự. Dưới đây là ví dụ (bạn có thể cần phải ghi đè một số phương thức khác):

public class LinkedProperties extends Properties{ 


    private static final long serialVersionUID = 1L; 

    private Map<Object, Object> linkMap = new LinkedHashMap<Object,Object>(); 

    @Override 
    public synchronized Object put(Object key, Object value){ 
     return linkMap.put(key, value); 
    } 

    @Override 
    public synchronized boolean contains(Object value){ 
     return linkMap.containsValue(value); 
    } 

    @Override 
    public boolean containsValue(Object value){ 
     return linkMap.containsValue(value); 
    } 

    @Override 
    public synchronized Enumeration<Object> elements(){ 
     throw new UnsupportedOperationException(
      "Enumerations are so old-school, don't use them, " 
     + "use keySet() or entrySet() instead"); 
    } 

    @Override 
    public Set<Entry<Object, Object>> entrySet(){ 
     return linkMap.entrySet(); 
    } 

    @Override 
    public synchronized void clear(){ 
     linkMap.clear(); 
    } 

    @Override 
    public synchronized boolean containsKey(Object key){ 
     return linkMap.containsKey(key); 
    } 

} 
+0

Đẹp và đơn giản. Có thể được thực hiện đơn giản hơn bằng cách lưu trữ các giá trị trong cả 'super' và' linkMap' và sau đó chỉ có thể ghi đè các hoạt động sửa đổi và lặp lại. ví dụ. 'put' {linkedMap.put (khóa, giá trị); return super.put (khóa, giá trị); } – karmakaze

+0

Tôi sẽ đề nghị '@ Override' cũng' size() 'và' toString() ' –

+0

@ToKra rõ ràng là có. Cảm ơn –

16

Ví dụ từ www.java2s.com sẽ giải quyết vấn đề của bạn.

import java.util.Enumeration; 
import java.util.Properties; 
import java.util.Vector; 

/** 
* <a href="OrderedProperties.java.html"><b><i>View Source</i></b></a> 
* 
* @author Brian Wing Shun Chan 
* 
*/ 
public class OrderedProperties extends Properties { 

    public OrderedProperties() { 
     super(); 

     _names = new Vector(); 
    } 

    public Enumeration propertyNames() { 
     return _names.elements(); 
    } 

    public Object put(Object key, Object value) { 
     if (_names.contains(key)) { 
      _names.remove(key); 
     } 

     _names.add(key); 

     return super .put(key, value); 
    } 

    public Object remove(Object key) { 
     _names.remove(key); 

     return super .remove(key); 
    } 

    private Vector _names; 

} 

Và mã của bạn sẽ thay đổi để:

Properties props = new OrderedProperties(); 
props.load(new FileInputStream(args[0])); 
for (Enumeration e = props.propertyNames(); e.hasMoreElements();) { 
} 
+1

Bạn có thể muốn xem xét câu hỏi có thể được hiểu là có nghĩa là chúng tôi muốn đọc một tệp gốc không được tạo lập trình hoặc không được tạo bằng lớp OrderedProperties của bạn. Trong những trường hợp như vậy, giải pháp được cung cấp không phải là giải pháp. – H2ONaCl

+1

@broiyan Giải pháp này nên hoạt động bất kể cách tệp thuộc tính được tạo. – YoK

+0

Điều này hoạt động giống như một sự quyến rũ. Tôi đã sử dụng nó như sau: Properties properties = new OrderedProperties(); Bản đồ propertyFileMap = new LinkedHashMap <>(); Enzeration propertyKeyNames = (Liệt kê ) properties.propertyNames(); trong khi (propertyKeyNames.hasMoreElements()) { Thuộc tính chuỗiKey = propertyKeyNames.nextElement(); Thuộc tính chuỗiValue = properties.getProperty (propertyKey); propertyFileMap.put (propertyKey, propertyValue); } –

0

Để giải quyết vấn đề: "để thực hiện các lớp học dựa vào thứ tự nộp các thuộc tính" Tôi thường sử dụng một trong 2 khả năng:

1 - sử dụng một tài sản như một danh sách bằng dấu phẩy với đẳng cấp tên hoặc với các phím để định nghĩa lớp

loadClasses = lớp nét-A, lớp nét-B, lớp nét-C

hoặc (hữu ích nếu "định nghĩa" bao gồm nhiều hơn một tài sản)

loadClasses = Keya, keyB, keyC
Keya = lớp nét-A
keyB = lớp nét-B
keyC = lớp nét-C


2 - sử dụng một chìa khóa tiếp theo là một chỉ số (bộ đếm). Đọc các khóa trong vòng lặp cho đến khi không tìm thấy giá trị nào.

class1 = lớp nét-A
class2 = lớp nét-B
class3 = lớp nét-C

7

Tương tự như một trong những trên, nhưng w/out overhead duy trì danh sách giá trị riêng của chúng tôi. Tất cả những gì chúng ta phải làm là duy trì một danh sách các khóa được sắp xếp riêng biệt và cung cấp một phương thức "keys()" mới.


public class SequencedProperties extends Properties { 

    private static final long serialVersionUID = -7032434592318855760L; 

    private List keyList = new ArrayList(); 

    @Override 
    public synchronized Enumeration keys() { 
     return Collections.enumeration(keyList); 
    } 

    @Override 
    public synchronized Object put(Object key, Object value) { 
     if (! containsKey(key)) { 
      keyList.add(key); 
     } 

     return super.put(key, value); 
    } 

    @Override 
    public synchronized Object remove(Object key) { 
     keyList.remove(key); 

     return super.remove(key); 
    } 

    @Override 
    public synchronized void putAll(Map values) { 
     for (Object key : values.keySet()) { 
      if (! containsKey(key)) { 
       keyList.add(key); 
      } 
     } 

     super.putAll(values); 
    } 
} 
+0

Điều gì về, tại thời điểm này, bằng cách sử dụng một 'LinkedHashSet' và tránh tất cả những' containsKey'? – Campa

1

thực hiện đúng cách keySet:

public class OrderedProperties extends Properties { 

    private Set<Object> keySet = new LinkedHashSet<Object>(100); 

    @Override 
    public Enumeration<Object> keys() { 
    return Collections.enumeration(keySet); 
    } 

    @Override 
    public Set<Object> keySet() { 
    return keySet; 
    } 

    @Override 
    public synchronized Object put(Object key, Object value) { 
    if (! keySet.contains(key)) { 
     keySet.add(key); 
    } 
    return super.put(key, value); 
    } 

    @Override 
    public synchronized Object remove(Object key) { 
    keySet.remove(key); 
    return super.remove(key); 
    } 

    @Override 
    public synchronized void putAll(Map values) { 
    for (Object key : values.keySet()) { 
     if (! containsKey(key)) { 
      keySet.add(key); 
     } 
    } 
    super.putAll(values); 
    } 
} 
+0

Cuộc gọi Ihmo '.contains()' khá không liên quan ở đây, phải không? PS cho độc giả không phải người Nga: đáng sợ cyrillic _правильной реализацией_ có nghĩa là "thực hiện đúng"! – Campa

+0

Xin chào! chứa() được tốt đẹp để thêm. Đáng sợ cyrillic thay thế bằng tiếng anh tự nhiên :) – GKislin

+0

Tại sao các phương thức 'tải' không được ghi đè lên? – Stephan

3

thực hiện đầy đủ dựa trên LinkedHashMap

import java.util.*; 
import java.io.*; 

/** 
* Ordered properties implementation 
*/ 

public class LinkedProperties extends Properties{ 
    private static final long serialVersionUID = 1L; 

    private Map<Object, Object> linkMap = new LinkedHashMap<Object,Object>(); 

    public void clear(){ 
     linkMap.clear(); 
    } 
    public boolean contains(Object value){ 
     return linkMap.containsValue(value); 
    } 
    public boolean containsKey(Object key){ 
     return linkMap.containsKey(key); 
    } 
    public boolean containsValue(Object value){ 
     return linkMap.containsValue(value); 
    } 
    public Enumeration elements(){ 
     throw new RuntimeException("Method elements is not supported in LinkedProperties class"); 
    } 
    public Set entrySet(){ 
     return linkMap.entrySet(); 
    } 
    public boolean equals(Object o){ 
     return linkMap.equals(o); 
    } 
    public Object get(Object key){ 
     return linkMap.get(key); 
    } 
    public String getProperty(String key) { 
     Object oval = get(key); //here the class Properties uses super.get() 
     if(oval==null)return null; 
     return (oval instanceof String) ? (String)oval : null; //behavior of standard properties 
    } 
    public boolean isEmpty(){ 
     return linkMap.isEmpty(); 
    } 
    public Enumeration keys(){ 
     Set keys=linkMap.keySet(); 
     return Collections.enumeration(keys); 
    } 
    public Set keySet(){ 
     return linkMap.keySet(); 
    } 
    public void list(PrintStream out) { 
     this.list(new PrintWriter(out,true)); 
    } 
    public void list(PrintWriter out) { 
     out.println("-- listing properties --"); 
     for (Map.Entry e : (Set<Map.Entry>)this.entrySet()){ 
      String key = (String)e.getKey(); 
      String val = (String)e.getValue(); 
      if (val.length() > 40) { 
       val = val.substring(0, 37) + "..."; 
      } 
      out.println(key + "=" + val); 
     } 
    } 

    public Object put(Object key, Object value){ 
     return linkMap.put(key, value); 
    } 
    public int size(){ 
     return linkMap.size(); 
    } 
    public Collection values(){ 
     return linkMap.values(); 
    } 

    //for test purpose only 
    public static void main(String[] arg)throws Exception{ 
     Properties p0=new Properties(); 
     Properties p1=new LinkedProperties(); 
     p0.put("aaa","111"); 
     p0.put("bbb","222"); 
     p0.put("ccc","333"); 
     p0.put("ddd","444"); 

     p1.put("aaa","111"); 
     p1.put("bbb","222"); 
     p1.put("ccc","333"); 
     p1.put("ddd","444"); 

     System.out.println("\n--"+p0.getClass()); 
     p0.list(System.out); 
     p0.store(System.out,"comments"); 
     p0.storeToXML(System.out,"comments"); 
     System.out.println(p0.toString()); 

     System.out.println("\n--"+p1.getClass()); 
     p1.list(System.out); 
     p1.store(System.out,"comments"); 
     p1.storeToXML(System.out,"comments"); 
     System.out.println(p1.toString()); 
    } 
} 

Kết quả:

--class java.util.Properties 
-- listing properties -- 
bbb=222 
aaa=111 
ddd=444 
ccc=333 
#comments 
#Wed Apr 10 08:55:42 EEST 2013 
bbb=222 
aaa=111 
ddd=444 
ccc=333 
<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 
<properties> 
<comment>comments</comment> 
<entry key="bbb">222</entry> 
<entry key="aaa">111</entry> 
<entry key="ddd">444</entry> 
<entry key="ccc">333</entry> 
</properties> 
{bbb=222, aaa=111, ddd=444, ccc=333} 

--class groovy.abi.LinkedProperties 
-- listing properties -- 
aaa=111 
bbb=222 
ccc=333 
ddd=444 
#comments 
#Wed Apr 10 08:55:42 EEST 2013 
aaa=111 
bbb=222 
ccc=333 
ddd=444 
<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 
<properties> 
<comment>comments</comment> 
<entry key="aaa">111</entry> 
<entry key="bbb">222</entry> 
<entry key="ccc">333</entry> 
<entry key="ddd">444</entry> 
</properties> 
{aaa=111, bbb=222, ccc=333, ddd=444} 
+0

chỉ điều này làm việc cho tôi. Nó đã đọc các tệp thuộc tính trong các chuỗi thực tế. – linuxeasy

Các vấn đề liên quan