xml文件解析成树状结构

package com.fcar.frameworks.utils;

import com.fcar.frameworks.core.GlobalVar;
import com.fcar.frameworks.utils.io.EncryptedInputStream;
import com.fcar.frameworks.utils.xjson.XJsonToXmlNodeParser;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Stack;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;


public class XmlFile {

   private XmlNode mRoot; //需要包装一层用于移植方便

// 因为需要记录文件名,因此这里屏蔽了这个方法,如果有问题,实在需要再开放
   /**
    * 构造函数,输入为文件输入流
    */
   private XmlFile(InputStream is) {
      mRoot = new Handler().parse(is);
   }

   /**
    * 构造函数,输入为文件名称
    *
    * @param fileName 文件名
    */
   public XmlFile(String fileName) {
      long time = System.currentTimeMillis();
      int whichXmlParserToUse = GlobalVar.getWhichXmlParserToUse();
      if (whichXmlParserToUse == 0)
         mRoot = new Handler().parse(fileName);
      else {
         File f = new File(fileName);
         XJsonToXmlNodeParser parser = null;
         InputStream inputStream = null;
         try {
            // 先尝试从外部数据库zip中读取文件
            inputStream = ZipFileManager.instance().getFileInputStream(fileName);
            if (inputStream == null) {
               if (f.exists())
                  inputStream = new FileInputStream(f);
               else
                  inputStream = GlobalVar.getContext().getAssets().open(fileName);
            }
            parser = new XJsonToXmlNodeParser(new EncryptedInputStream(new BufferedInputStream(inputStream))); // 使用BufferedInputStream提升IO速度
            mRoot = parser.parse();
         } catch (IOException e) {
            mRoot = null;
            return;
         } finally {
            if (parser != null)
               parser.close();
            if (inputStream != null)
               try {
                  inputStream.close();
               } catch (IOException e) {
                  e.printStackTrace();
               }
            // inputStream在parser.close中没有关闭
         }
      }
      time = System.currentTimeMillis() - time;
      L.i("XmlFile", "It takes " + time + " milliseconds to parse " + fileName);
   }

   /**
    * 获取根节点
    *
    * @return 该Xml文件的根节点
    */
   public XmlNode getRoot() {
      return mRoot;
   }

}

class Handler extends DefaultHandler {
   private final Boolean DBG = true;
   private XmlNode root;
   private Stack<XmlNode> tmp;
   private String tmpStr;

   /**
    * 解析Xml文件,输入为文件名称
    *
    * @param fileName 文件名,如果未找到,则尝试从Assets中寻找
    * @return Xml根节点
    */
   public XmlNode parse(String fileName) {
      if (fileName == null)
         return null;
      root = null;
      try {
         L.i("XmlFile", "open file --> " + fileName);
         File f = new File(fileName);
         if (f.exists()) {
            return parse(new FileInputStream(f));
         }
         return parse(GlobalVar.getContext().getAssets().open(fileName));
      } catch (FileNotFoundException e) {
         L.e("Error", "File not found --> " + fileName);
         //e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
      return null;
   }

   /**
    * 处理文件,输入为文件流
    *
    * @param is 输入数据流
    * @return Xml数据流的根节点
    */
   public XmlNode parse(InputStream is) {
      try {
         SAXParser p = SAXParserFactory.newInstance().newSAXParser();
         p.parse(is, this);
         if (tmp.size() != 0) {
            L.e("com.fcar", "error tmp != 0");
            return null;
         }
         tmp = null;
         tmpStr = null;
         return root;
      } catch (ParserConfigurationException | SAXException | IOException e) {
         e.printStackTrace();
      } finally {
         if (is != null)
            try {
               is.close();
            } catch (IOException e) {
               e.printStackTrace();
            }
      }
      return null;
   }

   @Override
   public void startDocument() throws SAXException {
      tmp = new Stack<XmlNode>();
   }

   @Override
   public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
      XmlNode n;
      //L.i("com.fcar.start", uri + " " + localName + " " + qName);
      if (tmp.size() > 0) {
         n = new XmlNode(qName, tmp.peek(), attributes);
         n.getParent().addChild(n);
         tmp.push(n);
      } else {
         n = new XmlNode(qName, null, attributes);
         root = n;
         tmp.push(n);
      }
      tmpStr = "";
   }

   @Override
   public void characters(char[] ch, int start, int length) throws SAXException {
      //有特殊字符,所以更改成这样
      tmpStr += new String(ch, start, length).trim();
      //tmp.peek().setText(new String(ch, start,length).trim());
      //L.i("com.fcar.char", tmp.peek().getText());
   }

   @Override
   public void endElement(String uri, String localName, String qName) throws SAXException {
      //L.i("com.fcar.end", uri + " " + localName + " " + qName);
      tmp.peek().setText(tmpStr);
      tmpStr = "";
      //检查语法 可以优化掉
      if (DBG) {
         XmlNode p = tmp.peek();
         if (!p.getName().equals(qName))
            L.e("com.fcar.end", p.getName() + " != " + qName);
      }
      //
      tmp.pop();
   }

}

--------------------------------------

package com.fcar.frameworks.utils;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.xml.sax.Attributes;


public class XmlNode implements Serializable {
// private static final long serialVersionUID = 352135146221453293L;

   private XmlNode mParent;
   private XmlNodeList mChildren;

   String mName;
   String mText;

   HashMap<String, String> mAttrs;

   public XmlNode(String name, XmlNode parent, Attributes attrs) {
      mParent = parent;
      mChildren = new XmlNodeList();
      mAttrs = new HashMap<String, String>();
      for (int i = 0; i < attrs.getLength(); i++) {
         mAttrs.put(attrs.getQName(i), attrs.getValue(i));
      }
      mName = name;
   }

   public XmlNode(String name, XmlNode parent) {
      mParent = parent;
      mChildren = new XmlNodeList();
      mAttrs = new HashMap<String, String>();
      mName = name;
   }

   public XmlNode() {
      mParent = null;
      mChildren = new XmlNodeList();
      mAttrs = new HashMap<String, String>();
      mName = "NoName";
   }

   public void addChild(XmlNode child) {
      mChildren.add(child);
   }

   //设置文本
   public void setText(String text) {
      mText = text;
   }

   //获取文本
   public String getText() {
      return mText;
   }

   //获取节点名称
   public String getName() {
      return mName;
   }

   //获取父节点
   public XmlNode getParent() {
      return mParent;
   }

   //获取指定名称的第一个子结点
   public XmlNode getChild(String name) {
      return mChildren.find(name);
   }

   //获取所有的子节点
   public XmlNodeList getChildren() {
      return mChildren;
   }

   public XmlNodeList getChildren(String name) {
      XmlNodeList list = new XmlNodeList();
      for (int i = 0; i < mChildren.getLength(); i++) {
         XmlNode n = mChildren.item(i);
         if (name.equals(n.getName())) {
            list.add(n);
         }
      }
      return list;
   }

   public boolean hasAttr(String attrName) {
      return mAttrs.containsKey(attrName);
   }

   public boolean hasChild(String childName) {
      return getChild(childName) != null;
   }

   public boolean hasChildren() {
      return mChildren.getList().isEmpty();
   }

   //获取制定名称的属性
   public String getAttr(String attrName) {
      return mAttrs.get(attrName);
   }

// public Map<String, String> getAttrs() {
//    return mAttrs;
// }

   //设置属性值
   public void setAttr(String attrName, String val) {
      mAttrs.put(attrName, val);
   }

   public void setParent(XmlNode parent) {
      mParent = parent;
   }

   public void setName(String name) {
      mName = name;
   }

   /**
    * 获取该节点所在的Xml树的根节点
    * @return 该节点所在的Xml树的根节点
    */
   public XmlNode getRoot() {
      XmlNode root = this;
      while (root.getParent() != null)
         root = root.getParent();
      return root;
   }

   /**
    * (在本节点所在的xml树内)传入一个Xml节点路径,传出该路径所描述的节点。
    * @param path 描述一个节点的字符串。该字符串是一串以斜杠(/)分隔开的xml节点名。不需要传入根节点名。如果要使用根节点,则传入空字符串或者"/"。
    *             例如:根节点(AUTO)--->子节点1(NODE1)----> 子节点2(NODE2)。其所对应的XmlPath字符串为"/NODE1/NODE2"或者"NODE1/NODE2"
    * @return 指定Xml节点
    */
   public XmlNode getXmlNodeByPath(String path) {
      XmlNode root = getRoot();
      String[] paths = path.split("/");

      if (paths.length == 0)
         return root;
      if (paths[0].isEmpty()) {
         for (int i = 1; i < paths.length; ++i) {
            root = root.getChild(paths[i]);
         }
      } else {
         for (int i = 0; i < paths.length; ++i) {
            root = root.getChild(paths[i]);
         }
      }
      return root;
   }

   public String getXmlPath() {
      StringBuilder sb = new StringBuilder();
      getXmlPath(sb);
      return sb.toString();
   }

   private void getXmlPath(StringBuilder sb) {
      XmlNode parent = getParent();
      if (parent != null)
         parent.getXmlPath(sb);
      sb.append('/').append(getName());
   }

}
---------------------------------------------

package com.fcar.frameworks.utils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class XmlNodeList implements Serializable {
//    private static final long serialVersionUID = 8516515565121423132L;
private List<XmlNode> mList;
   
   public XmlNodeList()
   {
      mList = new ArrayList<XmlNode>();
   }

   public List<XmlNode> getList(){
      return mList;
   }

   public XmlNode find(String name)
   {
      for(int i =0; i<mList.size(); i++)
      {
         if(mList.get(i).getName().equals(name))
            return item(i);
      }
      return null;
   }
   public void add(XmlNode n)
   {
      mList.add(n);
   }

   //获取并列节点个数
   public int getLength()
   {
      return mList.size();
   }

   //获取其中的一个节点
   public XmlNode item(int index)
   {
      return mList.get(index);
   }
}
----------------------------------------

package com.fcar.frameworks.utils.xjson;

import com.fcar.frameworks.core.GlobalVar;
import com.fcar.frameworks.utils.io.DoubleBuffer;
import com.fcar.frameworks.utils.WordBuilder;
import com.fcar.frameworks.utils.XmlNode;

import java.io.*;
import java.util.Stack;

/**
 * 将XJson文件解析成{@link XmlNode} 对象的工具类<br/>
 * Created by carl on 2016/4/7.
 */
public class XJsonToXmlNodeParser implements Closeable {
   private static final String TAG = "XJsonParser";

   private static final int EXPECT_TYPE_STRING = 1;
   private static final int EXPECT_TYPE_SQUARE_BRACKET_START = 2;
   private static final int EXPECT_TYPE_SQUARE_BRACKET_END = 4;
   private static final int EXPECT_TYPE_COLON = 8;
   private static final int EXPECT_TYPE_CURLY_BRACE_START = 16;
   private static final int EXPECT_TYPE_CURLY_BRACE_END = 32;
   private static final int EXPECT_TYPE_COMMA = 64;
   private static final int EXPECT_TYPE_NAME_STRING = 128;
   private static final int EXPECT_TYPE_TEXT_STRING = 256;
   private static final int EXPECT_TYPE_COLON_BEFORE_TEXT = 512;

   private static final char START_CURLY_BRACE = '{';
   private static final char END_CURLY_BRACE = '}';
   private static final char START_SQUARE_BRACKET = '[';
   private static final char END_SQUARE_BRACKET = ']';
   private static final char COLON = ':';
   private static final char BACK_SLASH = '\\';
   private static final char QUOTATION = '"';
   private static final char COMMA = ',';

   private DoubleBuffer doubleBuffer;

   /**
    * 存储当前正在处理的对象的栈
    */
   private Stack<XmlNode> stack;

   // 以下变量用于类内建输入流,解析完毕时自动关闭输入流
   private InputStream inputStream;

   public XJsonToXmlNodeParser(InputStream is) throws IOException {
      this.stack = new Stack<>();
      this.doubleBuffer = new DoubleBuffer(is);
   }

   /**
    * 本方法不能读取被加密的文件
    * @param fileName #
    * @throws IOException #
    */
   public XJsonToXmlNodeParser(String fileName) throws IOException {
      File f = new File(fileName);
      if (f.exists())
         inputStream = new FileInputStream(f);
      else
         inputStream = GlobalVar.getContext().getAssets().open(fileName);
      this.stack = new Stack<>();
      this.doubleBuffer = new DoubleBuffer(new BufferedInputStream(inputStream));
   }

   @Override
   public void close() {
      if (inputStream != null) {
         try {
            inputStream.close();
         } catch (IOException e) {
            e.printStackTrace();
         }
         inputStream = null;
      }
   }

   /**
    * 解析XJson字符流,解析直到一个对象解析完或者字符流结束。换句话说处理一个花括号对。
    * @return 解析出来的对应的XmlNode
    * @throws IOException #
    */
   public XmlNode parse() throws IOException {
      if (this.doubleBuffer == null)
         return null;

      int ch;
      int expectedType = EXPECT_TYPE_CURLY_BRACE_START;
      while ((ch = doubleBuffer.read()) != -1) {
         if (Character.isWhitespace(ch))
            continue;
         if (ch == START_CURLY_BRACE) {
            if ((expectedType & EXPECT_TYPE_CURLY_BRACE_START) != 0) {
               onStartObject();
               expectedType = EXPECT_TYPE_NAME_STRING;
            } else {
               throw new XJsonSyntaxException();
            }
         } else if (ch == END_CURLY_BRACE) {
            if ((expectedType & EXPECT_TYPE_TEXT_STRING) != 0) {
               // 没有读取到可选的text值就遇到了反花括号
               stack.peek().setText("");
               onEndObject();
               return stack.pop();
            } else if ((expectedType & EXPECT_TYPE_CURLY_BRACE_END) != 0) {
               onEndObject();
               return stack.pop();
            } else {
               throw new XJsonSyntaxException();
            }
         } else if (ch == START_SQUARE_BRACKET) {
            if ((expectedType & EXPECT_TYPE_SQUARE_BRACKET_START) != 0) {
               onStartArray();
               expectedType = EXPECT_TYPE_CURLY_BRACE_END;
            } else {
               throw new XJsonSyntaxException();
            }
         } else if (ch == COLON) {
            if ((expectedType & EXPECT_TYPE_COLON) != 0) {
               onMeetColon();
               expectedType = EXPECT_TYPE_STRING;
            } else if ((expectedType & EXPECT_TYPE_COLON_BEFORE_TEXT) != 0) {
               onMeetColonBeforeText();
               expectedType = EXPECT_TYPE_TEXT_STRING;
            } else {
               throw new XJsonSyntaxException();
            }
         } else if (ch == COMMA) {
            if ((expectedType & EXPECT_TYPE_TEXT_STRING) != 0) {
               // 没有读取到可选的text值就遇到了逗号
               stack.peek().setText("");
               expectedType = EXPECT_TYPE_SQUARE_BRACKET_START | EXPECT_TYPE_STRING;
            } else if ((expectedType & EXPECT_TYPE_COMMA) != 0) {
               expectedType = EXPECT_TYPE_SQUARE_BRACKET_START | EXPECT_TYPE_STRING;
            } else {
               throw new XJsonSyntaxException();
            }
         } else if (ch == QUOTATION) {
            // 是一般属性名或者属性值
            if ((expectedType & EXPECT_TYPE_STRING) != 0) {
               onStartString();
               if (isKey)
                  expectedType = EXPECT_TYPE_COMMA | EXPECT_TYPE_CURLY_BRACE_END;       // 属性值已经读取完毕
               else
                  expectedType = EXPECT_TYPE_COLON;                       // 属性名已经读取完毕
            } else if ((expectedType & EXPECT_TYPE_NAME_STRING) != 0) {             // 标签名
               onStartNameString();
               expectedType = EXPECT_TYPE_COLON_BEFORE_TEXT;
            } else if ((expectedType & EXPECT_TYPE_TEXT_STRING) != 0) {             // 标签内部文本值
               onStartTextString();
               expectedType = EXPECT_TYPE_COMMA | EXPECT_TYPE_CURLY_BRACE_END;
            } else {
               throw new XJsonSyntaxException();
            }
         } else {
            // 其它非空白字符
            throw new XJsonSyntaxException();
         }
      }

      throw new XJsonStreamEndsUnexpectlyException();
      // 理论上在读到数据流尾之前解析出XJson对象
   }
   
   /**
    * 获取指定字符转意以后的字符,目前并没有什么处理,转义符后面是什么字符就转意什么出来
    * @param ch 指定字符
    * @return 转意以后的字符
    */
   public char getEscapeCharacter(int ch) {
      return (char) ch;
   }

   protected void onStartObject() {
      stack.push(new XmlNode());
   }

   protected void onEndObject() {

   }

   protected void onStartArray() throws IOException {
      XmlNode parent = stack.peek();
      do {
         XmlNode child = parse();
         parent.addChild(child);
         child.setParent(parent);
         int ch;
         while ((ch = doubleBuffer.read()) != -1) {
            if (Character.isWhitespace(ch))
               continue;
            if (ch == COMMA)
               break;
            if (ch == END_SQUARE_BRACKET) {
               return;
            }
         }
      } while (true);
   }

   @SuppressWarnings("unused")
   protected void onEndArray() {

   }

   protected void onMeetColon() {

   }

   protected void onMeetColonBeforeText() {

   }

   private WordBuilder wb = new WordBuilder();
   private boolean isKey = true;     // true表示当前正在扫描的字符串是属性,否则表示值
   private String key = null;
   protected void onStartString() throws IOException {
      wb.clear();
      int ch;
      while ((ch = doubleBuffer.read()) != -1) {
         if (ch == BACK_SLASH) {
            ch = getEscapeCharacter(doubleBuffer.read());
            wb.append(ch);
         } else if (ch == QUOTATION) {
            // 在这里遇到引号("),说明遇到了字符串终结的引号
            break;
         } else {
            wb.append(ch);
         }
      }
      String string = wb.toString();
      if (isKey) {
         key = string;
         isKey = false;
      } else {
         stack.peek().setAttr(key, string);
         isKey = true;
      }
   }

   protected void onStartTextString() throws IOException {
      wb.clear();
      int ch;
      while ((ch = doubleBuffer.read()) != -1) {
         if (ch == BACK_SLASH) {
            ch = getEscapeCharacter(doubleBuffer.read());
            wb.append(ch);
         } else if (ch == QUOTATION) {
            // 在这里遇到引号(")说明,遇到了字符串终结的引号
            break;
         } else {
            wb.append(ch);
         }
      }
      String string = wb.toString();
      stack.peek().setText(string);
   }

   protected void onStartNameString() throws IOException {
      wb.clear();
      int ch;
      while ((ch = doubleBuffer.read()) != -1) {
         if (ch == BACK_SLASH) {
            ch = getEscapeCharacter(doubleBuffer.read());
            wb.append(ch);
         } else if (ch == QUOTATION) {
            // 在这里遇到引号(")说明,遇到了字符串终结的引号
            break;
         } else {
            wb.append(ch);
         }
      }
      String string = wb.toString();
      stack.peek().setName(string);
   }
}
---------------------------------------------------------------
package com.fcar.frameworks.utils.io;

import com.fcar.frameworks.utils.ByteEncryptor;

import java.io.IOException;
import java.io.InputStream;

/**
 * Created by carl on 2016/4/12.
 */
public class EncryptedInputStream extends InputStream implements EncryptionInterface {

   private InputStream inputStream;

   /**
    * 正文读到哪个字节了
    */
   private int count = 0;
   private int version;

   public EncryptedInputStream(InputStream is) throws IOException {
      inputStream = is;
      readVersion();
   }

   public void readVersion() throws IOException {
      byte[] buf = new byte[EncryptionInterface.HEADER_SIZE];
      if (inputStream.read(buf) != buf.length) {
         throw new EncryptedFileFormatException();
      }
      if (buf[0] != buf[1])
         throw new EncryptedFileFormatException();
      version = (buf[0] & 0xff) - 0x54;
      switch (version) {
         case 1:
            // 后面什么都不用管了
            break;
         default:
            throw new EncryptedFileFormatVersionUnsupported();
      }
   }

   @Override
   public int read() throws IOException {
      switch (version) {
         case 1:
            return readVersion1();
         default:
            // 不可能出现了
      }
      // 不可能走到这里
      return -1;
   }

   public int readVersion1() throws IOException {
      int aByte = inputStream.read();
      if (aByte == -1)
         return -1;
      aByte = ByteEncryptor.decrypt(aByte, count++);
      return aByte & 0xff;
   }

   @Override
   public int available() throws IOException {
      return inputStream.available();
   }
}
-----------------------------------------------------------------------------



package com.fcar.frameworks.utils;

/**
 * 该类要与发布工具的加密算法一致
 * Created by carl on 2016/4/12.
 */
public class ByteEncryptor {
   private static final int[] MAGIC_NUMBER = {
         0x376fac2, 0x339677BE           // 都要用偶数,不改变原数的奇偶性,通过原数据的奇偶性选择Magic Number
   };

   public static int hashKey(int key) {
//    return key * 99839 + 26573 & 0xfffffffe;
      return key & 0xfffffffe;
   }

   public static int encrypt(int toEncrypt, int key) {
      key = hashKey(key);
      // key的最低位丢弃,避免改变原数的奇偶性,通过原数据的奇偶性选择Magic Number
      return (toEncrypt ^ key) + MAGIC_NUMBER[(toEncrypt & 0x7fffffff) % MAGIC_NUMBER.length];
   }

   public static int decrypt(int toDecrypt, int key) {
      key = hashKey(key);
      // key的最低位丢弃,避免改变原数的奇偶性,通过原数据的奇偶性选择Magic Number
      return toDecrypt - MAGIC_NUMBER[(toDecrypt & 0x7fffffff) % MAGIC_NUMBER.length] ^ key;
   }
}
package com.fcar.frameworks.utils;

import com.fcar.frameworks.core.GlobalVar;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * 读取Zip文件内容的辅助类,目前仅用于读取数据库<br/>
 * Created by carl on 2016/4/20.
 */
public class ZipFileManager {
   private static ZipFileManager instance;

   static {
      L.e("ZipFile: " + GlobalVar.getCurrDatabase());
      instance = new ZipFileManager(new File(GlobalVar.getCurrDatabase()));
   }

   public static ZipFileManager instance() {
      return instance;
   }

   private ZipFile zipFile;

   private ZipFileManager(File zip) {
      try {
         zipFile = new ZipFile(zip);
      } catch (IOException e) {
         e.printStackTrace();
         zipFile = null;
      }
   }

   public InputStream getFileInputStream(String file) {
      if (zipFile == null)
         return null;
      ZipEntry entry = zipFile.getEntry(file);
      if (entry == null)
         return null;
      try {
         return zipFile.getInputStream(entry);
      } catch (IOException e) {
         return null;
      }
   }

   public void close() throws IOException {
      if (zipFile != null)
         zipFile.close();
   }
}
----------------------------------------------------
package com.fcar.frameworks.utils;

/**
 * Created by carl on 2016/4/7.
 */
public class WordBuilder {
   private static final int DEFAULT_SIZE = 4096;

   private char[] buffer;
   private int index;

   public WordBuilder(int bufferSize) {
      buffer = new char[bufferSize];
      index = 0;
   }

   public WordBuilder() {
      this(DEFAULT_SIZE);
   }

   public WordBuilder append(char ch) {
      if (fullFilled()) {
         char[] newBuf = new char[buffer.length * 2];
         System.arraycopy(buffer, 0, newBuf, 0, buffer.length);
         buffer = newBuf;
      }
      buffer[index++] = ch;
      return this;
   }

   public boolean fullFilled() {
      return index == buffer.length;
   }

   public WordBuilder append(int ch) {
      return append((char) ch);
   }

   public void clear() {
      index = 0;
   }

   public String toString() {
      return new String(buffer, 0, index);
   }
}
----------------------------------------------------------------
package com.fcar.frameworks.utils;

import java.math.BigDecimal;
import java.util.Random;

public class Hex {
   private Hex(){}
   public static boolean isHex(char c) {
      return (c>='0' && c <= '9') || (c>='a' && c <= 'f')|| (c>='A' && c <= 'F');
   }

   public static byte parseChar(char c) {
      if(c>='0' && c <= '9') return (byte)(c - '0');
      if(c>='a' && c <= 'f') return (byte)(c-'a'+10);
      if(c>='A' && c <= 'F') return (byte)(c-'A'+10);
      return 0;
   }

   public static int auto(String s){
      if(s.length() == 1) s = "0" + s;
      byte[] buf = Hex.parse(s);
      switch (buf.length){
         case 1: return buf[0]&0xff;
         case 2: return toShortB(buf)&0xffff;
         case 3:
         case 4: return toIntB(buf);
         default:
            break;
      }
      return 0;
   }

    //转换字符串到byte
    //例如 parseByte("5A") == (byte)0x5A
   public static byte parseByte(String s) {
      if(s == null || s.isEmpty()) return 0;
      if(s.length() == 1)
         return parseChar(s.charAt(0));
      
      return (byte)(parseChar(s.charAt(0)) * 0x10 + parseChar(s.charAt(1)));
   }

   public static BigDecimal paresBigdec(String s){
      BigDecimal b = new BigDecimal(0);
      if(s == null) return b;
      if(s.length() <= 15){
         L.e("Hex", "只转换长度大于15的字符串");
         return b;
      }
      byte[] bs = Hex.parse(s);
      for(byte bb: bs){
         b = b.multiply(new BigDecimal(0x100));
         b = b.add(new BigDecimal((int)bb&0xff));
      }
      return b;
   }
   public static long parseLong(String s){
      if(s == null) return 0;
      if(s.length() <= 8){
         L.e("Hex", "只转换长度大于8的字符串");
         return 0;
      }
      byte[] bs = Hex.parse(s);
      long result = 0;
      for(byte b: bs){
         result = (result << 8) + b;
      }
      return result;
   }
   public static int parseInt(String s)
   {
      if(s == null) return 0;
      if(s.length() != 8)
      {
         L.e("Hex", "只转换长度为8的字符串");
         return 0;
      }
      byte[] bs = Hex.parse(s);
      return (bs[0]&0xff)*0x1000000+(bs[1]&0xff)*0x10000+(bs[2]&0xff)*0x100+(bs[3]&0xff);
   }

    //转换字符串到byte数组
    //例如 parse("5A 5A") == { 0x5A, 0x5A};
    // parse("5A,5A") == {0x5A, 0x5A};
    // parse("0x5a,0x5a") == {0x5A, 0x5A};
   public static byte[] parse(String s)
   {
      byte[] res = new byte[s.length()/2];
      int c = 0;
      for(int i =0; i<s.length()-1; i++)
      {
         if(isHex(s.charAt(i)) && isHex(s.charAt(i+1)))
         {
            res[c++] = parseByte(s.substring(i));
            i++;
         }
         else if ((s.charAt(i) == '?') && (s.charAt(i+1) == '?')) {
            res[c++] = (byte) new Random().nextInt();
            i++;
         }
      }

      byte[] res2 = new byte[c];
      System.arraycopy(res, 0, res2, 0, c);
      return res2;
   }

    //转换byte数组到字符串
    //例如: byte[] b = {(byte)0xa5, (byte)0xa5};
    // toString(b).equels == "A5 A5 ";
   //@SuppressLint("DefaultLocale")
   public static String toString(byte[] b)
   {
      return toString(b, 0, b.length);
      
   }

    //@SuppressLint("DefaultLocale")
    public static String toString(byte[] b, int len)
    {
        return toString(b, 0, len);
    }

    //转换byte数组到字符串
    //与上面函数不同的是指定了转换的个数
   //@SuppressLint("DefaultLocale")
   public static String toString(byte[] b, int from, int len)
   {
      String res = "";
      
      for(int i = from; i<from+len; i++)
      {
         String hex = Integer.toHexString(b[i] & 0xFF);
         if(hex.length() == 1) hex = '0' + hex;
         
         res += hex.toUpperCase();
         res += " ";
      }
      
      return res;
   }

    //转换int 到byte数组 len=4
   //大端
    public static byte[] fromIntB(int val)
   {
      byte[] b = new byte[4];
      
      b[3] = (byte) (val & 0xff);
      b[2] = (byte) ((val>>8) & 0xff);
      b[1] = (byte) ((val>>16) & 0xff);
      b[0] = (byte) ((val>>24) & 0xff);
      return b;
   }

    //转换int 到byte数组 len=4
   //小端
    public static byte[] fromIntL(int val)
   {
      byte[] b = new byte[4];
      
      b[0] = (byte) (val & 0xff);
      b[1] = (byte) ((val>>8) & 0xff);
      b[2] = (byte) ((val>>16) & 0xff);
      b[3] = (byte) ((val>>24) & 0xff);
      return b;
   }

    //转换short 到byte数组 2字节 大端
    public static byte[] fromShortB(short val)
   {
      byte[] b = new byte[2];
      b[1] = (byte) (val & 0xff);
      b[0] = (byte) ((val>>8) & 0xff);
      return b;
   }

    //转换short 到byte数组, 2字节 小端
    public static byte[] fromShortL(short val) {
      byte[] b = new byte[2];
      b[0] = (byte) (val & 0xff);
      b[1] = (byte) ((val>>8) & 0xff);
      return b;
   }

    //转换4字节数组到int, 大端, 数组必须大于等于长度4, 函数不做检查
    public static int toIntB(byte[] bs) {
        int r0=0,r1, r2, r3;
      //if(bs == null || bs.length < 3) return -1;
      if(bs.length == 3)
        {
            r3 = ((int) bs[2]) & 0xff;
            r2 = ((int) bs[1]) & 0xff;
            r1 = ((int) bs[0]) & 0xff;
        }
        else
        {
            r3 = ((int) bs[3]) & 0xff;
            r2 = ((int) bs[2]) & 0xff;
            r1 = ((int) bs[1]) & 0xff;
            r0 = ((int) bs[0]) & 0xff;
        }
      
      return (r0<<24) | (r1<<16) | (r2 <<8) | r3;
   }

    //转换4字节到int, 小端, 数组必须大于等于长度4, 函数不做检查
   public static int toIntL(byte[] bs) {
        int r0, r1 , r2, r3 = 0;
        //if(bs == null || bs.length < 3) return -1;
        if(bs.length == 3)
        {
            r2 = ((int) bs[2]) & 0xff;
            r1 = ((int) bs[1]) & 0xff;
            r0 = ((int) bs[0]) & 0xff;
        }
        else {
            r3 = ((int) bs[3]) & 0xff;
            r2 = ((int) bs[2]) & 0xff;
            r1 = ((int) bs[1]) & 0xff;
            r0 = ((int) bs[0]) & 0xff;
        }
      
      return (r3<<24) | (r2<<16) | (r1 <<8) | r0;
   }

   public static short toShortB(byte[] bs) {
      int r1 = ((int)bs[1]) & 0xff;
      int r0 = ((int)bs[0]) & 0xff;

      return (short)(r0<<8 | r1);
   }

   public static short toShortL(byte[] bs) {
      int r1 = ((int)bs[1]) & 0xff;
      int r0 = ((int)bs[0]) & 0xff;

      return (short)(r1<<8 | r0);
   }

    //合并四个数组
   public static byte[] merge(byte[] b1, byte[] b2, byte[] b3, byte[] b4) {
      byte[] res = new byte[b1.length + b2.length + b3.length + b4.length];
      System.arraycopy(b1, 0, res, 0,  b1.length);
      System.arraycopy(b2, 0, res, b1.length, b2.length);
      System.arraycopy(b3, 0, res, b1.length+b2.length, b3.length);
      System.arraycopy(b4, 0, res, b1.length+b2.length+b3.length, b4.length);

      return res;
   }

    //合并三个数组
   public static byte[] merge(byte[] b1, byte[] b2, byte[] b3) {
      byte[] res = new byte[b1.length + b2.length + b3.length];
      System.arraycopy(b1, 0, res, 0,  b1.length);
      System.arraycopy(b2, 0, res, b1.length, b2.length);
      System.arraycopy(b3, 0, res, b1.length+b2.length, b3.length);
      return res;
   }

    //合并两个数组
   public static byte[] merge(byte[] b1, byte[] b2) {
      byte[] res = new byte[b1.length + b2.length];
      System.arraycopy(b1, 0, res, 0, b1.length);
      System.arraycopy(b2, 0, res, b1.length, b2.length);
      
      return res;
   }

    //复制source数组的内容到 dest
   public static int copy(byte[] dest, byte[] source) {
      return copy(dest, 0, source, 0, source.length);
   }

    //从spos位置复制source数组count长度的数据到dest位置destpos
   public static int copy(byte[] dest, int destpos, byte[] source, int spos, int count)
   {
      if(dest.length < destpos + count)
         count = dest.length - destpos;
      if(source.length < spos + count)
         count = source.length - spos;
      System.arraycopy(source, spos, dest, destpos, count);
      
      return count;
   }

   //一字节和 GetCrcOneAdd
   //一字节和取反 GetCreOneAddUn
   //一字节和取补 GetCrcOneAddRe
   //一字节异或 GetCrcOneXor
   //一字节CRC校验 GetCrcOneCrc
   //一字节除倒数第二位(也是校验和,少算一位即可) GetCrcOneDiv
   //benz 5bps 两字节校验和,低字节在前,高字节在后 GetCrcOneAdd2
   //卡特专用 pro_seekcat
   //gaz_0d倒数第三字节 校验 一字节取补 倒数第二字节为0x0d, gaz_0d
   //国产kwp协议, 2字节校验和,高字节在前 GetCrcOneAdd2
    private static byte toByte(int a) { return (byte)(a & 0xff);}
    private static int  toInt(byte a) { return (int)a & 0xff;   }

    public static byte[] getCrcOneAdd(byte[] data, int from, int len) {
        int res = 0;
        for(int i =from; i<from+len; i++)
            res += toInt(data[i]);
        return fromIntL(res);
    }
    public static byte getCrcOneAddUn(byte[] data, int from, int len) {
        int res = toInt(getCrcOneAdd(data, from, len)[0]);
        res = ~res;
        return toByte(res);
    }
    public static byte getCrcOneAddRe(byte[] data, int from, int len) {
        return toByte(getCrcOneAddUn(data, from, len) + 1);
    }
    public static byte getCrcOneXor(byte[] data, int from, int len) {
        int res = 0;
        for(int i=from; i<from+len; i++)
            res = res ^ data[i];
        return toByte(res);
    }
    public static byte getCrcOneCrc(byte[] data, int from, int len) {
        //L.i("getcrc "+ Hex.toString(data, from, len));
        byte res = 0x59;
        switch (len + 1)
        {
            case 6: res = 0x10; break;
            case 7: res = (byte)0xf6; break;
            case 8: res = 0x0a; break;
            case 9: res = (byte)0xe9; break;
            case 10:res = 0x7c; break;
            case 11:res = (byte)0xfe; break;
            case 12:res = (byte)0xe2; break;
        }
        int j = toInt(data[from]);
        int n;
        for(int i =1+from; i<from+len; i++) {
            for(int k=0; k<8; k++)
            {
                j = j << 1;
                n = (data[i]>>(7-k)) & 0x01;
                j += n;
                if(j>255) j = j ^ 285;
            }
        }
        for(int k=0; k<8; k++)
        {
            j = j << 1;
            n = (res>>(7-k)) & 0x01;
            j += n;
            if(j>255) j = j ^ 285;
        }
        //L.i("crc result:", Integer.toHexString(j));
        return toByte(j);
    }
// static public byte getCrc(byte val, byte crc) {
//    for (int i = 0; i < 8; i++) {
//       if(((val ^ crc) & 0x80) != 0) {
//          crc^= 0x0e;
//          crc = (byte)((crc << 1) | 1);
//       } else {
//          crc= (byte)(crc << 1);
//       }
//       val = (byte)(val << 1);
//    }
//    return crc;
// }
}
----------------------------------------------------------
package com.fcar.frameworks.utils.xjson;

/**
 * Created by carl on 2016/4/21.
 */
public class XJsonStreamEndsUnexpectlyException extends XJsonSyntaxException {
   public XJsonStreamEndsUnexpectlyException() {
   }

   public XJsonStreamEndsUnexpectlyException(String message) {
      super(message);
   }

   public XJsonStreamEndsUnexpectlyException(String message, Throwable cause) {
      super(message, cause);
   }

   public XJsonStreamEndsUnexpectlyException(Throwable cause) {
      super(cause);
   }
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值