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