一.概述
ParameterParser类是一个简单的解析器,解析出键值对
二.源码
package org.apache.commons.fileupload;
import java.util.HashMap;
import java.util.Map;
/**
* 一个简单的解析器,旨在解析名称/值对序列
* 如果参数值包含不安全字符(例如'='字符或分隔符),则它们将被包含在引号中。 参数值是可选的,可以省略
* <p>
* <code>param1 = value; param2 = "anything goes; really"; param3</code>
* </p>
*/
public class ParameterParser {
// 被解析的字符串
private char[] chars = null;
// 字符串的当前位置
private int pos = 0;
// 字符串的最大位置position
private int len = 0;
// 开始
private int i1 = 0;
// 结尾
private int i2 = 0;
// Map中存储的名称是否应转换为小写
private boolean lowerCaseNames = false;
public ParameterParser() {
super();
}
/**
* 从给定的字符串中提取名称/值对的映射。 名称name预计将是独一无二的。
* @param str 包含名称/值对序列的字符串
* @param separators 名称/值对的分隔符
* @return 返回一个名称/值对的Map
*/
public Map parse(final String str, char[] separators) {
if (separators == null || separators.length == 0) {
return new HashMap();
}
char separator = separators[0];
if (str != null) {
int idx = str.length();
for (int i = 0; i < separators.length; i++) {
int tmp = str.indexOf(separators[i]);
if (tmp != -1) {
if (tmp < idx) {
idx = tmp;
separator = separators[i];
}
}
}
}
return parse(str, separator);
}
/**
* 从给定的字符串中提取名称/值对的映射。 名称name预计将是独一无二的。
* @param str 包含名称/值对序列的字符串
* @param separator 名称/值对的分隔符
* @return 返回一个名称/值对的Map
*/
public Map parse(final String str, char separator) {
if (str == null) {
return new HashMap();
}
return parse(str.toCharArray(), separator);
}
public Map parse(final char[] chars, char separator) {
if (chars == null) {
return new HashMap();
}
return parse(chars, 0, chars.length, separator);
}
/**
* 从给定的字符串中提取名称/值对的映射。 名称name预计将是独一无二的。
*
* @param chars 包含名称/值对序列的字符数组
* @param offset - 初始偏移量
* @param length - 长度
* @param separator 名称/值对的分隔符
* @return 返回一个名称/值对的Map
*/
public Map parse(final char[] chars, int offset, int length, char separator) {
if (chars == null) {
return new HashMap();
}
HashMap params = new HashMap();
this.chars = chars;
this.pos = offset;
this.len = length;
String paramName = null;
String paramValue = null;
while (hasChar()) {// 有待解析的字符
// 解析出参数名
paramName = parseToken(new char[] {'=', separator });
paramValue = null;
if (hasChar() && (chars[pos] == '=')) {
pos++; // 跳过"="
paramValue = parseQuotedToken(new char[] {separator});
}
if (hasChar() && (chars[pos] == separator)) {
pos++; // 跳过分隔符
}
if ((paramName != null) && (paramName.length() > 0)) {// 存在参数名
if (this.lowerCaseNames) {// 参数名小写
paramName = paramName.toLowerCase();
}
params.put(paramName, paramValue);
}
}
return params;
}
/**
* 直到遇到任何给定的终结符
* Parses out a token until any of the given terminators
* is encountered.
*
* @param terminators 终止字符数组,遇到任何这些字符时表示结尾
*
* @return the token
*/
private String parseToken(final char[] terminators) {
char ch;
i1 = pos;
i2 = pos;
while (hasChar()) {
ch = chars[pos];
if (isOneOf(ch, terminators)) {// 找到结尾字符
break;
}
i2++;
pos++;
}
return getToken(false);
}
/**
* Parses out a token until any of the given terminators
* is encountered outside the quotation marks.
* @param terminators 名称/值对的分隔符
*/
private String parseQuotedToken(final char[] terminators) {
char ch;
i1 = pos;
i2 = pos;
// 是否去掉引号
boolean quoted = false;
boolean charEscaped = false;
while (hasChar()) {
ch = chars[pos];
if (!quoted && isOneOf(ch, terminators)) {
break;
}
if (!charEscaped && ch == '"') {
quoted = !quoted;
}
charEscaped = (!charEscaped && ch == '\\');
i2++;
pos++;
}
return getToken(true);
}
/**
* 此方法会删除前导和尾随空格以及封闭引号
* @param quoted 是否去除引号
* @return the token
*/
private String getToken(boolean quoted) {
// 除去开始的空格
while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) {
i1++;
}
// 除去结尾的空格
while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) {
i2--;
}
if (quoted) {
if (((i2 - i1) >= 2) && (chars[i1] == '"') && (chars[i2 - 1] == '"')) {
i1++;
i2--;
}
}
String result = null;
if (i2 > i1) {
result = new String(chars, i1, i2 - i1);
}
return result;
}
// true表示字符ch在charray中
private boolean isOneOf(char ch, final char[] charray) {
boolean result = false;
for (int i = 0; i < charray.length; i++) {
if (ch == charray[i]) {
result = true;
break;
}
}
return result;
}
/**
* true-表示有字符需要解析
*/
private boolean hasChar() {
return this.pos < this.len;
}
// 返回参数名是否小写
public boolean isLowerCaseNames() {
return this.lowerCaseNames;
}
/**
* 设置参数名是否小写
*/
public void setLowerCaseNames(boolean b) {
this.lowerCaseNames = b;
}
}