<h4>形式の選択</h4>
<p>設定ファイルの作成はかなり複雑です。構成項目をカンマ区切りのテキスト ファイルに保存してみたり、構成項目を非常に冗長な YAML および XML で保存してみたりしました。構成ファイルの場合、最も重要なことは一貫性と規則性を持つことです。これにより、コードを簡単かつ迅速に記述し、構成ファイルのデータを解析できるようになります。同時に、ユーザーが変更を加える場合は、簡単に保存できます。そして設定を更新します。 </p>
<p>現在、一般的な構成ファイル形式がいくつかあります。最も一般的な構成ファイル形式に対応するライブラリが Java にあります。この記事では XML 形式を使用します。プロジェクトによっては、含まれるデータに関連するメタデータを豊富に提供できることがその優れた機能の 1 つであるため、XML の使用を選択する場合もありますが、他のプロジェクトでは、その冗長さのために XML を選択しない場合もあります。 Java にはデフォルトで堅牢な XML ライブラリが多数含まれているため、Java での XML の操作は非常に簡単です。 </p>
<h4>XML の基本</h4>
<p>XML についての議論は大きなトピックです。私は 700 ページを超える XML に関する本を持っています。幸いなことに、XML の操作には、その多くの機能についての詳しい知識は必要ありません。 HTML と同様に、XML は開始タグと終了タグを備えた階層化されたマークアップ言語であり、各タグには 0 個以上のデータを含めることができます。 XML の簡単なサンプル スニペットを次に示します。 </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:xml;"><xml>
<node>
<element>Penguin</element>
</node>
</xml></pre><div class="contentsignin">ログイン後にコピー</div></div><p> この自己記述的な例では、XML パーサーは次の概念を使用します。 </p><ul class=" list-paddingleft-2"><li><p>Documentation ドキュメント: <code> <xml></code> タグはドキュメントの始まりを示し、<code></xml></code> タグはこのドキュメントの終わりを示します。 </p></li><li><p>ノード ノード: <code><node></code> ラベルはノードを表します。 </p></li><li><p>要素: <code><element>ペンギン</element></code>、先頭 <code><</code> から最後の <code>></code> は要素を表します。 </p></li><li><p> コンテンツ: <code><element></code> 要素の文字列 <code>Penguin</code> がコンテンツです。 </p></li></ul><p>信じられないかもしれませんが、上記の概念を理解していれば、XML ファイルの作成と解析を始めることができます。 </p><h4>サンプル構成ファイルを作成する</h4><p>XML ファイルを解析する方法を学ぶために必要なのは、最小限のサンプル ファイルだけです。グラフィカル インターフェイス ウィンドウのプロパティを保存する構成ファイルがあるとします。 </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:xml;"><xml>
<window>
<theme>Dark</theme>
<fullscreen>0</fullscreen>
<icons>Tango</icons>
</window>
</xml></pre><div class="contentsignin">ログイン後にコピー</div></div><p> <code>~/.config/DemoXMLParser</code> という名前のディレクトリを作成します。 </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:bash;">$ mkdir ~/.config/DemoXMLParser</pre><div class="contentsignin">ログイン後にコピー</div></div><p>Linux の場合<code>~/.config</code> ディレクトリは、構成ファイルを保存するためのデフォルトの場所であり、Free Desktop Working Group の仕様で定義されています。 Freedesktop 標準に準拠していないオペレーティング システムを使用している場合でも、このディレクトリを使用できますが、これらのディレクトリを自分で作成する必要があります。 </p><p>XML サンプル構成ファイルをコピーし、貼り付けて、<code>~/.config/DemoXMLParser/myconfig.xml</code> ファイルとして保存します。 </p><h4>Java を使用して XML を解析する</h4><p>Java の初心者の方は、まず、初心者の Java 開発者向けに私が書いた 7 つのヒントを読んでください。 Java に慣れてきたら、お気に入りの統合開発ツール (IDE) を開いて新しいプロジェクトを作成します。新しいプロジェクトに <code>myConfigParser</code> という名前を付けます。 </p><p>最初は依存関係のインポートや例外キャッチにあまり注意を払わないでください。まず、<code>javax</code> および <code>java.io の標準 Java 拡張機能を使用してインスタンス化を試みることができます。 </code> パッケージ、パーサー。 IDE を使用している場合は、適切な依存関係をインポートするように求められます。そうでない場合は、依存関係の完全なリストを含む完全なコードをこの記事の後半で見つけることができます。 </p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:java;">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();</pre><div class="contentsignin">ログイン後にコピー</div></div><p>このサンプル コードでは、<code>java.nio.Paths</code> クラスを使用してユーザーのホーム ディレクトリを検索し、そのパスをデフォルトの構成ファイルに接続します。次に、<code>java.io.File</code> クラスを使用して、構成ファイルを <code>File</code> オブジェクトとして定義します。 </p><p>次に、2 つのクラス <code>javax.xml.parsers.DocumentBuilder</code> と <code>javax.xml.parsers.DocumentBuilderFactory</code> を使用して内部ドキュメント構造 Converter を作成します。プログラムは XML データをインポートして解析できます。 </p><p>最後に、Java は <code>doc</code> というドキュメント オブジェクトを作成し、<code>configFile</code> ファイルをこのオブジェクトにロードします。 <code>org.w3c.dom</code> パッケージを使用して、XML データを読み取り、正規化します。 </p><p>基本的にはそれだけです。理論的には、データ分析作業は完了しました。ただし、データにアクセスできない場合、データ解析はほとんど役に立ちません。そこで、構成から重要なプロパティ値を読み取るためのクエリをさらにいくつか書いてみましょう。 </p><h4>使用 Java 访问 XML 的值</h4><p>从你已经读取的 XML 文档中获取数据,其实就是要先找到一个特定的节点,然后遍历它包含的所有元素。通常我们会使用多个循环语句来遍历节点中的元素,但是为了保持代码可读性,我会尽可能少地使用循环语句:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:java;">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());
}
}</pre><div class="contentsignin">ログイン後にコピー</div></div><p>这段示例代码使用了 <code>org.w3c.dom.NodeList</code> 类,创建了一个名为 <code>nodes</code> 的 <code>NodeList</code> 对象。这个对象包含了所有名字匹配字符串 <code>window</code> 的子节点,实际上这样的节点只有一个,因为本文的示例配置文件中只配置了一个。</p><p>紧接着,它使用了一个 <code>for</code> 循环来遍历 <code>nodes</code> 列表。具体过程是:根据节点出现的顺序逐个取出,然后交给一个 <code>if-then</code> 子句处理。这个 <code>if-then</code> 子句创建了一个名为 <code>myelement</code> 的 <code>Element</code> 对象,其中包含了当前节点下的所有元素。你可以使用例如 <code>getChildNodes</code> 和 <code>getElementById</code> 方法来查询这些元素,项目中还 记录了 其他查询方法。</p><p>在这个示例中,每个元素就是配置的键。而配置的值储存在元素的内容中,你可以使用 <code>.getTextContent</code> 方法来提取出配置的值。</p><p>在你的 IDE 中运行代码(或者运行编译后的二进制文件):</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:java;">$ java ./DemoXMLParser.java
Property = window
Theme = Dark
Fullscreen = 0
Icon set = Tango</pre><div class="contentsignin">ログイン後にコピー</div></div><p>下面是完整的代码示例:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:java;">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</pre><div class="contentsignin">ログイン後にコピー</div></div><h4>使用 Java 更新 XML</h4><p>用户时不时地会改变某个偏好项,这时候 <code>org.w3c.dom</code> 库就可以帮助你更新某个 XML 元素的内容。你只需要选择这个 XML 元素,就像你读取它时那样。不过,此时你不再使用 <code>.getTextContent</code> 方法,而是使用 <code>.setTextContent</code> 方法。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:java;">updatePref = myelement.getElementsByTagName("fullscreen").item(0);
updatePref.setTextContent("1");
System.out.println("Updated fullscreen to " + myelement.getElementsByTagName("fullscreen").item(0).getTextContent());</pre><div class="contentsignin">ログイン後にコピー</div></div><p>这么做会改变应用程序内存中的 XML 文档,但是还没有把数据写回到磁盘上。配合使用 <code>javax</code> 和 <code>w3c</code> 库,你就可以把读取到的 XML 内容写回到配置文件中。</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:java;">TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer xtransform;
xtransform = transformerFactory.newTransformer();
DOMSource mydom = new DOMSource(doc);
StreamResult streamResult = new StreamResult(configFile);
xtransform.transform(mydom, streamResult);</pre><div class="contentsignin">ログイン後にコピー</div></div><p>这么做会没有警告地写入转换后的数据,并覆盖掉之前的配置。</p><p>下面是完整的代码,包括更新 XML 的操作:</p><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:java;">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</pre><div class="contentsignin">ログイン後にコピー</div></div><h4>如何保证配置不出问题</h4>
<p>编写配置文件看上去是一个还挺简单的任务。一开始,你可能会用一个简单的文本格式,因为你的应用程序只要寥寥几个配置项而已。但是,随着你引入了更多的配置项,读取或者写入错误的数据可能会给你的应用程序带来意料之外的错误。一种帮助你保持配置过程安全、不出错的方法,就是使用类似 XML 的规范格式,然后依靠你用的编程语言的内置功能来处理这些复杂的事情。</p>
<p>这也正是我喜欢使用 Java 和 XML 的原因。每当我试图读取错误的配置值时,Java 就会提醒我。通常,这是由于我在代码中试图获取的节点,并不存在于我期望的 XML 路径中。XML 这种高度结构化的格式帮助了代码保持可靠性,这对用户和开发者来说都是有好处的。</p>
以上がJava 永続性 XML ファイルの構成方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。