2013-09-29 34 views
0

我很少聊天客户端软件使用XML文件来存储聊天记录,我的处理读/写类是:的Java存储/读取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字符specified.``

和读取异常,当Filling exception 例外这里是java.lang.NullPointerException

任何我我怎么能保证这不会发生?问题是这样的基本上打破了整个客户端当前

回答

1

而不是

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

总是请使用

e.printStackTrace(); 

或正确的日志框架,像log4j的,并登录正确的错误:

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

为什么这很重要?

,因为这样做,你可能会为我们提供了完整的堆栈跟踪...

此外,转义字符串用作XML内容,这是明智的使用已经写得很好,证明像在Apache commons StringEscapeUtils工具,而不是重新发明轮子

编辑

从OP的评论

哦,谢谢,我现在可以看到,误差在getTagValue()

有对于NPE在这里的多种可能性,但cuplrit是在这一行

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

下可以为空

eElement.getElementsByTagName(sTag).item(0) 

如果文档中没有该名称的标签。

the documentation

返回集合中第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 
} 

另外要注意的是现在这个返回一个空字符串,这可能会或可能不会好:它可以去那说节点被忽视不存在...

+0

哦,谢谢,我现在可以看到该错误是在'getTagValue()' – Alosyius

+0

而其铸造'java.lang.NullPointerException' – Alosyius

+0

@Alosyius:检查出来,我更新了答案 – ppeterka