Android 解析 ByteArrayInputStream
Android彩信解码函数,需要从输入流中解析字段。
今天又看了一下pduparse中几个解析函数,在这里做个总结。
大概可以分为3类
一、解析字节
1.extractByteValue
protected static int extractByteValue(ByteArrayInputStream pduDataStream) { assert(null != pduDataStream); int temp = pduDataStream.read(); assert(-1 != temp); return temp & 0xFF; }
这个啥也没的说,就是把一个byte转换成一个整型返回。
二、解析整型
1.parseShortInteger
基本同时,只是返回的有效位不一样,取这个byte的前7位,因此范围0-127
就 return temp & 0x7F ; 这句不一样。
2.parseUnsignedInt
解析一个无符号整型。
assert(null != pduDataStream); int result = 0; int temp = pduDataStream.read(); if (temp == -1) { return temp; } while((temp & 0x80) != 0) { result = result << 7; result |= temp & 0x7F; temp = pduDataStream.read(); if (temp == -1) { return temp; } } result = result << 7; result |= temp & 0x7F; return result;
首先判断第一个数字最高位,如果是0,取这个字节的低7位返回。
如果是1,就继续读下一位,直到读到高位为0的byte为止,最后把各个byte的低7位串成一个整型返回。
相当于每一个byte只有7为有效。
由于一个int最多32为,所以用这种方式表示的字节流不会超过5(32/7)个octec(8位字节).
3、 parseLongInteger
int temp = pduDataStream.read(); assert(-1 != temp); int count = temp & 0xFF; if (count > LONG_INTEGER_LENGTH_MAX) { throw new RuntimeException("Octet count greater than 8 and I can't represent that!"); } long result = 0; for (int i = 0 ; i < count ; i++) { temp = pduDataStream.read(); assert(-1 != temp); result <<= 8; result += (temp & 0xFF); } return result;
这个解析一个长整型
先读取一个count,表示该整型由多少octet组成,然后读响应字节,组成一个长整型。
由于长整型最多8个字节,所以这个count不会大于8.
再者,由于有了长度,它不需要用高位来标示结束符,因此每一个字节8位都有效。
4.parseIntegerValue
assert(null != pduDataStream); pduDataStream.mark(1); int temp = pduDataStream.read(); assert(-1 != temp); pduDataStream.reset(); if (temp > SHORT_INTEGER_MAX) { return parseShortInteger(pduDataStream); } else { return parseLongInteger(pduDataStream); }
解析整型。
先读取第一个字节,如果大于SHORT_INTEGER_MAX(127),即高位为1,则认为是一个short int,直接返回低7位。
否则就解析长int,先读取长度,再解析该长度的自己组成一个整型。
5.parseValueLength
assert(null != pduDataStream); int temp = pduDataStream.read(); assert(-1 != temp); int first = temp & 0xFF; if (first <= SHORT_LENGTH_MAX) { return first; } else if (first == LENGTH_QUOTE) { return parseUnsignedInt(pduDataStream); }
读取第一个的8位字节,如果小于SHORT_LENGTH_MAX(30),返回。
如果等于LENGTH_QUOTE(31),按照parseUnsignedInt方法解析。
三、解析字符串
1.parseWapString
pduDataStream.mark(1); // Check first char int temp = pduDataStream.read(); assert(-1 != temp); if ((TYPE_QUOTED_STRING == stringType) && (QUOTED_STRING_FLAG == temp)) { // Mark again if QUOTED_STRING_FLAG and ignore it pduDataStream.mark(1); } else if ((TYPE_TEXT_STRING == stringType) && (QUOTE == temp)) { // Mark again if QUOTE and ignore it pduDataStream.mark(1); } else { // Otherwise go back to origin pduDataStream.reset(); } return getWapString(pduDataStream, stringType);
首先解析第一个字节,如果字符串类型是TYPE_QUOTED_STRING,并且解析出来的第一个字节标识也是QUOTED_STRING_FLAG(34),就跳过这个标示,准备读下面数据。
如果出入类型是TYPE_TEXT_STRING,并且解析出来的第一个字节也是QUOTE(127),同样也是跳过这个标识,准备读下面数据。
否则,就是没有类型标示的字符串,那么就回退数据流。按照一个字符串来解析getWapString。
2.getWapString
ByteArrayOutputStream out = new ByteArrayOutputStream(); int temp = pduDataStream.read(); assert(-1 != temp); while((-1 != temp) && ('/0' != temp)) { // check each of the character if (stringType == TYPE_TOKEN_STRING) { if (isTokenCharacter(temp)) { out.write(temp); } } else { if (isText(temp)) { out.write(temp); } } temp = pduDataStream.read(); assert(-1 != temp); } if (out.size() > 0) { return out.toByteArray(); } return null;
这个没什么好说的,就是读取字节到结束,或者 /0结束为止。
3.parseEncodedStringValue
pduDataStream.mark(1); EncodedStringValue returnValue = null; int charset = 0; int temp = pduDataStream.read(); assert(-1 != temp); int first = temp & 0xFF; pduDataStream.reset(); if (first < TEXT_MIN) { parseValueLength(pduDataStream); charset = parseShortInteger(pduDataStream); //get the "Charset" } byte[] textString = parseWapString(pduDataStream, TYPE_TEXT_STRING); try { if (0 != charset) { returnValue = new EncodedStringValue(charset, textString); } else { returnValue = new EncodedStringValue(textString); } } catch(Exception e) { return null; } return returnValue;
首先读取第一个字节。
如果小于TEXT_MIN,就是说明这个字节是一个标示符,下面有编码方式。跳过这个字节,读取编码方式,然后调用parseWapString再解析下面的字符串数据。
否则,就是说明这个字符串没有编码方式,单纯一个字符串。就从头将其作为一个字符串解析。
补充,至于这些关键字符SHORT_LENGTH_MAX、LENGTH_QUOTE之类的,是wsp协议规定的,见wap-230-wsp-20010705-a.pdf,在我上传至资源中。
更多相关文章
- Android 加密解密字符串
- android 字符串转json
- Android中的strings文件中字符串的拼接
- Android定义字符串数组资源并在程序中使用
- android字符串资源字符format
- 〖Android〗Android App项目资源字符串检查(检查是否缺少对应的翻
- 2019AndroidBAT.字节跳动74道高级面试第二篇
- android 字节数据的转换与处理
- android string.xml中格式资源字符串