]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/tools/misc/src/com/ibm/icu/dev/tool/charsetdet/mbcs/BIG5Tool.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / tools / misc / src / com / ibm / icu / dev / tool / charsetdet / mbcs / BIG5Tool.java
1 /*
2  ***********************************************************************
3  *
4  * Copyright (C) 2006, International Business Machines Corporation and
5  * others. All Rights Reserved.
6  *
7  ***********************************************************************
8  *
9  * BIG5Tool
10  *
11  *    This tool produces the character usage frequency statistics for the Big5
12  *    Chinese charset, for use by the ICU charset detectors.
13  *
14  *    usage:  java BIG5Tool [-d] [directory path]
15  *
16  *        -d:   Produce the data in a form to be exported to the ICU implementation
17  *              Default is to produce an informative dump.
18  *              
19  *        -sjis Do Shift_JIS.  The structure of sjis is very similar to Big5.
20  *
21  *        directory path
22  *              Source directory for the text files to be analyzed.
23  *              All files in the specified directory must be in the Big5 encoding.
24  *
25  */
26
27 package com.ibm.icu.dev.tool.charsetdet.mbcs;
28
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.HashMap;
34 import java.util.List;
35
36
37 public class BIG5Tool {
38
39     // The file buffer and file data length need to be out in class member variables
40     //  so that the code lifted from charSet detection for scanning the multi-byte chars
41     //  can see them conveniently.
42     byte []    buf = new byte[1000000];
43     int        fileSize;
44
45     boolean    option_d = false;    // data option.  Produce exportable data
46     boolean    option_v = true;     // verbose informaional output.
47     boolean    sjis     = false;    // True if input text files are Shift_JIS encoded.
48
49
50
51     public static void main(String[] args) {
52         BIG5Tool  This = new BIG5Tool();
53         This.Main(args);
54     }
55
56
57
58     void Main(String[] args) {
59         int i;
60
61         //
62         //   Command Line Option Handling
63         //
64         String     dirName  = null;
65         for (i=0; i<args.length; i++) {
66             if (args[i].equals("-d")) {
67                 option_d = true;
68                 option_v = false;
69                 continue;
70             }
71             if (args[i].equals("-sjis")) {
72                 sjis = true;
73                 continue;
74             }
75             if (args[i].startsWith("-")) {
76                 System.err.println("Unrecognized option: " + args[i]);
77                 System.exit(-1);
78             }
79             if (dirName == null) {
80                 dirName = args[i];
81             } else {
82                 System.err.println("Unrecognized option: " + dirName);
83                 System.exit(-1);
84             }
85         }
86         if (dirName == null) {
87             dirName = ".";
88         }
89
90         //
91         //  Verify that the specified directory exists.
92         //
93         File dir = new File(dirName);
94         if (dir.isDirectory() == false) {
95             System.err.println("\"" + dirName + "\" is not a directory");
96             System.exit(-1);
97         }
98         processDir(dir);
99         
100     }
101
102     //
103     // Collect statistics from all ordinary files in a specified directory.
104     //
105     void processDir(File dir) {
106         int      totalMbcsChars  = 0;
107         HashMap  m = new HashMap(10000);
108         int      i;
109
110         System.out.println(dir.getName());
111         File[] files = dir.listFiles();
112         for (i=0; i<files.length; i++) {
113             try {
114                 if (files[i].isFile()) {
115                     FileInputStream is = new FileInputStream(files[i]);
116                     fileSize = is.read(buf);
117                     if (option_v) {
118                         System.out.println(files[i].getPath());
119                         System.out.println("  " + fileSize + " bytes.");
120                     }
121                     iteratedChar ichar = new iteratedChar();
122                     int fileChars     = 0;
123                     int fileMbcsChars = 0;
124                     int errs          = 0;
125
126                     while (nextChar(ichar)) {
127                         if (ichar.error == true) {
128                             errs++;
129                             continue;
130                         }
131                         fileChars++;
132                         if (ichar.charValue > 255) {
133                             fileMbcsChars++;
134                             totalMbcsChars++;
135                         }
136                         if (ichar.charValue <= 255) {
137                             // Don't keep occurence statistics for the single byte range
138                             continue;
139                         }
140
141                         //
142                         //  Frequency of occurence statistics are accumulated in a map.
143                         //
144                         ChEl  keyEl = new ChEl(ichar.charValue, 0);
145                         ChEl  valEl = (ChEl)m.get(keyEl);
146                         if (valEl == null) {
147                             m.put(keyEl, keyEl);
148                             valEl = keyEl;
149                         }
150                         valEl.occurences++;
151                     }
152                     if (option_v) {
153                         System.out.println("  " + fileChars     + " Chars");
154                         System.out.println("  " + fileMbcsChars + " mbcs Chars");
155                         System.out.println("  " + errs          + " errors");
156                         System.out.println("\n");
157                     }
158                 }
159             }
160             catch (Exception e) {
161                 System.err.println("Exception:" + e);
162
163             }
164         }
165
166         //
167         //  We've processed through all of the files.
168         //     sort and dump out the frequency statistics.
169         //
170         Object [] encounteredChars = m.values().toArray();
171         Arrays.sort(encounteredChars);
172         int cumulativeChars = 0;
173         int cumulativePercent = 0;
174         if (option_v) {
175             System.out.println("# <char code> <occurences>  <Cumulative %>");
176             for (i=0; i<encounteredChars.length; i++) {
177                 ChEl c = (ChEl)encounteredChars[i];
178                 cumulativeChars += c.occurences;
179                 cumulativePercent = cumulativeChars*100/totalMbcsChars;
180                 System.out.println(i + "   " + Integer.toHexString(c.charCode) + "        " 
181                         + c.occurences + "         " + cumulativePercent);
182             }
183         }
184         if (option_d) {
185             //
186             //   Output the list of characters formatted for pasting into a
187             //     Java source code array initializer.
188             //     Resort into order based on the character code value, not
189             //      on frequency of occurence.
190             //
191             List  charList = new ArrayList();
192             
193             for (i=0; i<100 && cumulativePercent<50; i++) {
194                 ChEl c = (ChEl)encounteredChars[i];
195                 cumulativeChars += c.occurences;
196                 cumulativePercent = cumulativeChars*100/totalMbcsChars;
197                 charList.add(new Integer(c.charCode));
198             }
199             Object [] sortedChars = charList.toArray();
200             Arrays.sort(sortedChars);
201             
202             System.out.print("          {");
203             for (i=0; i<sortedChars.length; i++) {
204                 if (i != 0) {
205                     System.out.print(", ");
206                     if ((i)%10 == 0) {
207                         System.out.print("\n           ");
208                     }
209                 }
210                 int cp = ((Integer)sortedChars[i]).intValue();
211                 System.out.print("0x" + Integer.toHexString(cp));
212             }
213             System.out.println("};");
214         }
215     }
216     
217     //
218     //  This is a little class containing a
219     //    multi-byte character value and an occurence count for that char.
220     //  Instances of this class are kept in the collection that accumulates statistics
221     //
222     //  WARNING:  this class's natural ordering (from Comparable) and equals()
223     //            are inconsistent.
224
225     static class ChEl implements Comparable {
226         int charCode;
227         int occurences;
228
229         ChEl(int c, int o) {
230             charCode = c;
231             occurences = o;
232         }
233
234         // Equals needs to work with a map, with the charCode as the key.
235         //   For insertion/lookup, we care about the char code only, not the occurence count.
236         public boolean equals(Object other) {
237             ChEl o = (ChEl)other;
238             return o.charCode == this.charCode;
239         }
240
241         // Hashcode needs to be compatible with equals
242         //   We're using this in a hashMap!
243         public int hashCode() {
244             return charCode;
245         }
246
247         // We want to be able to sort the results by frequency of occurence
248         //   Compare backwards.  We want most frequent chars first.
249         public int compareTo(Object other) {
250             ChEl o = (ChEl)other;
251             return (this.occurences> o.occurences? -1 :
252                    (this.occurences==o.occurences?  0 : 1));
253         }
254
255     }
256
257     //
258     // iteratedChar is copied and slightly hacked from the similar calss in CharsetRecog_mbcs
259     //              Pulls out one logical char according to the rules of EUC encoding.
260     //
261     class iteratedChar {
262         int             charValue = 0;             // The char value is a value from the encoding.
263                                                    //   It's meaning is not well defined, other than
264                                                    //   different encodings
265         int             index     = 0;
266         int             nextIndex = 0;
267         boolean         error     = false;
268         boolean         done      = false;
269
270         void reset() {
271             charValue = 0;
272             index     = -1;
273             nextIndex = 0;
274             error     = false;
275             done      = false;
276         }
277
278         int nextByte() {
279             if (nextIndex >= fileSize) {
280                 done = true;
281                 return -1;
282             }
283             int byteValue = (int)buf[nextIndex++] & 0x00ff;
284             return byteValue;
285         }
286     }
287
288
289     boolean nextChar(iteratedChar it) {
290         it.index = it.nextIndex;
291         it.error = false;
292         int firstByte  = 0;
293         int secondByte = 0;
294
295         buildChar: {
296             firstByte = it.charValue = it.nextByte();
297             if (firstByte < 0) {
298                 // Ran off the end of the input data
299                 it.done = true;
300                 break buildChar;
301             }
302             if (firstByte <= 0x0080 ||
303                     (sjis && firstByte>=0x00a0 && firstByte< 0x00e0) ||
304                     (sjis && firstByte>=0x00fd && firstByte<=0x00ff)) {
305                 // single byte char
306                 break buildChar;
307             }
308
309             secondByte = it.nextByte();
310             it.charValue = (it.charValue << 8) | secondByte;
311
312             if (secondByte <  0x40 ||
313                 secondByte == 0x007f ||
314                 secondByte == 0x00ff ||
315                 sjis && secondByte >= 0x00fd) {
316                     it.error = true;
317             }
318             
319             if (it.error) {
320                 System.out.println("Error " + Integer.toHexString(firstByte) + " " + Integer.toHexString(secondByte));
321             }
322        }
323
324         return (it.done == false);
325     }
326
327 }