Wed, 22 Jan 2014 12:37:28 -0800
Added tag jdk8u5-b05 for changeset b90de55aca30
kvn@3038 | 1 | /** |
kvn@3038 | 2 | * @test |
kvn@3038 | 3 | * @bug 7070134 |
kvn@3038 | 4 | * @summary Hotspot crashes with sigsegv from PorterStemmer |
kvn@3038 | 5 | * |
kvn@3038 | 6 | * @run shell Test7070134.sh |
kvn@3038 | 7 | */ |
kvn@3038 | 8 | |
kvn@3038 | 9 | /* |
kvn@3038 | 10 | |
kvn@3038 | 11 | Porter stemmer in Java. The original paper is in |
kvn@3038 | 12 | |
kvn@3038 | 13 | Porter, 1980, An algorithm for suffix stripping, Program, Vol. 14, |
kvn@3038 | 14 | no. 3, pp 130-137, |
kvn@3038 | 15 | |
kvn@3749 | 16 | http://www.tartarus.org/~martin/PorterStemmer |
kvn@3749 | 17 | |
kvn@3749 | 18 | The software is completely free for any purpose, unless notes at the head |
kvn@3749 | 19 | of the program text indicates otherwise (which is rare). In any case, |
kvn@3749 | 20 | the notes about licensing are never more restrictive than the BSD License. |
kvn@3749 | 21 | |
kvn@3749 | 22 | In every case where the software is not written by me (Martin Porter), |
kvn@3749 | 23 | this licensing arrangement has been endorsed by the contributor, and it is |
kvn@3749 | 24 | therefore unnecessary to ask the contributor again to confirm it. |
kvn@3749 | 25 | |
kvn@3749 | 26 | I have not asked any contributors (or their employers, if they have them) |
kvn@3749 | 27 | for proofs that they have the right to distribute their software in this way. |
kvn@3038 | 28 | |
kvn@3038 | 29 | History: |
kvn@3038 | 30 | |
kvn@3038 | 31 | Release 1 |
kvn@3038 | 32 | |
kvn@3038 | 33 | Bug 1 (reported by Gonzalo Parra 16/10/99) fixed as marked below. |
kvn@3038 | 34 | The words 'aed', 'eed', 'oed' leave k at 'a' for step 3, and b[k-1] |
kvn@3038 | 35 | is then out outside the bounds of b. |
kvn@3038 | 36 | |
kvn@3038 | 37 | Release 2 |
kvn@3038 | 38 | |
kvn@3038 | 39 | Similarly, |
kvn@3038 | 40 | |
kvn@3038 | 41 | Bug 2 (reported by Steve Dyrdahl 22/2/00) fixed as marked below. |
kvn@3038 | 42 | 'ion' by itself leaves j = -1 in the test for 'ion' in step 5, and |
kvn@3038 | 43 | b[j] is then outside the bounds of b. |
kvn@3038 | 44 | |
kvn@3038 | 45 | Release 3 |
kvn@3038 | 46 | |
kvn@3038 | 47 | Considerably revised 4/9/00 in the light of many helpful suggestions |
kvn@3038 | 48 | from Brian Goetz of Quiotix Corporation (brian@quiotix.com). |
kvn@3038 | 49 | |
kvn@3038 | 50 | Release 4 |
kvn@3038 | 51 | |
kvn@3038 | 52 | */ |
kvn@3038 | 53 | |
kvn@3038 | 54 | import java.io.*; |
kvn@3038 | 55 | |
kvn@3038 | 56 | /** |
kvn@3038 | 57 | * Stemmer, implementing the Porter Stemming Algorithm |
kvn@3038 | 58 | * |
kvn@3038 | 59 | * The Stemmer class transforms a word into its root form. The input |
kvn@3038 | 60 | * word can be provided a character at time (by calling add()), or at once |
kvn@3038 | 61 | * by calling one of the various stem(something) methods. |
kvn@3038 | 62 | */ |
kvn@3038 | 63 | |
kvn@3038 | 64 | class Stemmer |
kvn@3038 | 65 | { private char[] b; |
kvn@3038 | 66 | private int i, /* offset into b */ |
kvn@3038 | 67 | i_end, /* offset to end of stemmed word */ |
kvn@3038 | 68 | j, k; |
kvn@3038 | 69 | private static final int INC = 50; |
kvn@3038 | 70 | /* unit of size whereby b is increased */ |
kvn@3038 | 71 | public Stemmer() |
kvn@3038 | 72 | { b = new char[INC]; |
kvn@3038 | 73 | i = 0; |
kvn@3038 | 74 | i_end = 0; |
kvn@3038 | 75 | } |
kvn@3038 | 76 | |
kvn@3038 | 77 | /** |
kvn@3038 | 78 | * Add a character to the word being stemmed. When you are finished |
kvn@3038 | 79 | * adding characters, you can call stem(void) to stem the word. |
kvn@3038 | 80 | */ |
kvn@3038 | 81 | |
kvn@3038 | 82 | public void add(char ch) |
kvn@3038 | 83 | { if (i == b.length) |
kvn@3038 | 84 | { char[] new_b = new char[i+INC]; |
kvn@3038 | 85 | for (int c = 0; c < i; c++) new_b[c] = b[c]; |
kvn@3038 | 86 | b = new_b; |
kvn@3038 | 87 | } |
kvn@3038 | 88 | b[i++] = ch; |
kvn@3038 | 89 | } |
kvn@3038 | 90 | |
kvn@3038 | 91 | |
kvn@3038 | 92 | /** Adds wLen characters to the word being stemmed contained in a portion |
kvn@3038 | 93 | * of a char[] array. This is like repeated calls of add(char ch), but |
kvn@3038 | 94 | * faster. |
kvn@3038 | 95 | */ |
kvn@3038 | 96 | |
kvn@3038 | 97 | public void add(char[] w, int wLen) |
kvn@3038 | 98 | { if (i+wLen >= b.length) |
kvn@3038 | 99 | { char[] new_b = new char[i+wLen+INC]; |
kvn@3038 | 100 | for (int c = 0; c < i; c++) new_b[c] = b[c]; |
kvn@3038 | 101 | b = new_b; |
kvn@3038 | 102 | } |
kvn@3038 | 103 | for (int c = 0; c < wLen; c++) b[i++] = w[c]; |
kvn@3038 | 104 | } |
kvn@3038 | 105 | |
kvn@3038 | 106 | /** |
kvn@3038 | 107 | * After a word has been stemmed, it can be retrieved by toString(), |
kvn@3038 | 108 | * or a reference to the internal buffer can be retrieved by getResultBuffer |
kvn@3038 | 109 | * and getResultLength (which is generally more efficient.) |
kvn@3038 | 110 | */ |
kvn@3038 | 111 | public String toString() { return new String(b,0,i_end); } |
kvn@3038 | 112 | |
kvn@3038 | 113 | /** |
kvn@3038 | 114 | * Returns the length of the word resulting from the stemming process. |
kvn@3038 | 115 | */ |
kvn@3038 | 116 | public int getResultLength() { return i_end; } |
kvn@3038 | 117 | |
kvn@3038 | 118 | /** |
kvn@3038 | 119 | * Returns a reference to a character buffer containing the results of |
kvn@3038 | 120 | * the stemming process. You also need to consult getResultLength() |
kvn@3038 | 121 | * to determine the length of the result. |
kvn@3038 | 122 | */ |
kvn@3038 | 123 | public char[] getResultBuffer() { return b; } |
kvn@3038 | 124 | |
kvn@3038 | 125 | /* cons(i) is true <=> b[i] is a consonant. */ |
kvn@3038 | 126 | |
kvn@3038 | 127 | private final boolean cons(int i) |
kvn@3038 | 128 | { switch (b[i]) |
kvn@3038 | 129 | { case 'a': case 'e': case 'i': case 'o': case 'u': return false; |
kvn@3038 | 130 | case 'y': return (i==0) ? true : !cons(i-1); |
kvn@3038 | 131 | default: return true; |
kvn@3038 | 132 | } |
kvn@3038 | 133 | } |
kvn@3038 | 134 | |
kvn@3038 | 135 | /* m() measures the number of consonant sequences between 0 and j. if c is |
kvn@3038 | 136 | a consonant sequence and v a vowel sequence, and <..> indicates arbitrary |
kvn@3038 | 137 | presence, |
kvn@3038 | 138 | |
kvn@3038 | 139 | <c><v> gives 0 |
kvn@3038 | 140 | <c>vc<v> gives 1 |
kvn@3038 | 141 | <c>vcvc<v> gives 2 |
kvn@3038 | 142 | <c>vcvcvc<v> gives 3 |
kvn@3038 | 143 | .... |
kvn@3038 | 144 | */ |
kvn@3038 | 145 | |
kvn@3038 | 146 | private final int m() |
kvn@3038 | 147 | { int n = 0; |
kvn@3038 | 148 | int i = 0; |
kvn@3038 | 149 | while(true) |
kvn@3038 | 150 | { if (i > j) return n; |
kvn@3038 | 151 | if (! cons(i)) break; i++; |
kvn@3038 | 152 | } |
kvn@3038 | 153 | i++; |
kvn@3038 | 154 | while(true) |
kvn@3038 | 155 | { while(true) |
kvn@3038 | 156 | { if (i > j) return n; |
kvn@3038 | 157 | if (cons(i)) break; |
kvn@3038 | 158 | i++; |
kvn@3038 | 159 | } |
kvn@3038 | 160 | i++; |
kvn@3038 | 161 | n++; |
kvn@3038 | 162 | while(true) |
kvn@3038 | 163 | { if (i > j) return n; |
kvn@3038 | 164 | if (! cons(i)) break; |
kvn@3038 | 165 | i++; |
kvn@3038 | 166 | } |
kvn@3038 | 167 | i++; |
kvn@3038 | 168 | } |
kvn@3038 | 169 | } |
kvn@3038 | 170 | |
kvn@3038 | 171 | /* vowelinstem() is true <=> 0,...j contains a vowel */ |
kvn@3038 | 172 | |
kvn@3038 | 173 | private final boolean vowelinstem() |
kvn@3038 | 174 | { int i; for (i = 0; i <= j; i++) if (! cons(i)) return true; |
kvn@3038 | 175 | return false; |
kvn@3038 | 176 | } |
kvn@3038 | 177 | |
kvn@3038 | 178 | /* doublec(j) is true <=> j,(j-1) contain a double consonant. */ |
kvn@3038 | 179 | |
kvn@3038 | 180 | private final boolean doublec(int j) |
kvn@3038 | 181 | { if (j < 1) return false; |
kvn@3038 | 182 | if (b[j] != b[j-1]) return false; |
kvn@3038 | 183 | return cons(j); |
kvn@3038 | 184 | } |
kvn@3038 | 185 | |
kvn@3038 | 186 | /* cvc(i) is true <=> i-2,i-1,i has the form consonant - vowel - consonant |
kvn@3038 | 187 | and also if the second c is not w,x or y. this is used when trying to |
kvn@3038 | 188 | restore an e at the end of a short word. e.g. |
kvn@3038 | 189 | |
kvn@3038 | 190 | cav(e), lov(e), hop(e), crim(e), but |
kvn@3038 | 191 | snow, box, tray. |
kvn@3038 | 192 | |
kvn@3038 | 193 | */ |
kvn@3038 | 194 | |
kvn@3038 | 195 | private final boolean cvc(int i) |
kvn@3038 | 196 | { if (i < 2 || !cons(i) || cons(i-1) || !cons(i-2)) return false; |
kvn@3038 | 197 | { int ch = b[i]; |
kvn@3038 | 198 | if (ch == 'w' || ch == 'x' || ch == 'y') return false; |
kvn@3038 | 199 | } |
kvn@3038 | 200 | return true; |
kvn@3038 | 201 | } |
kvn@3038 | 202 | |
kvn@3038 | 203 | private final boolean ends(String s) |
kvn@3038 | 204 | { int l = s.length(); |
kvn@3038 | 205 | int o = k-l+1; |
kvn@3038 | 206 | if (o < 0) return false; |
kvn@3038 | 207 | for (int i = 0; i < l; i++) if (b[o+i] != s.charAt(i)) return false; |
kvn@3038 | 208 | j = k-l; |
kvn@3038 | 209 | return true; |
kvn@3038 | 210 | } |
kvn@3038 | 211 | |
kvn@3038 | 212 | /* setto(s) sets (j+1),...k to the characters in the string s, readjusting |
kvn@3038 | 213 | k. */ |
kvn@3038 | 214 | |
kvn@3038 | 215 | private final void setto(String s) |
kvn@3038 | 216 | { int l = s.length(); |
kvn@3038 | 217 | int o = j+1; |
kvn@3038 | 218 | for (int i = 0; i < l; i++) b[o+i] = s.charAt(i); |
kvn@3038 | 219 | k = j+l; |
kvn@3038 | 220 | } |
kvn@3038 | 221 | |
kvn@3038 | 222 | /* r(s) is used further down. */ |
kvn@3038 | 223 | |
kvn@3038 | 224 | private final void r(String s) { if (m() > 0) setto(s); } |
kvn@3038 | 225 | |
kvn@3038 | 226 | /* step1() gets rid of plurals and -ed or -ing. e.g. |
kvn@3038 | 227 | |
kvn@3038 | 228 | caresses -> caress |
kvn@3038 | 229 | ponies -> poni |
kvn@3038 | 230 | ties -> ti |
kvn@3038 | 231 | caress -> caress |
kvn@3038 | 232 | cats -> cat |
kvn@3038 | 233 | |
kvn@3038 | 234 | feed -> feed |
kvn@3038 | 235 | agreed -> agree |
kvn@3038 | 236 | disabled -> disable |
kvn@3038 | 237 | |
kvn@3038 | 238 | matting -> mat |
kvn@3038 | 239 | mating -> mate |
kvn@3038 | 240 | meeting -> meet |
kvn@3038 | 241 | milling -> mill |
kvn@3038 | 242 | messing -> mess |
kvn@3038 | 243 | |
kvn@3038 | 244 | meetings -> meet |
kvn@3038 | 245 | |
kvn@3038 | 246 | */ |
kvn@3038 | 247 | |
kvn@3038 | 248 | private final void step1() |
kvn@3038 | 249 | { if (b[k] == 's') |
kvn@3038 | 250 | { if (ends("sses")) k -= 2; else |
kvn@3038 | 251 | if (ends("ies")) setto("i"); else |
kvn@3038 | 252 | if (b[k-1] != 's') k--; |
kvn@3038 | 253 | } |
kvn@3038 | 254 | if (ends("eed")) { if (m() > 0) k--; } else |
kvn@3038 | 255 | if ((ends("ed") || ends("ing")) && vowelinstem()) |
kvn@3038 | 256 | { k = j; |
kvn@3038 | 257 | if (ends("at")) setto("ate"); else |
kvn@3038 | 258 | if (ends("bl")) setto("ble"); else |
kvn@3038 | 259 | if (ends("iz")) setto("ize"); else |
kvn@3038 | 260 | if (doublec(k)) |
kvn@3038 | 261 | { k--; |
kvn@3038 | 262 | { int ch = b[k]; |
kvn@3038 | 263 | if (ch == 'l' || ch == 's' || ch == 'z') k++; |
kvn@3038 | 264 | } |
kvn@3038 | 265 | } |
kvn@3038 | 266 | else if (m() == 1 && cvc(k)) setto("e"); |
kvn@3038 | 267 | } |
kvn@3038 | 268 | } |
kvn@3038 | 269 | |
kvn@3038 | 270 | /* step2() turns terminal y to i when there is another vowel in the stem. */ |
kvn@3038 | 271 | |
kvn@3038 | 272 | private final void step2() { if (ends("y") && vowelinstem()) b[k] = 'i'; } |
kvn@3038 | 273 | |
kvn@3038 | 274 | /* step3() maps double suffices to single ones. so -ization ( = -ize plus |
kvn@3038 | 275 | -ation) maps to -ize etc. note that the string before the suffix must give |
kvn@3038 | 276 | m() > 0. */ |
kvn@3038 | 277 | |
kvn@3038 | 278 | private final void step3() { if (k == 0) return; /* For Bug 1 */ switch (b[k-1]) |
kvn@3038 | 279 | { |
kvn@3038 | 280 | case 'a': if (ends("ational")) { r("ate"); break; } |
kvn@3038 | 281 | if (ends("tional")) { r("tion"); break; } |
kvn@3038 | 282 | break; |
kvn@3038 | 283 | case 'c': if (ends("enci")) { r("ence"); break; } |
kvn@3038 | 284 | if (ends("anci")) { r("ance"); break; } |
kvn@3038 | 285 | break; |
kvn@3038 | 286 | case 'e': if (ends("izer")) { r("ize"); break; } |
kvn@3038 | 287 | break; |
kvn@3038 | 288 | case 'l': if (ends("bli")) { r("ble"); break; } |
kvn@3038 | 289 | if (ends("alli")) { r("al"); break; } |
kvn@3038 | 290 | if (ends("entli")) { r("ent"); break; } |
kvn@3038 | 291 | if (ends("eli")) { r("e"); break; } |
kvn@3038 | 292 | if (ends("ousli")) { r("ous"); break; } |
kvn@3038 | 293 | break; |
kvn@3038 | 294 | case 'o': if (ends("ization")) { r("ize"); break; } |
kvn@3038 | 295 | if (ends("ation")) { r("ate"); break; } |
kvn@3038 | 296 | if (ends("ator")) { r("ate"); break; } |
kvn@3038 | 297 | break; |
kvn@3038 | 298 | case 's': if (ends("alism")) { r("al"); break; } |
kvn@3038 | 299 | if (ends("iveness")) { r("ive"); break; } |
kvn@3038 | 300 | if (ends("fulness")) { r("ful"); break; } |
kvn@3038 | 301 | if (ends("ousness")) { r("ous"); break; } |
kvn@3038 | 302 | break; |
kvn@3038 | 303 | case 't': if (ends("aliti")) { r("al"); break; } |
kvn@3038 | 304 | if (ends("iviti")) { r("ive"); break; } |
kvn@3038 | 305 | if (ends("biliti")) { r("ble"); break; } |
kvn@3038 | 306 | break; |
kvn@3038 | 307 | case 'g': if (ends("logi")) { r("log"); break; } |
kvn@3038 | 308 | } } |
kvn@3038 | 309 | |
kvn@3038 | 310 | /* step4() deals with -ic-, -full, -ness etc. similar strategy to step3. */ |
kvn@3038 | 311 | |
kvn@3038 | 312 | private final void step4() { switch (b[k]) |
kvn@3038 | 313 | { |
kvn@3038 | 314 | case 'e': if (ends("icate")) { r("ic"); break; } |
kvn@3038 | 315 | if (ends("ative")) { r(""); break; } |
kvn@3038 | 316 | if (ends("alize")) { r("al"); break; } |
kvn@3038 | 317 | break; |
kvn@3038 | 318 | case 'i': if (ends("iciti")) { r("ic"); break; } |
kvn@3038 | 319 | break; |
kvn@3038 | 320 | case 'l': if (ends("ical")) { r("ic"); break; } |
kvn@3038 | 321 | if (ends("ful")) { r(""); break; } |
kvn@3038 | 322 | break; |
kvn@3038 | 323 | case 's': if (ends("ness")) { r(""); break; } |
kvn@3038 | 324 | break; |
kvn@3038 | 325 | } } |
kvn@3038 | 326 | |
kvn@3038 | 327 | /* step5() takes off -ant, -ence etc., in context <c>vcvc<v>. */ |
kvn@3038 | 328 | |
kvn@3038 | 329 | private final void step5() |
kvn@3038 | 330 | { if (k == 0) return; /* for Bug 1 */ switch (b[k-1]) |
kvn@3038 | 331 | { case 'a': if (ends("al")) break; return; |
kvn@3038 | 332 | case 'c': if (ends("ance")) break; |
kvn@3038 | 333 | if (ends("ence")) break; return; |
kvn@3038 | 334 | case 'e': if (ends("er")) break; return; |
kvn@3038 | 335 | case 'i': if (ends("ic")) break; return; |
kvn@3038 | 336 | case 'l': if (ends("able")) break; |
kvn@3038 | 337 | if (ends("ible")) break; return; |
kvn@3038 | 338 | case 'n': if (ends("ant")) break; |
kvn@3038 | 339 | if (ends("ement")) break; |
kvn@3038 | 340 | if (ends("ment")) break; |
kvn@3038 | 341 | /* element etc. not stripped before the m */ |
kvn@3038 | 342 | if (ends("ent")) break; return; |
kvn@3038 | 343 | case 'o': if (ends("ion") && j >= 0 && (b[j] == 's' || b[j] == 't')) break; |
kvn@3038 | 344 | /* j >= 0 fixes Bug 2 */ |
kvn@3038 | 345 | if (ends("ou")) break; return; |
kvn@3038 | 346 | /* takes care of -ous */ |
kvn@3038 | 347 | case 's': if (ends("ism")) break; return; |
kvn@3038 | 348 | case 't': if (ends("ate")) break; |
kvn@3038 | 349 | if (ends("iti")) break; return; |
kvn@3038 | 350 | case 'u': if (ends("ous")) break; return; |
kvn@3038 | 351 | case 'v': if (ends("ive")) break; return; |
kvn@3038 | 352 | case 'z': if (ends("ize")) break; return; |
kvn@3038 | 353 | default: return; |
kvn@3038 | 354 | } |
kvn@3038 | 355 | if (m() > 1) k = j; |
kvn@3038 | 356 | } |
kvn@3038 | 357 | |
kvn@3038 | 358 | /* step6() removes a final -e if m() > 1. */ |
kvn@3038 | 359 | |
kvn@3038 | 360 | private final void step6() |
kvn@3038 | 361 | { j = k; |
kvn@3038 | 362 | if (b[k] == 'e') |
kvn@3038 | 363 | { int a = m(); |
kvn@3038 | 364 | if (a > 1 || a == 1 && !cvc(k-1)) k--; |
kvn@3038 | 365 | } |
kvn@3038 | 366 | if (b[k] == 'l' && doublec(k) && m() > 1) k--; |
kvn@3038 | 367 | } |
kvn@3038 | 368 | |
kvn@3038 | 369 | /** Stem the word placed into the Stemmer buffer through calls to add(). |
kvn@3038 | 370 | * Returns true if the stemming process resulted in a word different |
kvn@3038 | 371 | * from the input. You can retrieve the result with |
kvn@3038 | 372 | * getResultLength()/getResultBuffer() or toString(). |
kvn@3038 | 373 | */ |
kvn@3038 | 374 | public void stem() |
kvn@3038 | 375 | { k = i - 1; |
kvn@3038 | 376 | if (k > 1) { step1(); step2(); step3(); step4(); step5(); step6(); } |
kvn@3038 | 377 | i_end = k+1; i = 0; |
kvn@3038 | 378 | } |
kvn@3038 | 379 | |
kvn@3038 | 380 | /** Test program for demonstrating the Stemmer. It reads text from a |
kvn@3038 | 381 | * a list of files, stems each word, and writes the result to standard |
kvn@3038 | 382 | * output. Note that the word stemmed is expected to be in lower case: |
kvn@3038 | 383 | * forcing lower case must be done outside the Stemmer class. |
kvn@3038 | 384 | * Usage: Stemmer file-name file-name ... |
kvn@3038 | 385 | */ |
kvn@3038 | 386 | public static void main(String[] args) |
kvn@3038 | 387 | { |
kvn@3038 | 388 | char[] w = new char[501]; |
kvn@3038 | 389 | Stemmer s = new Stemmer(); |
kvn@3038 | 390 | for (int i = 0; i < args.length; i++) |
kvn@3038 | 391 | try |
kvn@3038 | 392 | { |
kvn@3038 | 393 | FileInputStream in = new FileInputStream(args[i]); |
kvn@3038 | 394 | |
kvn@3038 | 395 | try |
kvn@3038 | 396 | { while(true) |
kvn@3038 | 397 | |
kvn@3038 | 398 | { int ch = in.read(); |
kvn@3038 | 399 | if (Character.isLetter((char) ch)) |
kvn@3038 | 400 | { |
kvn@3038 | 401 | int j = 0; |
kvn@3038 | 402 | while(true) |
kvn@3038 | 403 | { ch = Character.toLowerCase((char) ch); |
kvn@3038 | 404 | w[j] = (char) ch; |
kvn@3038 | 405 | if (j < 500) j++; |
kvn@3038 | 406 | ch = in.read(); |
kvn@3038 | 407 | if (!Character.isLetter((char) ch)) |
kvn@3038 | 408 | { |
kvn@3038 | 409 | /* to test add(char ch) */ |
kvn@3038 | 410 | for (int c = 0; c < j; c++) s.add(w[c]); |
kvn@3038 | 411 | |
kvn@3038 | 412 | /* or, to test add(char[] w, int j) */ |
kvn@3038 | 413 | /* s.add(w, j); */ |
kvn@3038 | 414 | |
kvn@3038 | 415 | s.stem(); |
kvn@3038 | 416 | { String u; |
kvn@3038 | 417 | |
kvn@3038 | 418 | /* and now, to test toString() : */ |
kvn@3038 | 419 | u = s.toString(); |
kvn@3038 | 420 | |
kvn@3038 | 421 | /* to test getResultBuffer(), getResultLength() : */ |
kvn@3038 | 422 | /* u = new String(s.getResultBuffer(), 0, s.getResultLength()); */ |
kvn@3038 | 423 | |
kvn@3038 | 424 | System.out.print(u); |
kvn@3038 | 425 | } |
kvn@3038 | 426 | break; |
kvn@3038 | 427 | } |
kvn@3038 | 428 | } |
kvn@3038 | 429 | } |
kvn@3038 | 430 | if (ch < 0) break; |
kvn@3038 | 431 | System.out.print((char)ch); |
kvn@3038 | 432 | } |
kvn@3038 | 433 | } |
kvn@3038 | 434 | catch (IOException e) |
kvn@3038 | 435 | { System.out.println("error reading " + args[i]); |
kvn@3038 | 436 | break; |
kvn@3038 | 437 | } |
kvn@3038 | 438 | } |
kvn@3038 | 439 | catch (FileNotFoundException e) |
kvn@3038 | 440 | { System.out.println("file " + args[i] + " not found"); |
kvn@3038 | 441 | break; |
kvn@3038 | 442 | } |
kvn@3038 | 443 | } |
kvn@3038 | 444 | } |