溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java持久化XML文件如何配置

發(fā)布時(shí)間:2023-05-04 11:04:20 來源:億速云 閱讀:95 作者:iii 欄目:編程語言

這篇文章主要介紹“Java持久化XML文件如何配置”,在日常操作中,相信很多人在Java持久化XML文件如何配置問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java持久化XML文件如何配置”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

選擇一個(gè)格式

編寫配置文件是一件相當(dāng)復(fù)雜的事情。我曾經(jīng)試過把配置項(xiàng)使用逗號分隔保存在一個(gè)文本文件里,也試過把配置項(xiàng)保存在非常詳細(xì)的 YAML 和 XML 中。對于配置文件來說,最重要是要有一致性和規(guī)律性,它們使你可以簡單快速地編寫代碼,從配置文件中解析出數(shù)據(jù);同時(shí),當(dāng)用戶決定要做出修改時(shí),很方便地保存和更新配置。目前有 幾種流行的配置文件格式。對于大多數(shù)常見的配置文件格式,Java 都有對應(yīng)的庫library。

XML 基礎(chǔ)

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

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

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

  • 文檔Document:<xml> 標(biāo)簽標(biāo)志著一個(gè) 文檔 的開始,</xml> 標(biāo)簽標(biāo)志著這個(gè)文檔的結(jié)束。

  • 節(jié)點(diǎn)Node:<node> 標(biāo)簽代表了一個(gè) 節(jié)點(diǎn)。

  • 元素Element:<element>Penguin</element> 中,從開頭的 < 到最后的 > 表示了一個(gè) 元素。

  • 內(nèi)容Content: 在 <element> 元素里,字符串 Penguin 就是 內(nèi)容。

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

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

要學(xué)習(xí)如何解析 XML 文件,只需要一個(gè)極簡的示例文件就夠了。假設(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è)目錄,只不過你需要自己創(chuàng)建這些目錄了。

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

使用 Java 解析 XML

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

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

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 類來找到用戶的主目錄,然后在拼接上默認(rèn)配置文件的路徑。接著,它用 java.io.File 類來把配置文件定義為一個(gè) File 對象。

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

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

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

使用 Java 訪問 XML 的值

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

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è)名為 nodesNodeList 對象。這個(gè)對象包含了所有名字匹配字符串 window 的子節(jié)點(diǎn),實(shí)際上這樣的節(jié)點(diǎn)只有一個(gè),因?yàn)楸疚牡氖纠渲梦募兄慌渲昧艘粋€(gè)。

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

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

在你的 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 庫就可以幫助你更新某個(gè) XML 元素的內(nèi)容。你只需要選擇這個(gè) XML 元素,就像你讀取它時(shí)那樣。不過,此時(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 文檔,但是還沒有把數(shù)據(jù)寫回到磁盤上。配合使用 javaxw3c 庫,你就可以把讀取到的 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ì)沒有警告地寫入轉(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
如何保證配置不出問題

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

到此,關(guān)于“Java持久化XML文件如何配置”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI