]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/dev/tool/charsetdet/sbcs/StatisticsTool.java
icu4jsrc
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / dev / tool / charsetdet / sbcs / StatisticsTool.java
1 /*\r
2  ***********************************************************************\r
3  * Copyright (C) 2005-2007, International Business Machines            *\r
4  * Corporation and others. All Rights Reserved.                        *\r
5  ***********************************************************************\r
6  *\r
7  */\r
8 \r
9 package com.ibm.icu.dev.tool.charsetdet.sbcs;\r
10 \r
11 \r
12 import java.io.*;\r
13 import java.util.Arrays;\r
14 import java.util.ArrayList;\r
15 import java.util.Collections;\r
16 import java.util.Iterator;\r
17 import java.util.List;\r
18 \r
19 import com.ibm.icu.impl.Utility;\r
20 \r
21 /**\r
22  * @author emader\r
23  *\r
24  * TODO To change the template for this generated type comment go to\r
25  * Window - Preferences - Java - Code Style - Code Templates\r
26  */\r
27 public class StatisticsTool implements NGramParser.NGramParserClient, NGramList.NGramKeyMapper\r
28 {\r
29     /* TODO Make this usage string more sane. */\r
30     private static final String usageString = \r
31         "\nUsage: StatisticsTool [OPTIONS] [FILES]\n\n" +\r
32         "This program will read in a Unicode text file of text in a particular language\n" +\r
33         "and compute the statistics needed to detected that language and character set.\n " +\r
34         "Options:\n" +\r
35         "-e       specify the target encoding\n" +\r
36         "-h or -? print this usage text.\n" +\r
37         "-v       also generate statistics for visual order.\n" +\r
38         "-l       only generate statistics for logical order (cancel -v)." +\r
39         "-c       run the checker.\n" +\r
40         "-t       run the encoding test.\n" +\r
41         "example: com.ibm.icu.dev.tool.charset.StatisticsTool -e 8859-1 Spanish.txt";\r
42 \r
43     private static final int BUFFER_SIZE = 1024;\r
44     \r
45     private char[] buffer;\r
46     private int bufIndex;\r
47     private int bufMax;\r
48 \r
49     private InputFile inputFile;\r
50     \r
51     private NGramList ngrams;\r
52     \r
53     private static byte[] allBytes = {\r
54             (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,\r
55             (byte) 0x08, (byte) 0x09, (byte) 0x0A, (byte) 0x0B, (byte) 0x0C, (byte) 0x0D, (byte) 0x0E, (byte) 0x0F,\r
56             (byte) 0x10, (byte) 0x11, (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15, (byte) 0x16, (byte) 0x17,\r
57             (byte) 0x18, (byte) 0x19, (byte) 0x1A, (byte) 0x1B, (byte) 0x1C, (byte) 0x1D, (byte) 0x1E, (byte) 0x1F,\r
58             (byte) 0x20, (byte) 0x21, (byte) 0x22, (byte) 0x23, (byte) 0x24, (byte) 0x25, (byte) 0x26, (byte) 0x27,\r
59             (byte) 0x28, (byte) 0x29, (byte) 0x2A, (byte) 0x2B, (byte) 0x2C, (byte) 0x2D, (byte) 0x2E, (byte) 0x2F,\r
60             (byte) 0x30, (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x34, (byte) 0x35, (byte) 0x36, (byte) 0x37,\r
61             (byte) 0x38, (byte) 0x39, (byte) 0x3A, (byte) 0x3B, (byte) 0x3C, (byte) 0x3D, (byte) 0x3E, (byte) 0x3F,\r
62             (byte) 0x40, (byte) 0x41, (byte) 0x42, (byte) 0x43, (byte) 0x44, (byte) 0x45, (byte) 0x46, (byte) 0x47,\r
63             (byte) 0x48, (byte) 0x49, (byte) 0x4A, (byte) 0x4B, (byte) 0x4C, (byte) 0x4D, (byte) 0x4E, (byte) 0x4F,\r
64             (byte) 0x50, (byte) 0x51, (byte) 0x52, (byte) 0x53, (byte) 0x54, (byte) 0x55, (byte) 0x56, (byte) 0x57,\r
65             (byte) 0x58, (byte) 0x59, (byte) 0x5A, (byte) 0x5B, (byte) 0x5C, (byte) 0x5D, (byte) 0x5E, (byte) 0x5F,\r
66             (byte) 0x60, (byte) 0x61, (byte) 0x62, (byte) 0x63, (byte) 0x64, (byte) 0x65, (byte) 0x66, (byte) 0x67,\r
67             (byte) 0x68, (byte) 0x69, (byte) 0x6A, (byte) 0x6B, (byte) 0x6C, (byte) 0x6D, (byte) 0x6E, (byte) 0x6F,\r
68             (byte) 0x70, (byte) 0x71, (byte) 0x72, (byte) 0x73, (byte) 0x74, (byte) 0x75, (byte) 0x76, (byte) 0x77,\r
69             (byte) 0x78, (byte) 0x79, (byte) 0x7A, (byte) 0x7B, (byte) 0x7C, (byte) 0x7D, (byte) 0x7E, (byte) 0x7F,\r
70             (byte) 0x80, (byte) 0x81, (byte) 0x82, (byte) 0x83, (byte) 0x84, (byte) 0x85, (byte) 0x86, (byte) 0x87,\r
71             (byte) 0x88, (byte) 0x89, (byte) 0x8A, (byte) 0x8B, (byte) 0x8C, (byte) 0x8D, (byte) 0x8E, (byte) 0x8F,\r
72             (byte) 0x90, (byte) 0x91, (byte) 0x92, (byte) 0x93, (byte) 0x94, (byte) 0x95, (byte) 0x96, (byte) 0x97,\r
73             (byte) 0x98, (byte) 0x99, (byte) 0x9A, (byte) 0x9B, (byte) 0x9C, (byte) 0x9D, (byte) 0x9E, (byte) 0x9F,\r
74             (byte) 0xA0, (byte) 0xA1, (byte) 0xA2, (byte) 0xA3, (byte) 0xA4, (byte) 0xA5, (byte) 0xA6, (byte) 0xA7,\r
75             (byte) 0xA8, (byte) 0xA9, (byte) 0xAA, (byte) 0xAB, (byte) 0xAC, (byte) 0xAD, (byte) 0xAE, (byte) 0xAF,\r
76             (byte) 0xB0, (byte) 0xB1, (byte) 0xB2, (byte) 0xB3, (byte) 0xB4, (byte) 0xB5, (byte) 0xB6, (byte) 0xB7,\r
77             (byte) 0xB8, (byte) 0xB9, (byte) 0xBA, (byte) 0xBB, (byte) 0xBC, (byte) 0xBD, (byte) 0xBE, (byte) 0xBF,\r
78             (byte) 0xC0, (byte) 0xC1, (byte) 0xC2, (byte) 0xC3, (byte) 0xC4, (byte) 0xC5, (byte) 0xC6, (byte) 0xC7,\r
79             (byte) 0xC8, (byte) 0xC9, (byte) 0xCA, (byte) 0xCB, (byte) 0xCC, (byte) 0xCD, (byte) 0xCE, (byte) 0xCF,\r
80             (byte) 0xD0, (byte) 0xD1, (byte) 0xD2, (byte) 0xD3, (byte) 0xD4, (byte) 0xD5, (byte) 0xD6, (byte) 0xD7,\r
81             (byte) 0xD8, (byte) 0xD9, (byte) 0xDA, (byte) 0xDB, (byte) 0xDC, (byte) 0xDD, (byte) 0xDE, (byte) 0xDF,\r
82             (byte) 0xE0, (byte) 0xE1, (byte) 0xE2, (byte) 0xE3, (byte) 0xE4, (byte) 0xE5, (byte) 0xE6, (byte) 0xE7,\r
83             (byte) 0xE8, (byte) 0xE9, (byte) 0xEA, (byte) 0xEB, (byte) 0xEC, (byte) 0xED, (byte) 0xEE, (byte) 0xEF,\r
84             (byte) 0xF0, (byte) 0xF1, (byte) 0xF2, (byte) 0xF3, (byte) 0xF4, (byte) 0xF5, (byte) 0xF6, (byte) 0xF7,\r
85             (byte) 0xF8, (byte) 0xF9, (byte) 0xFA, (byte) 0xFB, (byte) 0xFC, (byte) 0xFD, (byte) 0xFE, (byte) 0xFF\r
86     };\r
87     \r
88     /**\r
89      * \r
90      */\r
91     public StatisticsTool()\r
92     {\r
93         buffer = new char[BUFFER_SIZE];\r
94         \r
95         buffer[0] = ' ';\r
96         bufIndex = 0;\r
97         bufMax = 1;\r
98     }\r
99     \r
100     private static void usage()\r
101     {\r
102         System.out.println(usageString);\r
103     }\r
104     \r
105 //    private static void exceptionError(Exception e)\r
106 //    {\r
107 //        System.err.println("ioError: " + e.toString());\r
108 //    }\r
109 \r
110     private int nextBuffer(InputFile inputFileArg)\r
111     {\r
112         bufIndex = 0;\r
113         \r
114         return inputFileArg.read(buffer);\r
115     }\r
116     \r
117     public char nextChar()\r
118     {\r
119         if (bufIndex >= bufMax) {\r
120             bufMax = nextBuffer(inputFile);\r
121         }\r
122         \r
123         if (bufMax < 0) {\r
124             return 0;\r
125         }\r
126         \r
127         return buffer[bufIndex++];\r
128     }\r
129     \r
130     public void handleNGram(String key)\r
131     {\r
132         ngrams.put(key);\r
133     }\r
134     \r
135     public Object mapKey(String key)\r
136     {\r
137         return key;\r
138     }\r
139     \r
140     private NGramList dumpNGrams()\r
141     {\r
142         String filename = inputFile.getPath();\r
143         int extension = filename.lastIndexOf(".");\r
144         String outputFileName = filename.substring(0, extension) + ".raw" + filename.substring(extension);\r
145         PrintStream output;\r
146         double cumulative = 0;\r
147         \r
148         try {\r
149             output = new PrintStream(\r
150                 new FileOutputStream(outputFileName), true, "UTF8");\r
151         } catch (IOException e) {\r
152             System.out.println("? Could not open " + outputFileName + " for writing.");\r
153             return null;\r
154         }\r
155         \r
156         System.out.println(inputFile.getFilename() + ": " + ngrams.getUniqueNGrams() + "/" + ngrams.getTotalNGrams());\r
157         \r
158         ArrayList array = new ArrayList(ngrams.values());\r
159         \r
160         Collections.sort(array);\r
161         \r
162         NGramList stats = new NGramList(inputFile);\r
163         int count = 0;\r
164         int totalNGrams = ngrams.getTotalNGrams();\r
165         \r
166         for (Iterator it = array.iterator(); it.hasNext(); count += 1) {\r
167             NGramList.NGram ngram  = (NGramList.NGram) it.next();\r
168             String value = ngram.getValue();\r
169             int refCount = ngram.getRefCount();\r
170             double ratio  = (double) refCount / totalNGrams * 100.0;\r
171             \r
172             cumulative += ratio;\r
173             \r
174             // TODO check should be count < max && cumulative < maxPercent\r
175             if (count < 64) {\r
176                 stats.put(value);\r
177             }\r
178             \r
179             output.println(value + "\t" + refCount + "\t" + ratio + "%\t" + cumulative + "%");\r
180         }\r
181         \r
182         output.close();\r
183         \r
184         return stats;\r
185     }\r
186     \r
187     private void writeStatistics(ArrayList keyList, boolean visual)\r
188     {\r
189         String filename = inputFile.getPath();\r
190         int extension = filename.lastIndexOf(".");\r
191         String outputFileName = filename.substring(0, extension) + "-" + inputFile.getEncoding() +\r
192                                     (visual? "-visual.dat" : ".dat");\r
193         PrintStream output;\r
194         \r
195         try {\r
196             output = new PrintStream(\r
197                 new FileOutputStream(outputFileName), true, "ASCII");\r
198         } catch (IOException e) {\r
199             System.out.println("? Could not open " + outputFileName + " for writing.");\r
200             return;\r
201         }\r
202         \r
203         int i = 0;\r
204         \r
205         output.print("    private static int[] ngrams = {");\r
206         \r
207         for (Iterator it = keyList.iterator(); it.hasNext(); i += 1) {\r
208             Integer ngram = (Integer) it.next();\r
209         \r
210             if (i % 16 == 0) {\r
211                 output.print("\n        ");\r
212             }\r
213             \r
214             output.print("0x" + Utility.hex(ngram.intValue(), 6) + ", ");\r
215         }\r
216         \r
217         output.println("\n    };\n");\r
218         \r
219         /*\r
220          * Generate the byte map\r
221          */\r
222         char[] unicodes = inputFile.decode(allBytes);\r
223         \r
224         for (int b = 0; b < 256; b += 1) {\r
225             char unicode  = unicodes[b];\r
226             int charClass = NGramParser.getCharClass(unicode);\r
227         \r
228             switch (charClass) {\r
229             case NGramParser.C_LETTER:\r
230                 unicodes[b] = Character.toLowerCase(unicode);\r
231                 break;\r
232         \r
233             case NGramParser.C_PUNCT:\r
234                 unicodes[b] = ' ';\r
235                 break;\r
236         \r
237             case NGramParser.C_IGNORE:\r
238             default:\r
239                 unicodes[b] = '\0';\r
240             }\r
241         }\r
242         \r
243         byte[] byteMap = inputFile.encode(unicodes);\r
244         \r
245         output.print("    private static byte[] byteMap = {");\r
246         \r
247         for (int b = 0; b < 256; b += 1) {\r
248             if (b % 8 == 0) {\r
249                 output.print("\n        ");\r
250             }\r
251             \r
252             output.print("(byte) 0x" + Utility.hex(byteMap[b] & 0xFF, 2) + ", ");\r
253         }\r
254         \r
255         output.println("\n    };");\r
256     }\r
257     \r
258     public NGramList collectStatistics(InputFile file)\r
259     {\r
260         if (!file.open()) {\r
261             return null;\r
262         }\r
263         \r
264         inputFile = file;\r
265         \r
266         NGramParser parser = new NGramParser(this);\r
267         \r
268         ngrams = new NGramList(this);\r
269         parser.parse();\r
270         \r
271         file.close();\r
272         \r
273         NGramList stats    = dumpNGrams();\r
274         ArrayList statKeys = new ArrayList(stats.keys());\r
275         \r
276         Collections.sort(statKeys);\r
277         writeStatistics(statKeys, false);\r
278         \r
279         if (inputFile.getVisualOrder()) {\r
280             ArrayList reversed = new ArrayList(statKeys.size());\r
281             \r
282             for (Iterator it = statKeys.iterator(); it.hasNext();) {\r
283                 Integer key = (Integer) it.next();\r
284                 int k = key.intValue();\r
285                 int r = 0;\r
286                 \r
287                 while (k != 0) {\r
288                     r = (r << 8) | (k & 0xFF);\r
289                     k >>= 8;\r
290                 }\r
291                 \r
292                 reversed.add(new Integer(r));\r
293             }\r
294             \r
295             Collections.sort(reversed);\r
296             writeStatistics(reversed, true);\r
297         }\r
298         \r
299         return stats;\r
300     }\r
301     \r
302     public static void main(String[] args)\r
303     {\r
304         List list = Arrays.asList(args);\r
305         InputFile[] input_files = new InputFile[args.length];\r
306         int file_count = 0;\r
307         String encoding = null;\r
308         boolean run_checker = false;\r
309         boolean encoding_test = false;\r
310         boolean visual_order = false;\r
311         \r
312         for (Iterator it = list.iterator(); it.hasNext(); /*anything?*/) {\r
313             String arg = (String) it.next();\r
314             \r
315             if (arg.equals("-v")) {\r
316                 visual_order = true;\r
317             } else if (arg.equals("-l")) {\r
318                 visual_order = false;\r
319             } else if (arg.equals("-c")) {\r
320                 run_checker = true;\r
321             } else if (arg.equals("-t")) {\r
322                 encoding_test = true;\r
323             } else if (arg.equals("-e")) {\r
324                 if (it.hasNext()) {\r
325                     encoding = (String) it.next();\r
326                 } else {\r
327                     System.err.println("Error: missing encoding.");\r
328                 }\r
329             } else if (arg.startsWith("-")) {\r
330                 if (! (arg.equals("-h") || arg.equals("-?"))) {\r
331                     System.err.println("Error: unknown option " + arg);\r
332                 }\r
333                 \r
334                 usage();\r
335             } else {\r
336                 input_files[file_count++] = new InputFile(arg, encoding, visual_order);\r
337             }\r
338         }\r
339 \r
340         if(file_count == 0){\r
341             System.err.println("Error: there are no files to process.");\r
342             usage();\r
343         }\r
344         \r
345         StatisticsTool tool = new StatisticsTool();\r
346         Checker[] checkers  = new Checker[file_count];\r
347         \r
348         for(int i = 0; i < file_count; i += 1) {\r
349             InputFile file = input_files[i];\r
350             \r
351             checkers[i] = new Checker(tool.collectStatistics(file), file);\r
352         }\r
353         \r
354         System.out.println();\r
355         \r
356         /**\r
357          * Checkers\r
358          */\r
359         if (run_checker) {\r
360             for(int c = 0; c < file_count; c += 1) {\r
361                 Checker checker = checkers[c];\r
362                 \r
363                 for(int f = 0; f < file_count; f += 1) {\r
364                     checker.check(input_files[f]);\r
365                 }\r
366             }\r
367             \r
368         }\r
369 \r
370         /*\r
371          * Detection test\r
372          */\r
373         if (encoding_test) {\r
374             char[] buffer   = new char[128];\r
375             \r
376             System.out.println("Detection test");\r
377             \r
378             for (int f = 0; f < file_count; f += 1) {\r
379                 InputFile file = input_files[f];\r
380                 int[] histogram = new int[file_count];\r
381                 int charCount, misses = 0;\r
382                 \r
383                 System.out.println(file.getFilename() + "(" + file.getEncoding() + "):");\r
384                 file.open();\r
385                 \r
386                 for (int c = 0; c < file_count; c += 1) {\r
387                     checkers[c].setMapper(file);                \r
388                 }\r
389                 \r
390                 // for each buffer\r
391                 //     for each checker\r
392                 //         call checkBuffer, save score\r
393                 //     find highest score, update histogram for that checker\r
394                 // show checker histogram\r
395                 \r
396                 while ((charCount = file.read(buffer)) > 0) {\r
397                     int[] scores = new int[file_count];\r
398                     int bestFit = -1, maxScore = 0;\r
399                     \r
400                     for (int c = 0; c < file_count; c += 1) {\r
401                         scores[c] = checkers[c].checkBuffer(buffer, charCount);\r
402                     }\r
403                     \r
404                     for (int c = 0; c < file_count; c += 1) {\r
405                         int score = scores[c];\r
406                         \r
407                         if (score > maxScore) {\r
408                             maxScore = score;\r
409                             bestFit = c;\r
410                         }\r
411                     }\r
412                     \r
413                     if (bestFit >= 0) {\r
414                         histogram[bestFit] += 1;                    \r
415                     } else {\r
416                         misses += 1;\r
417                     }\r
418                 }\r
419                 \r
420                 for (int c = 0; c < file_count; c += 1) {\r
421                     System.out.println("    " + checkers[c].getLanguage() + ": " + histogram[c]);\r
422                 }\r
423                 \r
424                 if (misses > 0) {\r
425                     System.out.println("    NONE: " + misses);\r
426                 }\r
427                 \r
428                 System.out.println();\r
429             }            \r
430         }\r
431     }\r
432 }\r