1 */
110
111 package org.apache.poi.util;
112
113
114
115 import java.io.UnsupportedEncodingException;
116
117
118
119 import java.text.NumberFormat;
120
121 import java.text.FieldPosition;
122
123
124
125 /**
126
127 * Title: String Utility Description: Collection of string handling utilities
128
129 *
130
131 * Now it is quite confusing: the method pairs, in which
132
133 * one of them write data and other read written data are:
134
135 * putUncompressedUnicodeHigh and getFromUnicode
136
137 * putUncompressedUnicode and getFromUnicodeHigh
138
139 *
140
141 *@author Andrew C. Oliver
142
143 *@author Sergei Kozello (sergeikozello at mail.ru)
144
145 *@created May 10, 2002
146
147 *@version 1.0
148
149 */
150
151
152
153 public class StringUtil {
154
155
156
157 private final static String ENCODING="ISO-8859-1";
158
159 /**
160
161 * Constructor for the StringUtil object
162
163 */
164
165 private StringUtil() { }
166
167
168
169
170
171 /**
172
173 * given a byte array of 16-bit unicode characters, compress to 8-bit and
174
175 * return a string
176
177 *
178
179 * { 0x16, 0x00 } -> 0x16
180
181 *
182
183 *@param string the byte array to be converted
184
185 *@param offset the initial offset into the
186
187 * byte array. it is assumed that string[ offset ] and string[ offset +
188
189 * 1 ] contain the first 16-bit unicode character
190
191 *@param len
192
193 *@return the converted string
194
195 *@exception ArrayIndexOutOfBoundsException if offset is out of bounds for
196
197 * the byte array (i.e., is negative or is greater than or equal to
198
199 * string.length)
200
201 *@exception IllegalArgumentException if len is too large (i.e.,
202
203 * there is not enough data in string to create a String of that
204
205 * length)
206
207 *@len the length of the final string
208
209 */
210
211
212
213 public static String getFromUnicodeHigh(final byte[] string,
214
215 final int offset, final int len)
216
217 throws ArrayIndexOutOfBoundsException, IllegalArgumentException {
218
219
220
221 if ((offset < 0) || (offset >= string.length)) {
222
223 throw new ArrayIndexOutOfBoundsException("Illegal offset");
224
225 }
226
227 if ((len < 0) || (((string.length - offset) / 2) < len)) {
228
229 throw new IllegalArgumentException("Illegal length");
230
231 }
232
233
234
235 char[] chars = new char[ len ];
236
237 for ( int i = 0; i < chars.length; i++ ) {
238
239 chars[i] = (char)( string[ offset + ( 2*i ) ] & 0xFF |
240
241 ( string[ offset + ( 2*i+1 ) ] << 8 ) );
242
243 }
244
245
246
247 return new String( chars );
248
249 }
250
251
252
253
254
255 /**
256
257 * given a byte array of 16-bit unicode characters, compress to 8-bit and
258
259 * return a string
260
261 *
262
263 * { 0x16, 0x00 } -> 0x16
264
265 *
266
267 *@param string the byte array to be converted
268
269 *@return the converted string
270
271 */
272
273
274
275 public static String getFromUnicodeHigh( final byte[] string ) {
276
277 return getFromUnicodeHigh( string, 0, string.length / 2 );
278
279 }
280
281
282
283
284
285 /**
286
287 * given a byte array of 16-bit unicode characters, compress to 8-bit and
288
289 * return a string
290
291 *
292
293 * { 0x00, 0x16 } -> 0x16
294
295 *
296
297 *@param string the byte array to be converted
298
299 *@param offset the initial offset into the
300
301 * byte array. it is assumed that string[ offset ] and string[ offset +
302
303 * 1 ] contain the first 16-bit unicode character
304
305 *@param len
306
307 *@return the converted string
308
309 *@exception ArrayIndexOutOfBoundsException if offset is out of bounds for
310
311 * the byte array (i.e., is negative or is greater than or equal to
312
313 * string.length)
314
315 *@exception IllegalArgumentException if len is too large (i.e.,
316
317 * there is not enough data in string to create a String of that
318
319 * length)
320
321 *@len the length of the final string
322
323 */
324
325
326
327 public static String getFromUnicode(final byte[] string,
328
329 final int offset, final int len)
330
331 throws ArrayIndexOutOfBoundsException, IllegalArgumentException {
332
333 if ((offset < 0) || (offset >= string.length)) {
334
335 throw new ArrayIndexOutOfBoundsException("Illegal offset");
336
337 }
338
339 if ((len < 0) || (((string.length - offset) / 2) < len)) {
340
341 throw new IllegalArgumentException("Illegal length");
342
343 }
344
345
346
347
348
349 char[] chars = new char[ len ];
350
351 for ( int i = 0; i < chars.length; i++ ) {
352
353 chars[i] = (char)( ( string[ offset + ( 2*i ) ] << 8 ) +
354
355 string[ offset + ( 2*i+1 ) ] );
356
357 }
358
359
360
361 return new String( chars );
362
363 }
364
365
366
367
368
369 /**
370
371 * given a byte array of 16-bit unicode characters, compress to 8-bit and
372
373 * return a string
374
375 *
376
377 * { 0x00, 0x16 } -> 0x16
378
379 *
380
381 *@param string the byte array to be converted
382
383 *@return the converted string
384
385 */
386
387
388
389 public static String getFromUnicode(final byte[] string) {
390
391 return getFromUnicode(string, 0, string.length / 2);
392
393 }
394
395
396
397
398
399 /**
400
401 * write compressed unicode
402
403 *
404
405 *@param input the String containing the data to be written
406
407 *@param output the byte array to which the data is to be written
408
409 *@param offset an offset into the byte arrat at which the data is start
410
411 * when written
412
413 */
414
415
416
417 public static void putCompressedUnicode(final String input,
418
419 final byte[] output,
420
421 final int offset) {
422
423 int strlen = input.length();
424
425
426
427 for (int k = 0; k < strlen; k++) {
428
429 output[offset + k] = (byte) input.charAt(k);
430
431 }
432
433 }
434
435
436
437
438
439 /**
440
441 * Write uncompressed unicode
442
443 *
444
445 *@param input the String containing the unicode data to be written
446
447 *@param output the byte array to hold the uncompressed unicode
448
449 *@param offset the offset to start writing into the byte array
450
451 */
452
453
454
455 public static void putUncompressedUnicode(final String input,
456
457 final byte[] output,
458
459 final int offset) {
460
461 int strlen = input.length();
462
463
464
465 for (int k = 0; k < strlen; k++) {
466
467 char c = input.charAt(k);
468
469
470
471 output[offset + (2 * k)] = (byte) c;
472
473 output[offset + (2 * k) + 1] = (byte) (c >> 8);
474
475 }
476
477 }
478
479
480
481 /**
482
483 * Write uncompressed unicode
484
485 *
486
487 *@param input the String containing the unicode data to be written
488
489 *@param output the byte array to hold the uncompressed unicode
490
491 *@param offset the offset to start writing into the byte array
492
493 */
494
495
496
497 public static void putUncompressedUnicodeHigh(final String input,
498
499 final byte[] output,
500
501 final int offset) {
502
503 int strlen = input.length();
504
505
506
507 for (int k = 0; k < strlen; k++) {
508
509 char c = input.charAt(k);
510
511
512
513 output[offset + (2 * k)] = (byte) (c >> 8);
514
515 output[offset + (2 * k)] = (byte) c;
516
517 }
518
519 }
520
521
522
523
524
525
526
527
528
529 /**
530
531 * Description of the Method
532
533 *
534
535 *@param message Description of the Parameter
536
537 *@param params Description of the Parameter
538
539 *@return Description of the Return Value
540
541 */
542
543 public static String format(String message, Object[] params) {
544
545 int currentParamNumber = 0;
546
547 StringBuffer formattedMessage = new StringBuffer();
548
549
550
551 for (int i = 0; i < message.length(); i++) {
552
553 if (message.charAt(i) == '%') {
554
555 if (currentParamNumber >= params.length) {
556
557 formattedMessage.append("?missing data?");
558
559 } else if ((params[currentParamNumber] instanceof Number)
560
561 && (i + 1 < message.length())) {
562
563 i += matchOptionalFormatting(
564
565 (Number) params[currentParamNumber++],
566
567 message.substring(i + 1), formattedMessage);
568
569 } else {
570
571 formattedMessage.append(params[currentParamNumber++].toString());
572
573 }
574
575 } else {
576
577 if ((message.charAt(i) == '\\') && (i + 1 < message.length())
578
579 && (message.charAt(i + 1) == '%')) {
580
581 formattedMessage.append('%');
582
583 i++;
584
585 } else {
586
587 formattedMessage.append(message.charAt(i));
588
589 }
590
591 }
592
593 }
594
595 return formattedMessage.toString();
596
597 }
598
599
600
601
602
603 /**
604
605 * Description of the Method
606
607 *
608
609 *@param number Description of the Parameter
610
611 *@param formatting Description of the Parameter
612
613 *@param outputTo Description of the Parameter
614
615 *@return Description of the Return Value
616
617 */
618
619 private static int matchOptionalFormatting(Number number,
620
621 String formatting,
622
623 StringBuffer outputTo) {
624
625 NumberFormat numberFormat = NumberFormat.getInstance();
626
627
628
629 if ((0 < formatting.length())
630
631 && Character.isDigit(formatting.charAt(0))) {
632
633 numberFormat.setMinimumIntegerDigits(Integer.parseInt(formatting.charAt(0) + ""));
634
635 if ((2 < formatting.length()) && (formatting.charAt(1) == '.')
636
637 && Character.isDigit(formatting.charAt(2))) {
638
639 numberFormat.setMaximumFractionDigits(Integer.parseInt(formatting.charAt(2) + ""));
640
641 numberFormat.format(number, outputTo, new FieldPosition(0));
642
643 return 3;
644
645 }
646
647 numberFormat.format(number, outputTo, new FieldPosition(0));
648
649 return 1;
650
651 } else if ((0 < formatting.length()) && (formatting.charAt(0) == '.')) {
652
653 if ((1 < formatting.length())
654
655 && Character.isDigit(formatting.charAt(1))) {
656
657 numberFormat.setMaximumFractionDigits(Integer.parseInt(formatting.charAt(1) + ""));
658
659 numberFormat.format(number, outputTo, new FieldPosition(0));
660
661 return 2;
662
663 }
664
665 }
666
667 numberFormat.format(number, outputTo, new FieldPosition(0));
668
669 return 1;
670
671 }
672
673
674
675 /**
676
677 * @return the encoding we want to use (ISO-8859-1)
678
679 */
680
681 public static String getPreferredEncoding() {
682
683 return ENCODING;
684
685 }
686
687 }
688
689 ???????????????StringUtil?????????????????????????????????ENCODING??????????????????StringUtil???????????????????????????????getFromUnicodeHigh??????????????offset??????????????????????????????offset????????????????????????????????????????string??????????????len?????????????????????????????string?????????????????????????????????????????????offset????????????????????????????????????????????????????????????len????????????????????????????char??????????????????????????????????len??????????????????????????i??????????????????????????????chars????????????????????????????????????????????i?????????????chars???????????????????i????????????????????????????????string????????????????????????????????????????offset?????????????????????????????????????????????????????i????????????????????????????????string????????????????????????????????????????offset?????????????????????????????????????????????????????i????????????????????????????chars???????????????????????????????getFromUnicodeHigh????????????????getFromUnicodeHigh????????????????????????????????????string???????????????????????????????????????????????string???????????????????????????????getFromUnicode??????????????offset??????????????????????????????offset????????????????????????????????????????string??????????????len?????????????????????????????string?????????????????????????????????????????????offset????????????????????????????????????????????????????????????len????????????????????????????char??????????????????????????????????len??????????????????????????i??????????????????????????????chars????????????????????????????????????????????i?????????????chars???????????????????i??????????????????????????????????string??????????????????????????????????????????offset???????????????????????????????????????????????????????i???????????????????????????????string???????????????????????????????????????offset????????????????????????????????????????????????????i????????????????????????????chars???????????????????????????????getFromUnicode????????????????getFromUnicode???????????????????????????????string??????????????????????????????????????????string?????????????????????????????putCompressedUnicode??????????????????????input?????????????????????????k?????????????????????????????strlen?????????????????????????????????????k?????????????output????????????????????offset?????????????????????????????k?????????????????????????????????????????input??????????????????????????????????????????????????????k?????????????????????????????putUncompressedUnicode??????????????????????input?????????????????????????k?????????????????????????????strlen?????????????????????????????????????k??????????????????????input???????????????????????????????????k?????????????output????????????????????offset??????????????????????????????????k???????????????????????????????????????????????c?????????????output????????????????????offset??????????????????????????????????k????????????????????????????????????????????????????c?????????????????????????????putUncompressedUnicodeHigh??????????????????????input?????????????????????????k?????????????????????????????strlen?????????????????????????????????????k??????????????????????input???????????????????????????????????k?????????????output????????????????????offset??????????????????????????????????k????????????????????????????????????????????????c?????????????output????????????????????offset??????????????????????????????????k???????????????????????????????????????????????c???????????????????????????????format?????????????????????????i?????????????????????????????message???????????????????????????????????????????????i?????????????????message????????????????????????????????i?????????????????????currentParamNumber???????????????????????????????????????????params?????????????????????formattedMessage?????????????????????????????params????????????????????????????????????currentParamNumber?????????????????????????????i?????????????????????????????????????message?????????????????????i??????????????????????????matchOptionalFormatting??????????????????????????????????????params?????????????????????????????????????????????currentParamNumber?????????????????????????????message???????????????????????????????????????????????i???????????????????????????????????????????????????????formattedMessage?????????????????????formattedMessage?????????????????????????????????????????????params????????????????????????????????????????????????????currentParamNumber??????????????????????message?????????????????????????????????????i?????????????????????????????????????????????????????i?????????????????????????????????????????????????????????????message?????????????????????????????message????????????????????????????????????????????i?????????????????????formattedMessage?????????????????????i?????????????????????formattedMessage?????????????????????????????????????????????message????????????????????????????????????????????????????????????i????????????????formattedMessage?????????????????????????????matchOptionalFormatting??????????????????formatting??????????????????????????????????????formatting?????????????numberFormat???????????????????????????????????????????????????????????????????formatting??????????????????????formatting???????????????????????????????????????????????formatting??????????????????????????????????????????formatting?????????????????numberFormat????????????????????????????????????????????????????????????????????????formatting?????????????????numberFormat?????????????????????????????????????number?????????????????????????????????????????????outputTo?????????????numberFormat?????????????????????????????????number?????????????????????????????????????????outputTo?????????????????????????formatting??????????????????????????????????????????????????formatting??????????????????????formatting??????????????????????????????????????????formatting?????????????????numberFormat????????????????????????????????????????????????????????????????????????formatting?????????????????numberFormat?????????????????????????????????????number?????????????????????????????????????????????outputTo?????????numberFormat?????????????????????????????number?????????????????????????????????????outputTo???????????????????????????????getPreferredEncoding????????????????ENCODING