一、词法分析阶段
1、创建Tok类,记录Token的类型以及将每个转换为相应的字符串值。
package Lex;
/**
* Created by think on 2017/6/8.
*/
public class TOK {
//Tok类型
public static final int OBJB = 0;
public static final int OBJE = 1;
public static final int ARRB = 2;
public static final int ARRE = 3;
public static final int DESC = 4;
public static final int SPLIT = 5;
public static final int STR = 6;
public static final int NUM = 7;
public static final int TRUE = 8;
public static final int FALSE = 9;
public static final int NULL = 10;
public static final int BGN = 11;
public static final int EOF = 12;
//并存储tok类型的个数
public static final int TOK_NUM = 13;
//每个Tok类型对应的字符串类型
public static final String[] CAST_STRS = { "OBJB","OBJE", "ARRB","ARRE","DESC", "SPLIT",
"STR", "NUM","TRUE", "FALSE", "NULL","BGN","EOF" };
//每个Tok类型对应的实际字符串
public static final String[] CAST_LOCAL_STRS = { "{", "}", "[", "]",
":", ",", "s", "n", "true","false", "null", "开始", "结束" };
//返回Tok类型字符串
public static String castTokTypeStr(int type) {
if (type < 0 || type > TOK_NUM)
return "undefine";
else
return CAST_STRS[type];
}
//返回Tok类型实际字符串
public static String castTokTypeLocalStr(int type) {
if (type < 0 || type > TOK_NUM)
return "undefine";
else
return CAST_LOCAL_STRS[type];
}
}
2、创建Token类,作为词法分析的结果,有type属性和value属性,其中只有Num类型和STR类型有真正的value值,其余的只有类型。
package Lex;
/**
* Created by think on 2017/6/8.
*/
public class Token {
public static final Token DESC = new Token(TOK.DESC);
public static final Token SPLIT = new Token(TOK.SPLIT);
public static final Token ARRB= new Token(TOK.ARRB);
public static final Token OBJB = new Token(TOK.OBJB);
public static final Token ARRE = new Token(TOK.ARRE);
public static final Token OBJE = new Token(TOK.OBJE);
public static final Token FALSE = new Token(TOK.FALSE);
public static final Token TRUE = new Token(TOK.TRUE);
public static final Token NULL = new Token(TOK.NULL);
public static final Token BGN = new Token(TOK.BGN);
public static final Token EOF = new Token(TOK.EOF);
// 从TOK类中定义的类型
private Integer type;
// 该tok的值
private String value;
//行号
private int lineNum;
//开始列号
private int beginCol;
//结束列号
private int endCol;
public Token(int type) {
this.type = type;
this.value = null;
}
public Token(int type, String value) {
this.type = type;
this.value = value;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public int getLineNum(){
return lineNum;
}
public void setLineNum(int lineNum) {
this.lineNum = lineNum;
}
public int getBeginCol() {
return beginCol;
}
public int getEndCol() {
return endCol;
}
public void setEndCol(int endCol){
this.endCol=endCol;
}
public void setBeginCol(int beginCol) {
this.beginCol = beginCol;
}
public Object getRealValue(){
Object curValue = null;
switch(this.getType()){
case TOK.TRUE:
curValue = true;
break;
case TOK.FALSE:
curValue = false;
break;
case TOK.NULL:
curValue = null;
break;
case TOK.NUM:
if(value.indexOf('.')>=0){
curValue = Double.parseDouble(value);
}else{
curValue = Integer.parseInt(value);
}
break;
case TOK.STR:
curValue = "\""+this.getValue()+"\"";
break;
}
return curValue;
}
//输出被中括号括起来的token值
public String toString() {
if (this.type != 6&&this.type!=7) {
return "[" + TOK.castTokTypeStr(this.type) + "]";
} else {
return "[" + TOK.castTokTypeStr(this.type) + ":" + this.value
+ "]";
}
}
//输出每个Token实际对应的值
public String toLocalString() {
if (this.type != 6&&this.type!=7) {
return TOK.castTokTypeLocalStr(this.type);
} else if(this.type == 6){
return "\""+this.value + "\"";
}else{
return this.value;
}
}
}
3、创建JsonLex类进行词法分析,其中next()用来获取下一个的token,nextchar()用于获取下一个的字符,revertchar()用于回退一个字符,其余进行词法解析。getWriteStr()用来把词法分析的json字符串按照json文件的格式进行输出。
package Lex;
import MyException.UnexpectedException;
/**
* Created by think on 2017/6/8.
*/
public class JsonLex {
// 当前行号
private int lineNum = 0;
//每个Token的开始位置
private int startCol = 0;
// 当前字符游标
private int cur = -1;
// 保存当前要解析的字符串
private String str = null;
// 保存当前要解析的字符串的长度
private int len = 0;
//private int startLine=0;
//private int lastEndCol;
public JsonLex(String str) {
if (str == null)
throw new NullPointerException("词法解析构造函数不能传递null");
this.str = str;
this.len = str.length();
//this.lastEndCol=0;
this.startCol = 0;
this.cur = -1;
this.lineNum = 0;
}
public boolean isLetterUnderline(char c) {
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_');
}
public boolean isNumLetterUnderline(char c) {
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9') || c == '_');
}
public boolean isNum(char c) {
return (c >= '0' && c <= '9');
}
public boolean isPunctuation(char c){
return (c==','||c=='.'||c=='-'||c=='('||c==')');
}
public static boolean isSpace(char c) {
return (c == ' ' || c == '\t' || c == '\n'||c=='\r');
}
private void checkEnd() throws UnexpectedException {
if (cur >= len - 1) {
throw generateUnexpectedException("未预期的结束,字符串未结束");
}
}
public UnexpectedException generateUnexpectedException(String str) {
return new UnexpectedException(lineNum,startCol, str);
}
//获取下一个字符
private char nextChar() {
if (cur >= len - 1) {
return 0;
}
cur++;
startCol++;
char c = str.charAt(cur);
if (c == '\n'||c=='\r') {
if(str.charAt(cur+1)!='\n'&&str.charAt(cur+1)!='\r'){
lineNum++;
//lastEndCol=startCol;
startCol = 0;
}
}
return c;
}
//回退一个字符
private int revertChar() {
if (cur <= 0) {
return 0;
}
int rcur = cur--;
char c = str.charAt(rcur);
if (c == '\n') {
lineNum--;
//startCol=lastEndCol;
}
return rcur;
}
//解析获取字符串的值
private String getStrValue(char s) throws UnexpectedException {
int start = cur;
char c;
c=nextChar();
while (c!=0) {
if (isNumLetterUnderline(c)||isSpace(c)||isPunctuation(c)) {
c = nextChar();
} else if (s == c) {
return str.substring(start + 1, cur);
} else {
throw generateUnexpectedException("字符串,需要\"结尾");
}
}
return null;
}
//解析获取数字的值
private String getNumValue() throws UnexpectedException {
int start = cur;
boolean hasPoint=false;
boolean hasE=false;
char c;
while ((c=nextChar())!=0) {
if(isNum(c)){}
else if(c=='.'){
if(hasPoint){
throw generateUnexpectedException("数字错误,多余的.");
}else {
hasPoint=true;
}
}else if(c=='e'){
if (hasE){
throw generateUnexpectedException("数字错误,多余的e");
}else{
hasE=true;
}
}else if (isLetterUnderline(c)||c==' '){
throw generateUnexpectedException("数字错误,未知标识符");
}else {
return str.substring(start, revertChar());
}
}
checkEnd();
return null;
}
//解析获取false true,null类型的Token
private Token getDefToken() throws UnexpectedException {
int start = cur;
char c;
while ((c = nextChar()) != 0) {
if(cur==1245){
System.out.print(1546);
}
if (!isNumLetterUnderline(c)) {
String value = str.substring(start, revertChar());
if ("true".equals(value)) {
return Token.TRUE;
} else if ("false".equals(value)) {
return Token.FALSE;
} else if ("null".equals(value)) {
return Token.NULL;
} else {
throw generateUnexpectedException("错误标识符");
}
}
}
checkEnd();
return null;
}
//解析获取标点符号的Token
public Token parseSymbol(char c) {
switch (c) {
case '[':
return Token.ARRB;
case ']':
return Token.ARRE;
case '{':
return Token.OBJB;
case '}':
return Token.OBJE;
case ',':
return Token.SPLIT;
case ':':
return Token.DESC;
}
return null;
}
//获取下一个Token
public Token next() throws UnexpectedException {
if (lineNum == 0) {
lineNum = 1;
return Token.BGN;
}
char c;
while ((c = nextChar()) != 0) {
if (c == '\"') {
Token tempToken = new Token(TOK.STR);
tempToken.setLineNum(lineNum);
tempToken.setBeginCol(startCol);
tempToken.setValue(getStrValue(c));
tempToken.setEndCol(startCol);
return tempToken;
} else if (isLetterUnderline(c)) {
Token tempToken= getDefToken();
tempToken.setLineNum(lineNum);
tempToken.setBeginCol(startCol-TOK.castTokTypeStr(tempToken.getType()).length());
tempToken.setEndCol(startCol);
return tempToken;
} else if (isNum(c) || c == '-') {
Token tempToken = new Token(TOK.NUM);
tempToken.setLineNum(lineNum);
tempToken.setBeginCol(startCol);
tempToken.setValue(getNumValue());
tempToken.setEndCol(startCol);
return tempToken;
} else if (isSpace(c)) {
continue;
} else {
Token tempToken = parseSymbol(c);
tempToken.setLineNum(lineNum);
tempToken.setBeginCol(startCol);
tempToken.setEndCol(startCol);
return tempToken;
}
}
if (c == 0) {
return Token.EOF;
}
return null;
}
//获取待解析json字符串的标准格式
public String getWriteStr() throws UnexpectedException {
Token tk;
String str = "";
int goTimes = 0;
this.next();
while ((tk = this.next()) != Token.EOF) {
if (tk.toLocalString() == "{" || tk.toLocalString() == "[") {
str = str + tk.toLocalString();
goTimes++;
str = str + "\r" + "\n";
for (int i = 0; i < goTimes * 4; i++) {
str = str + " ";
}
} else if (tk.toLocalString() == ",") {
str = str + tk.toLocalString();
str = str + "\r" + "\n";
for (int i = 0; i < goTimes * 4; i++) {
str = str + " ";
}
} else if (tk.toLocalString() == "}" || tk.toLocalString() == "]") {
goTimes--;
str = str + "\r" + "\n";
for (int i = 0; i < goTimes * 4; i++) {
str = str + " ";
}
str = str + tk.toLocalString();
} else {
str = str + tk.toLocalString();
}
}
return str;
}
}
4、创建UnexpectedException进行错误抛出。
package MyException;
/**
* Created by think on 2017/6/8.
*/
public class UnexpectedException extends Exception {
private Integer lineNum = null;
private Integer colNum = null;
private String desc = null;
private Throwable cause = null;
public UnexpectedException() {
super();
}
public UnexpectedException(Integer lineNum, Integer colNum, String message) {
this.colNum = colNum;
this.lineNum = lineNum;
this.desc = message;
}
public String getMessage() {
return "line:" + lineNum + ",column:" + colNum
+ "]" + desc + (cause == null ? "" : cause.toString());
}
public String getLocalMessage() {
return getMessage();
}
public String toString() {
return getMessage();
}
}
在词法分析阶段,可以完成词法错误的识别,如字符串没有用”结束,数字的浮点型和科学计数法行不对,true,false和null的拼写错误等。
二、语法分析阶段
1、根据用LR分析法进行分析,发现Json语法为LR(1)文法。
构造LALR(1)项目自动机得如下图:(这个自己画一遍吧,比较复杂,画的很乱)
求得LALR(1)分析表
状态 |
Action |
GoTo |
|||||||||||||||||
{ |
} |
[ |
] |
: |
, |
s |
n |
# |
TRUE |
FALSE |
null |
J |
O |
M |
P |
A |
E |
V |
|
0 |
s4 |
|
s21 |
|
|
|
|
|
|
|
|
|
1 |
2 |
|
|
3 |
|
|
1 |
|
|
|
|
|
|
|
|
r0 |
|
|
|
|
|
|
|
|
|
|
2 |
|
|
|
|
|
|
|
|
r1 |
|
|
|
|
|
|
|
|
|
|
3 |
|
|
|
|
|
|
|
|
r2 |
|
|
|
|
|
|
|
|
|
|
4 |
|
s5 |
|
|
|
|
s11 |
|
|
|
|
|
|
|
6 |
8 |
|
|
|
5 |
|
r3 |
|
r3 |
|
r3 |
|
|
r3 |
|
|
|
|
|
|
|
|
|
|
6 |
|
s7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
r4 |
|
r4 |
|
r4 |
|
|
r4 |
|
|
|
|
|
|
|
|
|
|
8 |
|
r5 |
|
|
|
s9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
|
|
|
|
|
s11 |
|
|
|
|
|
|
|
10 |
8 |
|
|
|
10 |
|
r6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
|
|
|
|
s12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
s4 |
|
s21 |
|
|
|
s16 |
s17 |
|
s18 |
s19 |
s20 |
|
14 |
|
|
15 |
|
13 |
13 |
|
r7 |
|
|
|
r7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
r12 |
|
r12 |
|
r12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
r13 |
|
r13 |
|
r13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
|
r14 |
|
r14 |
|
r14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
r15 |
|
r15 |
|
r15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
r16 |
|
r16 |
|
r16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
r17 |
|
r17 |
|
r17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
r18 |
|
r18 |
|
r18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
S4 |
|
|
s22 |
|
|
s16 |
s17 |
|
s18 |
s19 |
s20 |
|
14 |
|
|
15 |
23 |
25 |
22 |
|
r8 |
|
r8 |
|
r8 |
|
|
r8 |
|
|
|
|
|
|
|
|
|
|
23 |
|
|
|
s24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
|
r9 |
|
r9 |
|
r9 |
|
|
r9 |
|
|
|
|
|
|
|
|
|
|
25 |
|
|
|
r10 |
|
s26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
s4 |
|
s21 |
|
|
|
s16 |
s17 |
|
s18 |
s19 |
s20 |
|
14 |
|
|
15 |
27 |
25 |
27 |
|
|
|
r11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
对test/a/true.json进行分析得
SYMBOL |
INPUT |
ACTION |
GOTO |
# |
{ |
S4 |
|
#{ |
s |
s11 |
|
#{s |
: |
s12 |
|
#{s: |
[ |
s21 |
|
#{s:[ |
{ |
s4 |
|
#{s:[{ |
s |
s11 |
|
#{s:[{s |
: |
s12 |
|
#{s:[{s: |
s |
s16 |
|
#{s:[{s:s |
, |
r14 |
13 |
#{s:[{s:v |
, |
r7 |
8 |
#{s:[{p |
, |
s9 |
|
#{s:[{p, |
s |
s11 |
|
#{s:[{p,s |
: |
S12 |
|
#{s:[{p,s: |
s |
s16 |
|
#{s:[{p,s:s |
} |
r14 |
13 |
#{s:[{p,s:v |
} |
r7 |
8 |
#{s:[{p,p |
} |
r5 |
10 |
#{s:[{p,m |
} |
r6 |
6 |
#{s:[{m |
} |
s7 |
|
#{s:[{m} |
, |
r4 |
14 |
#{s:[o |
, |
r12 |
25 |
#{s:[v |
, |
s26 |
|
#{s:[v, |
{ |
S4 |
|
#{s:[v,{ |
s |
s11 |
|
#{s:[v,{s |
: |
s12 |
|
#{s:[v,{s: |
s |
s16 |
|
#{s:[v,{s:s |
, |
r14 |
13 |
#{s:[v,{s:v |
, |
r7 |
8 |
#{s:[v,{p |
, |
s9 |
|
#{s:[v,{p, |
s |
s11 |
|
#{s:[v,{p,s |
: |
s12 |
|
#{s:[v,{p,s: |
s |
s16 |
|
#{s:[v,{p,s:s |
} |
R14 |
13 |
#{s:[v,{p,s:V |
} |
r7 |
|
#{s:[v,{p,p |
} |
r5 |
10 |
#{s:[v,{p,m |
} |
r6 |
6 |
#{s:[v,{m |
} |
s7 |
|
#{s:[v,{m} |
] |
r4 |
14 |
#{s:[v,o |
] |
r12 |
25 |
#{s:[v,v |
] |
r10 |
27 |
#{s:[v,E |
] |
r11 |
23 |
#{s:[E |
] |
s24 |
|
#{s:[E] |
} |
r9 |
|
#{s:A |
} |
|
|
|
|
|
|
2、构建StateClass类,创建inputChar数组,存放分析表的终结符和非终结符,创建stateTable数字,存放分析表的值。创建production二维数组,存放产生式,其中数组的第一个值为左部,第二个值为右部。
package Parser;
import java.util.*;
/**
* Created by think on 2017/6/9.
*/
public class StateClass {
//分析表中的所有终结符和非终结符
public static final ArrayList inputChar =new ArrayList<>();
static {
inputChar.add("{");
inputChar.add("}");
inputChar.add("[");
inputChar.add("]");
inputChar.add(":");
inputChar.add(",");
inputChar.add("s");
inputChar.add("n");
inputChar.add("#");
inputChar.add("true");
inputChar.add("false");
inputChar.add("null");
inputChar.add("J");
inputChar.add("O");
inputChar.add("M");
inputChar.add("P");
inputChar.add("A");
inputChar.add("E");
inputChar.add("V");
}
//分析表
public static final String stateTable[][]={
// { } [ ] : , s n # TRUE FALSE null J O M P A E V
/*0*/ {"S4","","S21","","","","","","","","","","1","2","","","3","",""},
/*1*/ {"","","","","","","","","R0","","","","","","","","","",""},
/*2*/ {"","","","","","","","","R1","","","","","","","","","",""},
/*3*/ {"","","","","","","","","R2","","","","","","","","","",""},
/*4*/ {"","S5","","","","","S11","","","","","","","","6","8","","",""},
/*5*/ {"","R3","","R3","","R3","","","R3","","","","","","","","","",""},
/*6*/ {"","S7","","","","","","","","","","","","","","","","",""},
/*7*/ {"","R4","","R4","","R4","","","R4","","","","","","","","","",""},
/*8*/ {"","R5","","","","S9","","","","","","","","","","","","",""},
/*9*/ {"","","","","","","S11","","","","","","","","10","8","","",""},
/*10*/ {"","R6","","","","","","","","","","","","","","","","",""},
/*11*/ {"","","","","S12","","","","","","","","","","","","","",""},
/*12*/ {"S4","","S21","","","","S16","S17","","S18","S19","S20","","14","","","15","","13"},
/*13*/ {"","R7","","","","R7","","","","","","","","","","","","",""},
/*14*/ {"","R12","","R12","","R12","","","","","","","","","","","","",""},
/*15*/ {"","R13","","R13","","R13","","","","","","","","","","","","",""},
/*16*/ {"","R14","","R14","","R14","","","","","","","","","","","","",""},
/*17*/ {"","R15","","R15","","R15","","","","","","","","","","","","",""},
/*18*/ {"","R16","","R16","","R16","","","","","","","","","","","","",""},
/*19*/ {"","R17","","R17","","R17","","","","","","","","","","","","",""},
/*20*/ {"","R18","","R18","","R18","","","","","","","","","","","","",""},
/*21*/ {"S4","","","S22","","","S16","S17","","S18","S19","S20","","14","","","15","23","25"},
/*22*/ {"","R8","","R8","","R8","","","R8","","","","","","","","","",""},
/*23*/ {"","","","S24","","","","","","","","","","","","","","",""},
/*24*/ {"","R9","","R9","","R9","","","R9","","","","","","","","","",""},
/*25*/ {"","","","R10","","S26","","","","","","","","","","","","",""},
/*26*/ {"S4","","S21","","","","S16","S17","","S18","S19","S20","","14","","","15","27","25"},
/*27*/ {"","","","R11","","","","","","","","","","","","","","",""},
};
//产生式
public static final String[][] production={
{"S","J"},{"J","O"},{"J","A"},{"O","{}"},{"O","{M}"},{"M","P"},{"M","P,M"},
{"P","s:V"},{"A","[]"}, {"A","[E]"},{"E","V"},{"E","V,E"},{"V","O"},{"V","A"},
{"V","s"},{"V","n"}, {"V","t"},{"V","f"},{"V","u"}
};
}
3、创建stateMachine类进行最终的语法分析。Parse()用于解析json字符串的每个token,如果解析成功,则返回true。在analyse()进行每个token的字符串值的解析。
package Parser;
import Lex.JsonLex;
import Lex.TOK;
import Lex.Token;
import MyException.UnexpectedException;
import java.util.Stack;
/**
* Created by think on 2017/6/10.
*/
public class StateMachine {
private JsonLex lex = null;
private Integer status = null;
//符号栈
private Stack stateStack=new Stack<>();
//符号栈
private Stack symbolStack=new Stack<>();
public StateMachine(String str){
stateStack.push(0);
symbolStack.push("#");
if (str == null)
throw new NullPointerException("语法解析构造函数不能传递null");
lex = new JsonLex(str);
}
public boolean isNum(char c) {
return (c >= '0' && c <= '9');
}
//解析每个Token的字符串值
public boolean analyse(int lineNum,int colNum,String c) throws UnexpectedException {
status = stateStack.peek();
String tempStr= StateClass.stateTable[status][StateClass.inputChar.indexOf(c)];
if(tempStr==""){
throw new UnexpectedException(lineNum,colNum,"不合法标识符");
}else if (tempStr.charAt(0)=='S'){
stateStack.push(Integer.parseInt(tempStr.substring(1)));
symbolStack.push(c);
return true;
}else if (tempStr.charAt(0)=='R'){
int x=Integer.parseInt(tempStr.substring(1));
int len=StateClass.production[x][1].length();
for(int i=0;i< StateClass.production[x][1].length();i++){
stateStack.pop();
symbolStack.pop();
}
return analyse(lineNum,colNum,StateClass.production[x][0]);
}else if(isNum(tempStr.charAt(0))){
stateStack.push(Integer.parseInt(tempStr));
symbolStack.push(c);
return true;
}else if(tempStr=="acc"){
return true;
}
return false;
}
//解析json字符串
public boolean parse() throws UnexpectedException {
Token tk = null;
tk=lex.next();
tk=lex.next();
Integer oldStatus = status;
while(tk!=Token.EOF){
String analyseStr= TOK.CAST_LOCAL_STRS[tk.getType()];
if(analyse(tk.getLineNum(),tk.getBeginCol(),analyseStr)==false){
System.out.print("未知错误");
return false;
}
String tempC=symbolStack.peek();
if(tempC=="J"||tempC=="O"||tempC=="M"||tempC=="P"||tempC=="A"||tempC=="E"||tempC=="V"){
continue;
}
tk=lex.next();
}
return true;
}
}
三、文件读取和写入
1、创建FileIO类进行文件读取和写入。其中readFile用于读取文件内容并返回字符串,writeFile用于将字符串写入到指定文件中,如果文件不存在,则创建文件。
package FileIO;
/**
* Created by think on 2017/6/12.
*/
import java.io.*;
public class FileIO {
//从文件读取内容
public static String readFile(String path) throws IOException{
BufferedReader in = new BufferedReader(new FileReader( path));
String str="";
int c;
while((c = in.read())!=-1)
{
str=str+(char)c;
}
in.close();
return str;
}
//向文件写入内容
public static void writeFile(String path,String str) throws IOException{
File toFile = new File(path);
if (!toFile.exists()) {
toFile.createNewFile();
}
FileWriter fw = null;
fw = new FileWriter(toFile);
fw.write(str);
fw.close();
}
}
四、按路径得到Json元素值
1、创建Json文件,完成将json字符串解析为Map和list格式并完成按路径存取。其中maps栈用于保存所有对象map,lists栈用于保存所有数组,islist栈判断是否为list,keys栈用来保存key。
方法getStructure()用于得到解析后的map和list结构,search()用于根据路径得到元素值,printSearchResult()用于打印提取的结果值。
package Json;
import FileIO.FileIO;
import Lex.JsonLex;
import Lex.TOK;
import Lex.Token;
import MyException.UnexpectedException;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.System.exit;
/**
* Created by think on 2017/6/13.
*/
public class Json {
Stack