~ubuntu-branches/ubuntu/vivid/icu4j-4.4/vivid

« back to all changes in this revision

Viewing changes to tools/misc/src/com/ibm/icu/dev/tool/charsetdet/mbcs/BIG5Tool.java

  • Committer: Bazaar Package Importer
  • Author(s): Niels Thykier
  • Date: 2011-08-02 15:50:33 UTC
  • Revision ID: james.westby@ubuntu.com-20110802155033-itjzsl21y2lqdonn
Tags: upstream-4.4.2
ImportĀ upstreamĀ versionĀ 4.4.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}