最近遇到一項(xiàng)需求,要求把properties文件中的內(nèi)容讀取出來(lái)供用戶(hù)修改,修改完后需要再重新保存到properties文件中。很簡(jiǎn)單的需求吧,可問(wèn)題是Properties是繼承自HashTable的,直接通過(guò)keySet()、keys()或entrySet()方法對(duì)Properties中的元素進(jìn)行遍歷時(shí)取出來(lái)的內(nèi)容順序與properties文件中的順序不一致,這是問(wèn)題一;問(wèn)題二是就算取出來(lái)的時(shí)候是有序的,保存到文件中時(shí)又是無(wú)序的了。
創(chuàng)新互聯(lián)是一家專(zhuān)注于網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站建設(shè)與策劃設(shè)計(jì),汨羅網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)做網(wǎng)站,專(zhuān)注于網(wǎng)站建設(shè)十多年,網(wǎng)設(shè)計(jì)領(lǐng)域的專(zhuān)業(yè)建站公司;建站業(yè)務(wù)涵蓋:汨羅等地區(qū)。汨羅做網(wǎng)站價(jià)格咨詢(xún):18980820575
當(dāng)然,解決這兩個(gè)問(wèn)題的方法有很多。我最終采用的方法是自定義一個(gè)PropertiesUtil類(lèi),該類(lèi)繼承自Properties。PropertiesUtil提供一個(gè)返回由key按照存入順序組成的List的方法,getKeyList(),這樣問(wèn)題一就解決了。那如何保證getKeyList()方法返回的就是有序的key組成的集合呢?我查看了一下Properties方法的源碼,發(fā)現(xiàn)其setProperty()方法實(shí)際上就是調(diào)用了父類(lèi)HashTable的put()方法,其次Properties在從文件中加載內(nèi)容時(shí)是按照文件順序進(jìn)行讀取,然后調(diào)用父類(lèi)HashTable的put()方法進(jìn)行儲(chǔ)存。所以問(wèn)題的解決辦法就是PropertiesUtil持有一個(gè)私有的可以有序存儲(chǔ)key的集合,然后重寫(xiě)父類(lèi)的put()方法,在方法體中照常通過(guò)super.put()進(jìn)行屬性的存儲(chǔ),同時(shí)將key添加到存儲(chǔ)key的集合中。
Properties提供有save()方法和store()方法可以將當(dāng)前對(duì)象的內(nèi)容存放到指定的輸出流中,但它們的底層邏輯都是一樣的。通過(guò)調(diào)用keys()方法獲取一個(gè)Enumeration,然后對(duì)該Enumeration進(jìn)行遍歷,依次將對(duì)應(yīng)的key和value寫(xiě)入到輸出流中,所以要保證寫(xiě)入是有序的,就要保證遍歷keys()返回的Enumeration時(shí)取出的元素key是有序的。所以解決方法是重寫(xiě)keys()方法,保證遍歷返回的Enumeration時(shí)得到的key是有序的。
下面就示范怎么按順序讀properties文件,以及還得按原來(lái)的順序?qū)憄roperties文件。
package com.lxk.propertyFileTest; import java.util.*; /** * Created by lxk on 2017/5/2 */ public class OrderedProperties extends Properties { private static final long serialVersionUID = -4627607243846121965L; /** * 因?yàn)長(zhǎng)inkedHashSet有序,所以,key在調(diào)用put()的時(shí)候,存放到這里也就有序。 */ private final LinkedHashSet<Object> keys = new LinkedHashSet<>(); @Override public Enumeration<Object> keys() { return Collections.enumeration(keys); } /** * 在put的時(shí)候,只是把key有序的存到{@link OrderedProperties#keys} * 取值的時(shí)候,根據(jù)有序的keys,可以有序的取出所有value * 依然調(diào)用父類(lèi)的put方法,也就是key value 鍵值對(duì)還是存在hashTable里. * 只是現(xiàn)在多了個(gè)存key的屬性{@link OrderedProperties#keys} */ @Override public Object put(Object key, Object value) { keys.add(key); return super.put(key, value); } /** * 因?yàn)閺?fù)寫(xiě)了這個(gè)方法,在(方式一)的時(shí)候,才輸出有序。 * {@link MainOrder#printProp} */ @Override public Set<String> stringPropertyNames() { Set<String> set = new LinkedHashSet<>(); for (Object key : this.keys) { set.add((String) key); } return set; } /** * 因?yàn)閺?fù)寫(xiě)了這個(gè)方法,在(方式二)的時(shí)候,才輸出有序。 * {@link MainOrder#printProp} */ @Override public Set<Object> keySet() { return keys; } //這個(gè)就不設(shè)置有序了,因?yàn)樯婕暗紿ashTable內(nèi)部類(lèi):EntrySet,不好復(fù)寫(xiě)。 //public LinkedHashSet<Map.Entry<Object, Object>> entrySet() { // LinkedHashSet<Map.Entry<Object, Object>> entrySet = new LinkedHashSet<>(); // for (Object key : keys) { // // } // return entrySet; //} /** * 因?yàn)閺?fù)寫(xiě)了這個(gè)方法,在(方式四)的時(shí)候,才輸出有序。 * {@link MainOrder#printProp} */ @Override public Enumeration<?> propertyNames() { return Collections.enumeration(keys); } }
上面是繼承Java自帶的類(lèi),我們做的主要是實(shí)現(xiàn)有序,其他的還是原來(lái)的樣子就行。
看下整個(gè)的類(lèi)繼承關(guān)系:如下圖:
下面是main方法的類(lèi)。
package com.lxk.propertyFileTest; import java.io.*; import java.util.Enumeration; import java.util.Map; import java.util.Properties; import java.util.Set; /** * 讀寫(xiě)properties文件測(cè)試(帶順序的讀和寫(xiě)) * <p> * Created by lxk on 2017/5/2 */ public class MainOrder { public static void main(String[] args) { Properties prop = readOrderedPropertiesFile(); printProp(prop); writeOrderedPropertiesFile(prop); } /** * 輸出properties的key和value */ public static void printProp(Properties properties) { System.out.println("---------(方式一)------------"); for (String key : properties.stringPropertyNames()) { System.out.println(key + "=" + properties.getProperty(key)); } System.out.println("---------(方式二)------------"); Set<Object> keys = properties.keySet();//返回屬性key的集合 for (Object key : keys) { System.out.println(key.toString() + "=" + properties.get(key)); } System.out.println("---------(方式三)------------"); Set<Map.Entry<Object, Object>> entrySet = properties.entrySet();//返回的屬性鍵值對(duì)實(shí)體 for (Map.Entry<Object, Object> entry : entrySet) { System.out.println(entry.getKey() + "=" + entry.getValue()); } System.out.println("---------(方式四)------------"); Enumeration<?> e = properties.propertyNames(); while (e.hasMoreElements()) { String key = (String) e.nextElement(); String value = properties.getProperty(key); System.out.println(key + "=" + value); } } /** * 讀Properties文件(有序) */ private static Properties readOrderedPropertiesFile() { Properties properties = new OrderedProperties(); InputStreamReader inputStreamReader = null; try { InputStream inputStream = new BufferedInputStream(new FileInputStream("D:testOrder.properties")); //prop.load(in);//直接這么寫(xiě),如果properties文件中有漢子,則漢字會(huì)亂碼。因?yàn)槲丛O(shè)置編碼格式。 inputStreamReader = new InputStreamReader(inputStream, "utf-8"); properties.load(inputStreamReader); } catch (Exception e) { System.out.println(e.getMessage()); } finally { if (inputStreamReader != null) { try { inputStreamReader.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } } return properties; } /** * 寫(xiě)Properties文件(有序) */ private static void writeOrderedPropertiesFile(Properties properties) { properties.setProperty("phone", "10086"); OutputStreamWriter outputStreamWriter = null; try { //保存屬性到b.properties文件 FileOutputStream fileOutputStream = new FileOutputStream("order.properties", false);//true表示追加打開(kāi),false每次都是清空再重寫(xiě) //prop.store(oFile, "此參數(shù)是保存生成properties文件中第一行的注釋說(shuō)明文字");//這個(gè)會(huì)兩個(gè)地方亂碼 //prop.store(new OutputStreamWriter(oFile, "utf-8"), "漢字亂碼");//這個(gè)就是生成的properties文件中第一行的注釋文字亂碼 outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8"); properties.store(outputStreamWriter, "lll"); } catch (Exception e) { System.out.println(e.getMessage()); } finally { if (outputStreamWriter != null) { try { outputStreamWriter.close(); } catch (IOException e) { System.out.println(e.getMessage()); } } } } }
其實(shí)讀和寫(xiě),都和使用系統(tǒng)提供的類(lèi)的差別不大,只是現(xiàn)在讀到了我們自己寫(xiě)的子類(lèi)里面去了。
其他的代碼都是一樣樣的。
下面是讀的文件的內(nèi)容截圖:
再然后是,實(shí)際代碼運(yùn)行的結(jié)果截圖:
---------(方式一)------------ 1=11 2=22 3=33 4=44 5=55 6=66 7=77 8=88 9=99 10=18 11漢字=測(cè)試漢字以防亂碼產(chǎn)生 ---------(方式二)------------ 1=11 2=22 3=33 4=44 5=55 6=66 7=77 8=88 9=99 10=18 11漢字=測(cè)試漢字以防亂碼產(chǎn)生 ---------(方式三)------------ 11漢字=測(cè)試漢字以防亂碼產(chǎn)生 9=99 8=88 7=77 6=66 5=55 4=44 3=33 2=22 10=18 1=11 ---------(方式四)------------ 1=11 2=22 3=33 4=44 5=55 6=66 7=77 8=88 9=99 10=18 11漢字=測(cè)試漢字以防亂碼產(chǎn)生
額,太長(zhǎng)了,就不截圖了吧,就給把打印結(jié)果給展示一下得了。
可以看到,只有第三次是無(wú)序的,具體原因,我也在代碼里面解釋過(guò)了。
還有,就是生成的文件的截圖:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
文章名稱(chēng):Java代碼實(shí)現(xiàn)對(duì)properties文件有序的讀寫(xiě)的示例
標(biāo)題網(wǎng)址:http://jinyejixie.com/article12/pshddc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、電子商務(wù)、外貿(mào)建站、網(wǎng)站收錄、Google、網(wǎng)站導(dǎo)航
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)