0

私の小さなチャット クライアント ソフトウェアは、XML ファイルを使用してチャット履歴を保存します。読み書きを処理するクラスは次のとおりです。

public class History {

    public String filePath;

    public History(String filePath) {
        this.filePath = filePath;
    }

    public String stripNonValidXMLCharacters(String in ) {
        StringBuffer out = new StringBuffer(); // Used to hold the output.
        char current; // Used to reference the current character.

        if ( in == null || ("".equals( in ))) return ""; // vacancy test.
        for (int i = 0; i < in .length(); i++) {
            current = in .charAt(i); // NOTE: No IndexOutOfBoundsException caught here; it should not happen.
            if ((current == 0x9) ||
                (current == 0xA) ||
                (current == 0xD) ||
                ((current >= 0x20) && (current <= 0xD7FF)) ||
                ((current >= 0xE000) && (current <= 0xFFFD)) ||
                ((current >= 0x10000) && (current <= 0x10FFFF)))
                out.append(current);
        }
        return out.toString();
    }

    public synchronized void addMessage(String from, String agentName, String msg, String time, String channel) {
        try {
            DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
            org.w3c.dom.Document doc = docBuilder.parse(filePath);

            Node data = doc.getFirstChild();

            org.w3c.dom.Element root = doc.createElement(channel);
            org.w3c.dom.Element message = doc.createElement("message");
            org.w3c.dom.Element _sender = doc.createElement("sender");
            _sender.setTextContent(stripNonValidXMLCharacters(from));
            org.w3c.dom.Element _content = doc.createElement("content");
            _content.setTextContent(stripNonValidXMLCharacters(msg));
            org.w3c.dom.Element _recipient = doc.createElement("recipient");
            _recipient.setTextContent(stripNonValidXMLCharacters(agentName));
            org.w3c.dom.Element _time = doc.createElement("time");
            _time.setTextContent(stripNonValidXMLCharacters(time));


            message.appendChild(_sender);
            message.appendChild(_content);
            message.appendChild(_recipient);
            message.appendChild(_time);
            root.appendChild(message);

            data.appendChild(root);

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult(new File(filePath));
            transformer.transform(source, result);

        } catch (Exception ex) {
            System.out.println(ex.getStackTrace());
            // This is being trown randomly
        }
    }

    public synchronized void getHistory(String channel) {
        try {
            File fXmlFile = new File(filePath);
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            org.w3c.dom.Document doc = dBuilder.parse(fXmlFile);
            doc.getDocumentElement().normalize();

            NodeList nList = doc.getElementsByTagName(channel);

            for (int temp = 0; temp < nList.getLength(); temp++) {
                Node nNode = nList.item(temp);
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                    org.w3c.dom.Element eElement = (org.w3c.dom.Element) nNode;

                    if (getTagValue("sender", eElement).contains("Serv1")) {
                        printServerMsg(getTagValue("content", eElement).replace("%27", "'"), "", getTagValue("time", eElement));
                    } else {
                        printMsg(getTagValue("content", eElement).replace("%27", "'"), getTagValue("sender", eElement), getTagValue("time", eElement));
                    }

                }
            }
        } catch (Exception ex) {
            System.out.println("Filling Exception");

            // This is also being trown
        }
    }

    public String getTagValue(String sTag, org.w3c.dom.Element eElement) {
        NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();
        Node nValue = (Node) nlList.item(0);
        return nValue.getNodeValue();
    }
}

私が取得している書き込み時の例外は次のとおりです: `INVALID_CHARACTER_ERR: 無効または不正な XML 文字が指定されています。

そして例外を読むときFilling exception ここでの例外はjava.lang.NullPointerException

これが起こらないことを保証する方法はありますか? 問題は、これが基本的に現在クライアント全体を壊していることです

4

1 に答える 1

1

それ以外の

System.out.println("Filling Exception");

常にどちらかを使用

e.printStackTrace();

または、log4j などの適切なログ フレームワークを使用して、エラーを適切にログに記録します。

log.error("Filling Exception", e);

何でこれが大切ですか?

これを行うことで、完全なスタック トレースを提供できたはずです...

また、文字列をエスケープして XML コンテンツとして使用するには、車輪を再発明するのではなく、 Apache コモンズの StringEscapeUtilsなど、すでに十分に作成された実績のあるユーティリティを使用するのが賢明です。

編集

OPコメントより

ああ、ありがとう、エラーが getTagValue() にあることがわかりました

ここで NPE には複数の可能性がありますが、cuplrit はこの行にあります

NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();

以下はnullにすることができます

eElement.getElementsByTagName(sTag).item(0)

ドキュメントにその名前のタグがない場合。

ドキュメントから:

コレクション内の index 番目のアイテムを返します。index がリスト内のノード数以上の場合、null が返されます。

したがって、メソッドを次のように書き直します。

public String getTagValue(String sTag, org.w3c.dom.Element eElement) {
    Node n = eElement.getElementsByTagName(sTag).item(0);
    if(e !=null) {
        NodeList nlList = n.getChildNodes();
        Node nValue = (Node) nlList.item(0);
        if(nValue != null) {
            return nValue.getNodeValue();
        }
    }
    return ""; // or return null; if that is more applicable to the use case
}

また、これは空の文字列を返すことに注意してください。これは良いことも悪いこともあります。ノードが存在しないことに気付かない可能性があります...

于 2013-09-29T13:30:39.650 に答える