javascript脚本压缩工具JSEncoder实现(转)
package?com.cngd.jstool;
??2
??3
import?java.io.FileReader;
??4
import?java.io.BufferedReader;
??5
import?java.io.FileOutputStream;
??6
import?java.io.IOException;
??7
import?java.util.regex.Matcher;
??8
import?java.util.regex.Pattern;
??9
import?java.util.Vector;
?10
import?java.text.DecimalFormat;
?11
?12
/**?*//**
?13
?*?JSEncoder脚本压缩工具
?14
?*?<p/>
?15
?*?写完代码之后才发现这是JSA(http://sourceforge.net/project/showfiles.php?group_id=175776)的压缩算法的再实现
?16
?*?针对jquery-1.2.3.min.js这个文件的压缩比率结果比较如下
?17
?*?-------------------------------
?18
?*?原始大小?|?JSEncoder?|?JSA-20071021(2.0?pre-alpha)?|??jquery?packer算法
?19
?*?-------------------------------
?20
?*?53kb???|?32kb???????|??29kb???????????????????????|????29kb
?21
?*?-------------------------------
?22
?*?因为JSA进一步将局部变量进行了压缩,因此相比较更小
?23
?*?<p/>
?24
?*?<p/>
?25
?*?<p/>
?26
?*?User:?(在路上
?http://www.cnblogs.com/midea0978)
?27
?*?Date:?2008-4-18
?28
?*?Version:0.5
?29
?*/
?30
public?class?JSEncoder?
{
?31
????public?static?final?String?ENCODE_BASE64?=?"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
?32
????public?boolean?isDebug?=?false;
?33
?34
????/**?*//**
?35
?????*?@param?filename?js?filename
?36
?????*?@param?offset???offset>=0指定偏移变量,不同的offset可以实现代码表位置的变换,较小的offset可以获得更大的压缩率
?37
?????*?@return?压缩后的代码
?38
?????*/
?39
????public?String?encode(String?filename,?int?offset)?throws?Exception?
{
?40
????????String?jscript?=?readFileData(filename);
?41
????????int?size?=?jscript.length();
?42
????????jscript?=?jscript.replaceAll("\n",?"?");
?43
????????//替换\->\\
?44
????????jscript?=?jscript.replaceAll("\\\\",?"\\\\\\\\");
?45
????????//替换单引号'=>\'
?46
????????jscript?=?jscript.replaceAll("\\'",?"\\\\\\'");
?47
?48
????????Pattern?p?=?Pattern.compile("([\\w\\$]+)");
?49
????????Matcher?m?=?p.matcher(jscript);
?50
????????String?element;
?51
????????Vector<String>?dict?=?new?Vector<String>();
?52
????????int?index;
?53
????????StringBuffer?encscript?=?new?StringBuffer();
?54
????????StringBuffer?dicttab?=?new?StringBuffer();
?55
?56
????????debugInfo("=====编码字典对应表=====");
?57
????????while?(m.find())?
{
?58
????????????element?=?m.group(1).trim();
?59
????????????if?(!dict.contains(element))?
{
?60
????????????????dict.add(element);
?61
????????????????index?=?dict.size()?-?1;
?62
????????????}?else?
{
?63
????????????????index?=?dict.indexOf(element);
?64
????????????}
?65
????????????debugInfo(index?+?"==>"?+?element);
?66
????????????m.appendReplacement(encscript,?Base64Encode(offset?+?index?+?1));
?67
????????}
?68
????????for?(String?o?:?dict)?dicttab.append(o?+?"|");
?69
????????m.appendTail(encscript);
?70
????????debugInfo("=====??编码字典结束??=====");
?71
????????debugInfo("Offset="?+?offset?+?",字典大小="?+?dict.size());
?72
????????debugInfo("压缩后的代码:\n"?+?encscript.toString());
?73
????????String?dictstr?=?dicttab.substring(0,?dicttab.length()?-?1).toString();
?74
????????debugInfo("字典字符串:\n"?+?dictstr);
?75
????????String?res?=?formatCode(encscript.toString(),?dictstr,?dict.size(),?offset);
?76
????????int?packsize?=?res.length();
?77
????????DecimalFormat?df?=?new?DecimalFormat("######.0");
?78
????????System.out.println("\n原始文件大小:"?+?size?+?"\n压缩后文件大小:"?+?packsize);
?79
????????System.out.println("=================\n压缩比率:"?+?df.format((size?-?packsize)?*?100.0?/?size)?+?"%");
?80
????????return?res;
?81
????}
?82
?83
????private?String?readFileData(String?filename)?throws?IOException?
{
?84
????????BufferedReader?in?=?new?BufferedReader(new?FileReader(filename));
?85
????????StringBuffer?sb?=?new?StringBuffer();
?86
????????while?(in.ready())?
{
?87
????????????sb.append(in.readLine()?+?"\n");
?88
????????}
?89
????????in.close();
?90
????????return?sb.toString();
?91
????}
?92
?93
????private?void?debugInfo(String?txt)?
{
?94
????????if?(isDebug)?System.out.println(txt);
?95
????}
?96
?97
????public?static?void?main(String[]?args)?
{
?98
????????System.out.println("JSEncoder?0.5?by?midea0978?2008.4");
?99
????????System.out.println("=====================================");
100
????????System.out.println("http://www.cnblogs.com/midea0978\n");
101
????????if?(args.length?<?2)?
{
102
????????????System.out.println("Usage:java?JSEncoder.jar?jsfile?outputfile?[offset].");
103
????????????System.exit(0);
104
????????}
105
????????try?
{
106
????????????System.out.println("输入文件:?"?+?args[0]);
107
????????????System.out.println("输出文件:?"?+?args[1]);
108
????????????JSEncoder?util?=?new?JSEncoder();
109
????????????int?offset?=?args.length?>=?3???Integer.parseInt(args[2])?:?0;
110
????????????String?code?=?util.encode(args[0],?offset);
111
????????????FileOutputStream?fs?=?new?FileOutputStream(args[1]);
112
????????????fs.write(code.getBytes());
113
????????????fs.close();
114
????????}?catch?(Exception?e)?
{
115
????????????e.printStackTrace();
116
????????}
117
????}
118
119
????/**?*//**
120
?????*?仿Base64解码
121
?????*
122
?????*?@param?c?待编码的数字
123
?????*?@return?编码值
124
?????*/
125
????private?String?Base64Encode(int?c)?throws?Exception?
{
126
????????String?res;
127
????????if?(c?<?0)?throw?new?Exception("Error:Offset必须>=0.");
128
????????if?(c?>?63)
129
????????????res?=?Base64Encode(c?>>?6)?+?Base64Encode(c?&?63);
130
????????else?
{
131
????????????//为了配合appendReplacement方法的使用,将$替换为\$
132
????????????res?=?c?==?63???"\\$"?:?String.valueOf(ENCODE_BASE64.charAt(c));
133
????????}
134
????????return?res;
135
????}
136
137
????private?String?formatCode(String?enc,?String?dict,?int?size,?int?offset)?
{
138
????????StringBuffer?str?=?new?StringBuffer();
139
????????str.append("/*?Compressed?by?JSEncoder?*/\neval(function(E,I,A,D,J,K,L,H){function?C(A){return?A<62?String.fromCharCode(A+=A<26?65:A<52?71:-4):A<63?'_':A<64?'$':C(A>>6)+C(A&63)}while(A>0)K[C(D--)]=I[--A];function?N(A){return?K[A]==L[A]?A:K[A]}if(''.replace(/^/,String)){var?M=E.match(J),B=M[0],F=E.split(J),G=0;if(E.indexOf(F[0]))F=[''].concat(F);do{H[A++]=F[G++];H[A++]=N(B)}while(B=M[G]);H[A++]=F[G]||'';return?H.join('')}return?E.replace(J,N)}(");
140
????????str.append("'"?+?enc?+?"',");
141
????????str.append("'"?+?dict?+?"'.split('|'),");
142
????????str.append(size?+?","?+?(size?+?offset)?+?",/[\\w\\$]+/g,?{},?{},?[]))");
143
????????return?str.toString();
144
????}
145
146
}
147