最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Java實(shí)現(xiàn)XML文件的解析與更新

 更新時(shí)間:2022年03月22日 10:22:09   作者:Linux中國(guó)  
配置文件可以有很多種格式,包括?INI、JSON、YAML?和?XML。每一種編程語(yǔ)言解析這些格式的方式都不同。本文將通過(guò)Java語(yǔ)言實(shí)現(xiàn)XML文件的解析與更新,需要的可以參考一下

在你使用 Java 編寫軟件時(shí)實(shí)現(xiàn)持久化配置。

當(dāng)你編寫一個(gè)應(yīng)用時(shí),你通常都會(huì)希望用戶能夠定制化他們和應(yīng)用交互的方式,以及應(yīng)用與系統(tǒng)進(jìn)行交互的方式。這種方式通常被稱為 “偏好preference” 或者 “設(shè)置setting”,它們被保存在一個(gè) “偏好文件” 或者 “配置文件” 中,有時(shí)也直接簡(jiǎn)稱為 “配置config”。配置文件可以有很多種格式,包括 INI、JSON、YAML 和 XML。每一種編程語(yǔ)言解析這些格式的方式都不同。本文主要討論,當(dāng)你在使用 Java 編程語(yǔ)言 來(lái)編寫軟件時(shí),實(shí)現(xiàn)持久化配置的方式。

選擇一個(gè)格式

編寫配置文件是一件相當(dāng)復(fù)雜的事情。我曾經(jīng)試過(guò)把配置項(xiàng)使用逗號(hào)分隔保存在一個(gè)文本文件里,也試過(guò)把配置項(xiàng)保存在非常詳細(xì)的 YAML 和 XML 中。對(duì)于配置文件來(lái)說(shuō),最重要是要有一致性和規(guī)律性,它們使你可以簡(jiǎn)單快速地編寫代碼,從配置文件中解析出數(shù)據(jù);同時(shí),當(dāng)用戶決定要做出修改時(shí),很方便地保存和更新配置。

目前有 幾種流行的配置文件格式。對(duì)于大多數(shù)常見(jiàn)的配置文件格式,Java 都有對(duì)應(yīng)的庫(kù)library。在本文中,我將使用 XML 格式。對(duì)于一些項(xiàng)目,你可能會(huì)選擇使用 XML,因?yàn)樗囊粋€(gè)突出特點(diǎn)是能夠?yàn)榘臄?shù)據(jù)提供大量相關(guān)的元數(shù)據(jù),而在另外一些項(xiàng)目中,你可能會(huì)因?yàn)?XML 的冗長(zhǎng)而不選擇它。在 Java 中使用 XML 是非常容易的,因?yàn)樗J(rèn)包含了許多健壯的 XML 庫(kù)。

XML 基礎(chǔ)

討論 XML 可是一個(gè)大話題。我有一本關(guān)于 XML 的書,它有超過(guò) 700 頁(yè)的內(nèi)容。幸運(yùn)的是,使用 XML 并不需要非常了解它的諸多特性。就像 HTML 一樣,XML 是一個(gè)帶有開(kāi)始和結(jié)束標(biāo)記的分層標(biāo)記語(yǔ)言,每一個(gè)標(biāo)記(標(biāo)簽)內(nèi)可以包含零個(gè)或更多數(shù)據(jù)。下面是一個(gè) XML 的簡(jiǎn)單示例片段:

<xml>
      <node>
        <element>Penguin</element>
      </node>
    </xml>

在這個(gè) 自我描述的self-descriptive 例子中,XML 解析器使用了以下幾個(gè)概念:

  • 文檔Document: 標(biāo)簽標(biāo)志著一個(gè) 文檔 的開(kāi)始, 標(biāo)簽標(biāo)志著這個(gè)文檔的結(jié)束。
  • 節(jié)點(diǎn)Node: 標(biāo)簽代表了一個(gè) 節(jié)點(diǎn)。
  • 元素Element: Penguin 中,從開(kāi)頭的 < 到最后的 > 表示了一個(gè) 元素。
  • 內(nèi)容Content: 在 元素里,字符串 Penguin 就是 內(nèi)容。

不管你信不信,只要了解了以上幾個(gè)概念,你就可以開(kāi)始編寫、解析 XML 文件了。

創(chuàng)建一個(gè)示例配置文件

要學(xué)習(xí)如何解析 XML 文件,只需要一個(gè)極簡(jiǎn)的示例文件就夠了。假設(shè)現(xiàn)在有一個(gè)配置文件,里面保存的是關(guān)于一個(gè)圖形界面窗口的屬性:

<xml>
      <window>
        <theme>Dark</theme>
        <fullscreen>0</fullscreen>
        <icons>Tango</icons>
    </window>
    </xml>

創(chuàng)建一個(gè)名為 ~/.config/DemoXMLParser 的目錄:

$ mkdir ~/.config/DemoXMLParser

在 Linux 中,~/.config 目錄是存放配置文件的默認(rèn)位置,這是在 自由桌面工作組 的規(guī)范中定義的。如果你正在使用一個(gè)不遵守 自由桌面工作組Freedesktop標(biāo)準(zhǔn)的操作系統(tǒng),你也仍然可以使用這個(gè)目錄,只不過(guò)你需要自己創(chuàng)建這些目錄了。

復(fù)制 XML 的示例配置文件,粘貼并保存為 ~/.config/DemoXMLParser/myconfig.xml 文件。

使用 Java 解析 XML

如果你是 Java 的初學(xué)者,你可以先閱讀我寫的 面向 Java 入門開(kāi)發(fā)者的 7 個(gè)小技巧。一旦你對(duì) Java 比較熟悉了,打開(kāi)你最喜愛(ài)的集成開(kāi)發(fā)工具(IDE),創(chuàng)建一個(gè)新工程。我會(huì)把我的新工程命名為 myConfigParser。

剛開(kāi)始先不要太關(guān)注依賴導(dǎo)入和異常捕獲這些,你可以先嘗試用 javax 和 java.io 包里的標(biāo)準(zhǔn) Java 擴(kuò)展來(lái)實(shí)例化一個(gè)解析器。如果你使用了 IDE,它會(huì)提示你導(dǎo)入合適的依賴。如果沒(méi)有,你也可以在文章稍后的部分找到完整的代碼,里面就有完整的依賴列表。

Path configPath = Paths.get(System.getProperty("user.home"), ".config", "DemoXMLParser");
    File configFile = new File(configPath.toString(), "myconfig.xml");
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = null;
    builder = factory.newDocumentBuilder();
    Document doc = null;
    doc = builder.parse(configFile);
    doc.getDocumentElement().normalize();

這段示例代碼使用了 java.nio.Paths 類來(lái)找到用戶的主目錄,然后在拼接上默認(rèn)配置文件的路徑。接著,它用 java.io.File 類來(lái)把配置文件定義為一個(gè) File 對(duì)象。

緊接著,它使用了 javax.xml.parsers.DocumentBuilder 和 javax.xml.parsers.DocumentBuilderFactory 這兩個(gè)類來(lái)創(chuàng)建一個(gè)內(nèi)部的文檔構(gòu)造器,這樣 Java 程序就可以導(dǎo)入并解析 XML 數(shù)據(jù)了。

最后,Java 創(chuàng)建一個(gè)叫 doc 的文檔對(duì)象,并且把 configFile 文件加載到這個(gè)對(duì)象里。通過(guò)使用 org.w3c.dom 包,它讀取并規(guī)范化了 XML 數(shù)據(jù)。

基本上就是這樣啦。理論上來(lái)講,你已經(jīng)完成了數(shù)據(jù)解析的工作??墒?,如果你不能夠訪問(wèn)數(shù)據(jù)的話,數(shù)據(jù)解析也沒(méi)有多少用處嘛。所以,就讓我們?cè)賮?lái)寫一些查詢,從你的配置中讀取重要的屬性值吧。

使用 Java 訪問(wèn) XML 的值

從你已經(jīng)讀取的 XML 文檔中獲取數(shù)據(jù),其實(shí)就是要先找到一個(gè)特定的節(jié)點(diǎn),然后遍歷它包含的所有元素。通常我們會(huì)使用多個(gè)循環(huán)語(yǔ)句來(lái)遍歷節(jié)點(diǎn)中的元素,但是為了保持代碼可讀性,我會(huì)盡可能少地使用循環(huán)語(yǔ)句:

NodeList nodes = doc.getElementsByTagName("window");
    for (int i = 0; i < nodes.getLength(); i++) {
     Node mynode = nodes.item(i);
     System.out.println("Property = " + mynode.getNodeName());
           
     if (mynode.getNodeType() == Node.ELEMENT_NODE) {
       Element myelement = (Element) mynode;
                 
       System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
       System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
       System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
     }
    }

這段示例代碼使用了 org.w3c.dom.NodeList 類,創(chuàng)建了一個(gè)名為 nodes 的 NodeList 對(duì)象。這個(gè)對(duì)象包含了所有名字匹配字符串 window 的子節(jié)點(diǎn),實(shí)際上這樣的節(jié)點(diǎn)只有一個(gè),因?yàn)楸疚牡氖纠渲梦募兄慌渲昧艘粋€(gè)。

緊接著,它使用了一個(gè) for 循環(huán)來(lái)遍歷 nodes 列表。具體過(guò)程是:根據(jù)節(jié)點(diǎn)出現(xiàn)的順序逐個(gè)取出,然后交給一個(gè) if-then 子句處理。這個(gè) if-then 子句創(chuàng)建了一個(gè)名為 myelement 的 Element 對(duì)象,其中包含了當(dāng)前節(jié)點(diǎn)下的所有元素。你可以使用例如 getChildNodes 和 getElementById 方法來(lái)查詢這些元素,項(xiàng)目中還 記錄了 其他查詢方法。

在這個(gè)示例中,每個(gè)元素就是配置的鍵。而配置的值儲(chǔ)存在元素的內(nèi)容中,你可以使用 .getTextContent 方法來(lái)提取出配置的值。

在你的 IDE 中運(yùn)行代碼(或者運(yùn)行編譯后的二進(jìn)制文件):

$ java ./DemoXMLParser.java
    Property = window
    Theme = Dark
    Fullscreen = 0
    Icon set = Tango

下面是完整的代碼示例:

package myConfigParser;
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NamedNodeMap;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    public class ConfigParser {
            public static void main(String[] args) {
                    Path configPath = Paths.get(System.getProperty("user.home"), ".config", "DemoXMLParser");
                    File configFile = new File(configPath.toString(), "myconfig.xml");
                    DocumentBuilderFactory factory =
                    DocumentBuilderFactory.newInstance();
                    DocumentBuilder builder = null;
                   
                    try {
                            builder = factory.newDocumentBuilder();
                    } catch (ParserConfigurationException e) {
                            e.printStackTrace();
                    }
           
                    Document doc = null;
           
                    try {
                            doc = builder.parse(configFile);
                    } catch (SAXException e) {
                            e.printStackTrace();
                    } catch (IOException e) {
                            e.printStackTrace();
                    }
            doc.getDocumentElement().normalize();
           
            NodeList nodes = doc.getElementsByTagName("window");
            for (int i = 0; i < nodes.getLength(); i++) {
               Node mynode = nodes.item(i);
               System.out.println("Property = " + mynode.getNodeName());
               
               if (mynode.getNodeType() == Node.ELEMENT_NODE) {
                   Element myelement = (Element) mynode;
                   System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
                   System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
                   System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
               } // close if
            } // close for
        } // close method
    } //close class

使用 Java 更新 XML

用戶時(shí)不時(shí)地會(huì)改變某個(gè)偏好項(xiàng),這時(shí)候 org.w3c.dom 庫(kù)就可以幫助你更新某個(gè) XML 元素的內(nèi)容。你只需要選擇這個(gè) XML 元素,就像你讀取它時(shí)那樣。不過(guò),此時(shí)你不再使用 .getTextContent 方法,而是使用 .setTextContent 方法。

updatePref = myelement.getElementsByTagName("fullscreen").item(0);
    updatePref.setTextContent("1");
    System.out.println("Updated fullscreen to " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());

這么做會(huì)改變應(yīng)用程序內(nèi)存中的 XML 文檔,但是還沒(méi)有把數(shù)據(jù)寫回到磁盤上。配合使用 javax 和 w3c 庫(kù),你就可以把讀取到的 XML 內(nèi)容寫回到配置文件中。

TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer xtransform;
    xtransform = transformerFactory.newTransformer();
    DOMSource mydom = new DOMSource(doc);
    StreamResult streamResult = new StreamResult(configFile);
    xtransform.transform(mydom, streamResult);

這么做會(huì)沒(méi)有警告地寫入轉(zhuǎn)換后的數(shù)據(jù),并覆蓋掉之前的配置。

下面是完整的代碼,包括更新 XML 的操作:

package myConfigParser;
    import java.io.File;
    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerException;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.Node;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    public class ConfigParser {
            public static void main(String[] args) {
                    Path configPath = Paths.get(System.getProperty("user.home"), ".config", "DemoXMLParser");
                    File configFile = new File(configPath.toString(), "myconfig.xml");
                    DocumentBuilderFactory factory =
                    DocumentBuilderFactory.newInstance();
                    DocumentBuilder builder = null;
                   
                    try {
                            builder = factory.newDocumentBuilder();
                    } catch (ParserConfigurationException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    }
           
                    Document doc = null;
           
                    try {
                            doc = builder.parse(configFile);
                    } catch (SAXException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    } catch (IOException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    }
            doc.getDocumentElement().normalize();
            Node updatePref = null;
    //        NodeList nodes = doc.getChildNodes();
            NodeList nodes = doc.getElementsByTagName("window");
            for (int i = 0; i < nodes.getLength(); i++) {
               Node mynode = nodes.item(i);
               System.out.println("Property = " + mynode.getNodeName());
               
               if (mynode.getNodeType() == Node.ELEMENT_NODE) {
                   Element myelement = (Element) mynode;
                   System.out.println("Theme = " + myelement.getElementsByTagName("theme").item(0).getTextContent());
                   System.out.println("Fullscreen = " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());
                   System.out.println("Icon set = " + myelement.getElementsByTagName("icons").item(0).getTextContent());
                   updatePref = myelement.getElementsByTagName("fullscreen").item(0);
                   updatePref.setTextContent("2");
                   System.out.println("Updated fullscreen to " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());          
               } // close if
               
            }// close for
            // write DOM back to the file
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer xtransform;
            DOMSource mydom = new DOMSource(doc);
            StreamResult streamResult = new StreamResult(configFile);
            try {
                    xtransform = transformerFactory.newTransformer();
                    xtransform.transform(mydom, streamResult);
            } catch (TransformerException e) {
                    e.printStackTrace();
            }
                           
        } // close method
    } //close class

如何保證配置不出問(wèn)題

編寫配置文件看上去是一個(gè)還挺簡(jiǎn)單的任務(wù)。一開(kāi)始,你可能會(huì)用一個(gè)簡(jiǎn)單的文本格式,因?yàn)槟愕膽?yīng)用程序只要寥寥幾個(gè)配置項(xiàng)而已。但是,隨著你引入了更多的配置項(xiàng),讀取或者寫入錯(cuò)誤的數(shù)據(jù)可能會(huì)給你的應(yīng)用程序帶來(lái)意料之外的錯(cuò)誤。一種幫助你保持配置過(guò)程安全、不出錯(cuò)的方法,就是使用類似 XML 的規(guī)范格式,然后依靠你用的編程語(yǔ)言的內(nèi)置功能來(lái)處理這些復(fù)雜的事情。

這也正是我喜歡使用 Java 和 XML 的原因。每當(dāng)我試圖讀取錯(cuò)誤的配置值時(shí),Java 就會(huì)提醒我。通常,這是由于我在代碼中試圖獲取的節(jié)點(diǎn),并不存在于我期望的 XML 路徑中。XML 這種高度結(jié)構(gòu)化的格式幫助了代碼保持可靠性,這對(duì)用戶和開(kāi)發(fā)者來(lái)說(shuō)都是有好處的。

以上就是基于Java實(shí)現(xiàn)XML文件的解析與更新的詳細(xì)內(nèi)容,更多關(guān)于Java XML解析 更新的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java實(shí)現(xiàn)桌面右下角彈窗效果

    java實(shí)現(xiàn)桌面右下角彈窗效果

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)桌面右下角彈窗效果,模仿類似于qq消息彈窗,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • idea左側(cè)的commit框設(shè)置顯示出來(lái)方式

    idea左側(cè)的commit框設(shè)置顯示出來(lái)方式

    在IDEA中顯示左側(cè)的commit框,首先通過(guò)File-Settings-Version Control-Commit進(jìn)行設(shè)置,然后勾選Use non-modal commit interface完成
    2025-01-01
  • 實(shí)戰(zhàn)講解Maven安裝及基本使用詳解

    實(shí)戰(zhàn)講解Maven安裝及基本使用詳解

    這篇文章主要介紹了實(shí)戰(zhàn)講解Maven安裝及基本使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 如何使用Spring?Boot設(shè)置上傳文件大小限制

    如何使用Spring?Boot設(shè)置上傳文件大小限制

    上傳文件是互聯(lián)網(wǎng)中常應(yīng)用的場(chǎng)景之一,最典型的情況就是上傳頭像等,下面這篇文章主要給大家介紹了關(guān)于如何使用Spring?Boot設(shè)置上傳文件大小限制的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • java實(shí)現(xiàn)事件委托模式的實(shí)例詳解

    java實(shí)現(xiàn)事件委托模式的實(shí)例詳解

    這篇文章主要介紹了java實(shí)現(xiàn)事件委托模式的實(shí)例詳解的相關(guān)資料,這里提供實(shí)例來(lái)說(shuō)明如何實(shí)現(xiàn)改功能,希望能幫助到大家理解這樣的模式,需要的朋友可以參考下
    2017-08-08
  • Java代碼是如何被CPU狂飆起來(lái)的

    Java代碼是如何被CPU狂飆起來(lái)的

    無(wú)論是剛剛?cè)腴TJava的新手還是已經(jīng)工作了的老司機(jī),恐怕都不容易把Java代碼如何一步步被CPU執(zhí)行起來(lái)這個(gè)問(wèn)題完全講清楚。本文就帶你詳細(xì)了解Java代碼到底是怎么運(yùn)行起來(lái)的。感興趣的同學(xué)可以參考閱讀
    2023-03-03
  • springMVC導(dǎo)出word模板的方法

    springMVC導(dǎo)出word模板的方法

    這篇文章主要為大家詳細(xì)介紹了springMVC導(dǎo)出word模板的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Spring Data JPA中的動(dòng)態(tài)查詢實(shí)例

    Spring Data JPA中的動(dòng)態(tài)查詢實(shí)例

    本篇文章主要介紹了詳解Spring Data JPA中的動(dòng)態(tài)查詢。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • Springboot 整合 Dubbo/ZooKeeper 實(shí)現(xiàn) SOA 案例解析

    Springboot 整合 Dubbo/ZooKeeper 實(shí)現(xiàn) SOA 案例解析

    這篇文章主要介紹了Springboot 整合 Dubbo/ZooKeeper 詳解 SOA 案例,需要的朋友可以參考下
    2017-11-11
  • 詳解批處理框架之Spring Batch

    詳解批處理框架之Spring Batch

    Spring Batch是一個(gè)輕量級(jí)的、完善的批處理框架,作為Spring體系中的一員,它擁有靈活、方便、生產(chǎn)可用的特點(diǎn)。在應(yīng)對(duì)高效處理大量信息、定時(shí)處理大量數(shù)據(jù)等場(chǎng)景十分簡(jiǎn)便。結(jié)合調(diào)度框架能更大地發(fā)揮Spring Batch的作用
    2021-06-06

最新評(píng)論

太湖县| 临高县| 辛集市| 福鼎市| 福鼎市| 桃源县| 报价| 简阳市| 石河子市| 梁河县| 道孚县| 秦安县| 镶黄旗| 苏州市| 云霄县| 汾阳市| 安国市| 日喀则市| 武清区| 毕节市| 平阴县| 宿松县| 共和县| 怀化市| 胶南市| 鄂温| 墨脱县| 福建省| 尉犁县| 林州市| 新竹市| 苏尼特右旗| 邵武市| 临沧市| 武乡县| 涡阳县| 内江市| 永平县| 大港区| 长岛县| 临武县|