1 package be
.nikiroo
.utils
;
3 import java
.io
.ByteArrayInputStream
;
4 import java
.io
.ByteArrayOutputStream
;
5 import java
.io
.IOException
;
6 import java
.io
.InputStream
;
7 import java
.io
.OutputStream
;
8 import java
.io
.UnsupportedEncodingException
;
9 import java
.security
.MessageDigest
;
10 import java
.security
.NoSuchAlgorithmException
;
11 import java
.text
.Normalizer
;
12 import java
.text
.Normalizer
.Form
;
13 import java
.text
.ParseException
;
14 import java
.text
.SimpleDateFormat
;
15 import java
.util
.AbstractMap
;
16 import java
.util
.ArrayList
;
17 import java
.util
.Arrays
;
18 import java
.util
.Date
;
19 import java
.util
.List
;
20 import java
.util
.Map
.Entry
;
21 import java
.util
.regex
.Pattern
;
22 import java
.util
.zip
.GZIPInputStream
;
23 import java
.util
.zip
.GZIPOutputStream
;
25 import org
.unbescape
.html
.HtmlEscape
;
26 import org
.unbescape
.html
.HtmlEscapeLevel
;
27 import org
.unbescape
.html
.HtmlEscapeType
;
29 import be
.nikiroo
.utils
.streams
.Base64InputStream
;
30 import be
.nikiroo
.utils
.streams
.Base64OutputStream
;
33 * This class offer some utilities based around {@link String}s.
37 public class StringUtils
{
39 * This enum type will decide the alignment of a {@link String} when padding
40 * or justification is applied (if there is enough horizontal space for it
43 public enum Alignment
{
44 /** Aligned at left. */
48 /** Aligned at right. */
50 /** Full justified (to both left and right). */
53 // Old Deprecated values:
55 /** DEPRECATED: please use LEFT. */
58 /** DEPRECATED: please use CENTER. */
61 /** DEPRECATED: please use RIGHT. */
66 * Return the non-deprecated version of this enum if needed (or return
69 * @return the non-deprecated value
71 Alignment
undeprecate() {
72 if (this == Beginning
)
82 static private Pattern marks
= getMarks();
85 * Fix the size of the given {@link String} either with space-padding or by
89 * the {@link String} to fix
91 * the size of the resulting {@link String} or -1 for a noop
93 * @return the resulting {@link String} of size <i>size</i>
95 static public String
padString(String text
, int width
) {
96 return padString(text
, width
, true, null);
100 * Fix the size of the given {@link String} either with space-padding or by
101 * optionally shortening it.
104 * the {@link String} to fix
106 * the size of the resulting {@link String} if the text fits or
107 * if cut is TRUE or -1 for a noop
109 * cut the {@link String} shorter if needed
111 * align the {@link String} in this position if we have enough
112 * space (default is Alignment.Beginning)
114 * @return the resulting {@link String} of size <i>size</i> minimum
116 static public String
padString(String text
, int width
, boolean cut
,
120 align
= Alignment
.LEFT
;
123 align
= align
.undeprecate();
129 int diff
= width
- text
.length();
133 text
= text
.substring(0, width
);
134 } else if (diff
> 0) {
135 if (diff
< 2 && align
!= Alignment
.RIGHT
)
136 align
= Alignment
.LEFT
;
140 text
= new String(new char[diff
]).replace('\0', ' ') + text
;
143 int pad1
= (diff
) / 2;
144 int pad2
= (diff
+ 1) / 2;
145 text
= new String(new char[pad1
]).replace('\0', ' ') + text
146 + new String(new char[pad2
]).replace('\0', ' ');
150 text
= text
+ new String(new char[diff
]).replace('\0', ' ');
160 * Justify a text into width-sized (at the maximum) lines and return all the
161 * lines concatenated into a single '\\n'-separated line of text.
164 * the {@link String} to justify
166 * the maximum size of the resulting lines
168 * @return a list of justified text lines concatenated into a single
169 * '\\n'-separated line of text
171 static public String
justifyTexts(String text
, int width
) {
172 StringBuilder builder
= new StringBuilder();
173 for (String line
: justifyText(text
, width
, null)) {
174 if (builder
.length() > 0) {
175 builder
.append('\n');
177 builder
.append(line
);
180 return builder
.toString();
184 * Justify a text into width-sized (at the maximum) lines.
187 * the {@link String} to justify
189 * the maximum size of the resulting lines
191 * @return a list of justified text lines
193 static public List
<String
> justifyText(String text
, int width
) {
194 return justifyText(text
, width
, null);
198 * Justify a text into width-sized (at the maximum) lines.
201 * the {@link String} to justify
203 * the maximum size of the resulting lines
205 * align the lines in this position (default is
206 * Alignment.Beginning)
208 * @return a list of justified text lines
210 static public List
<String
> justifyText(String text
, int width
,
213 align
= Alignment
.LEFT
;
216 align
= align
.undeprecate();
220 return StringJustifier
.center(text
, width
);
222 return StringJustifier
.right(text
, width
);
224 return StringJustifier
.full(text
, width
);
227 return StringJustifier
.left(text
, width
);
232 * Justify a text into width-sized (at the maximum) lines.
235 * the {@link String} to justify
237 * the maximum size of the resulting lines
239 * @return a list of justified text lines
241 static public List
<String
> justifyText(List
<String
> text
, int width
) {
242 return justifyText(text
, width
, null);
246 * Justify a text into width-sized (at the maximum) lines.
249 * the {@link String} to justify
251 * the maximum size of the resulting lines
253 * align the lines in this position (default is
254 * Alignment.Beginning)
256 * @return a list of justified text lines
258 static public List
<String
> justifyText(List
<String
> text
, int width
,
260 List
<String
> result
= new ArrayList
<String
>();
262 // Content <-> Bullet spacing (null = no spacing)
263 List
<Entry
<String
, String
>> lines
= new ArrayList
<Entry
<String
, String
>>();
264 StringBuilder previous
= null;
265 StringBuilder tmp
= new StringBuilder();
266 String previousItemBulletSpacing
= null;
267 String itemBulletSpacing
= null;
268 for (String inputLine
: text
) {
269 boolean previousLineComplete
= true;
271 String current
= inputLine
.replace("\t", " ");
272 itemBulletSpacing
= getItemSpacing(current
);
273 boolean bullet
= isItemLine(current
);
274 if ((previousItemBulletSpacing
== null || itemBulletSpacing
275 .length() <= previousItemBulletSpacing
.length()) && !bullet
) {
276 itemBulletSpacing
= null;
279 if (itemBulletSpacing
!= null) {
280 current
= current
.trim();
281 if (!current
.isEmpty() && bullet
) {
282 current
= current
.substring(1);
284 current
= current
.trim();
285 previousLineComplete
= bullet
;
288 for (String word
: current
.split(" ")) {
289 if (word
.isEmpty()) {
293 if (tmp
.length() > 0) {
296 tmp
.append(word
.trim());
298 current
= tmp
.toString();
300 previousLineComplete
= current
.isEmpty()
301 || previousItemBulletSpacing
!= null
302 || (previous
!= null && isFullLine(previous
))
303 || isHrLine(current
) || isHrLine(previous
);
306 if (previous
== null) {
307 previous
= new StringBuilder();
309 if (previousLineComplete
) {
310 lines
.add(new AbstractMap
.SimpleEntry
<String
, String
>(
311 previous
.toString(), previousItemBulletSpacing
));
312 previous
.setLength(0);
313 previousItemBulletSpacing
= itemBulletSpacing
;
315 previous
.append(' ');
319 previous
.append(current
);
323 if (previous
!= null) {
324 lines
.add(new AbstractMap
.SimpleEntry
<String
, String
>(previous
325 .toString(), previousItemBulletSpacing
));
328 for (Entry
<String
, String
> line
: lines
) {
329 String content
= line
.getKey();
330 String spacing
= line
.getValue();
332 String bullet
= "- ";
333 if (spacing
== null) {
338 if (spacing
.length() > width
+ 3) {
342 for (String subline
: StringUtils
.justifyText(content
, width
343 - (spacing
.length() + bullet
.length()), align
)) {
344 result
.add(spacing
+ bullet
+ subline
);
345 if (!bullet
.isEmpty()) {
355 * Sanitise the given input to make it more Terminal-friendly by removing
356 * combining characters.
359 * the input to sanitise
360 * @param allowUnicode
361 * allow Unicode or only allow ASCII Latin characters
363 * @return the sanitised {@link String}
365 static public String
sanitize(String input
, boolean allowUnicode
) {
366 return sanitize(input
, allowUnicode
, !allowUnicode
);
370 * Sanitise the given input to make it more Terminal-friendly by removing
371 * combining characters.
374 * the input to sanitise
375 * @param allowUnicode
376 * allow Unicode or only allow ASCII Latin characters
377 * @param removeAllAccents
378 * TRUE to replace all accentuated characters by their non
379 * accentuated counter-parts
381 * @return the sanitised {@link String}
383 static public String
sanitize(String input
, boolean allowUnicode
,
384 boolean removeAllAccents
) {
386 if (removeAllAccents
) {
387 input
= Normalizer
.normalize(input
, Form
.NFKD
);
389 input
= marks
.matcher(input
).replaceAll("");
393 input
= Normalizer
.normalize(input
, Form
.NFKC
);
396 StringBuilder builder
= new StringBuilder();
397 for (int index
= 0; index
< input
.length(); index
++) {
398 char car
= input
.charAt(index
);
399 // displayable chars in ASCII are in the range 32<->255,
401 if (car
>= 32 && car
<= 255 && car
!= 127) {
405 input
= builder
.toString();
412 * Convert between the time in milliseconds to a {@link String} in a "fixed"
413 * way (to exchange data over the wire, for instance).
415 * Precise to the second.
418 * the specified number of milliseconds since the standard base
419 * time known as "the epoch", namely January 1, 1970, 00:00:00
422 * @return the time as a {@link String}
424 static public String
fromTime(long time
) {
425 SimpleDateFormat sdf
= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
426 return sdf
.format(new Date(time
));
430 * Convert between the time as a {@link String} to milliseconds in a "fixed"
431 * way (to exchange data over the wire, for instance).
433 * Precise to the second.
436 * the time as a {@link String}
438 * @return the number of milliseconds since the standard base time known as
439 * "the epoch", namely January 1, 1970, 00:00:00 GMT, or -1 in case
442 * @throws ParseException
443 * in case of parse error
445 static public long toTime(String displayTime
) throws ParseException
{
446 SimpleDateFormat sdf
= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
447 return sdf
.parse(displayTime
).getTime();
451 * Return a hash of the given {@link String}.
458 * @deprecated please use {@link HashUtils}
461 static public String
getMd5Hash(String input
) {
463 MessageDigest md
= MessageDigest
.getInstance("MD5");
464 md
.update(getBytes(input
));
465 byte byteData
[] = md
.digest();
467 StringBuffer hexString
= new StringBuffer();
468 for (int i
= 0; i
< byteData
.length
; i
++) {
469 String hex
= Integer
.toHexString(0xff & byteData
[i
]);
470 if (hex
.length() == 1)
471 hexString
.append('0');
472 hexString
.append(hex
);
475 return hexString
.toString();
476 } catch (NoSuchAlgorithmException e
) {
482 * Remove the HTML content from the given input, and un-html-ize the rest.
485 * the HTML-encoded content
487 * @return the HTML-free equivalent content
489 public static String
unhtml(String html
) {
490 StringBuilder builder
= new StringBuilder();
493 for (char car
: html
.toCharArray()) {
496 } else if (car
== '>') {
498 } else if (inTag
<= 0) {
503 char nbsp
= ' '; // non-breakable space (a special char)
505 return HtmlEscape
.unescapeHtml(builder
.toString()).replace(nbsp
, space
);
509 * Escape the given {@link String} so it can be used in XML, as content.
512 * the input {@link String}
514 * @return the escaped {@link String}
516 public static String
xmlEscape(String input
) {
521 return HtmlEscape
.escapeHtml(input
,
522 HtmlEscapeType
.HTML4_NAMED_REFERENCES_DEFAULT_TO_HEXA
,
523 HtmlEscapeLevel
.LEVEL_1_ONLY_MARKUP_SIGNIFICANT
);
527 * Escape the given {@link String} so it can be used in XML, as text content
528 * inside double-quotes.
531 * the input {@link String}
533 * @return the escaped {@link String}
535 public static String
xmlEscapeQuote(String input
) {
540 return HtmlEscape
.escapeHtml(input
,
541 HtmlEscapeType
.HTML4_NAMED_REFERENCES_DEFAULT_TO_HEXA
,
542 HtmlEscapeLevel
.LEVEL_1_ONLY_MARKUP_SIGNIFICANT
);
546 * Zip the data and then encode it into Base64.
551 * @return the Base64 zipped version
553 * @throws IOException
554 * in case of I/O error
556 public static String
zip64(String data
) throws IOException
{
558 return zip64(getBytes(data
));
559 } catch (UnsupportedEncodingException e
) {
560 // All conforming JVM are required to support UTF-8
567 * Zip the data and then encode it into Base64.
572 * @return the Base64 zipped version
574 * @throws IOException
575 * in case of I/O error
577 public static String
zip64(byte[] data
) throws IOException
{
579 ByteArrayOutputStream bout
= new ByteArrayOutputStream();
581 OutputStream out
= new GZIPOutputStream(bout
);
588 data
= bout
.toByteArray();
593 InputStream in
= new ByteArrayInputStream(data
);
595 in
= new Base64InputStream(in
, true);
596 return new String(IOUtils
.toByteArray(in
), "UTF-8");
603 * Unconvert from Base64 then unzip the content, which is assumed to be a
607 * the data in Base64 format
609 * @return the raw data
611 * @throws IOException
612 * in case of I/O error
614 public static String
unzip64s(String data
) throws IOException
{
615 return new String(unzip64(data
), "UTF-8");
619 * Unconvert from Base64 then unzip the content.
622 * the data in Base64 format
624 * @return the raw data
626 * @throws IOException
627 * in case of I/O error
629 public static byte[] unzip64(String data
) throws IOException
{
630 InputStream in
= new Base64InputStream(new ByteArrayInputStream(
631 getBytes(data
)), false);
633 in
= new GZIPInputStream(in
);
634 return IOUtils
.toByteArray(in
);
641 * Convert the given data to Base64 format.
644 * the data to convert
646 * @return the Base64 {@link String} representation of the data
648 * @throws IOException
649 * in case of I/O errors
651 public static String
base64(String data
) throws IOException
{
652 return base64(getBytes(data
));
656 * Convert the given data to Base64 format.
659 * the data to convert
661 * @return the Base64 {@link String} representation of the data
663 * @throws IOException
664 * in case of I/O errors
666 public static String
base64(byte[] data
) throws IOException
{
667 Base64InputStream in
= new Base64InputStream(new ByteArrayInputStream(
670 return new String(IOUtils
.toByteArray(in
), "UTF-8");
677 * Unconvert the given data from Base64 format back to a raw array of bytes.
680 * the data to unconvert
682 * @return the raw data represented by the given Base64 {@link String},
684 * @throws IOException
685 * in case of I/O errors
687 public static byte[] unbase64(String data
) throws IOException
{
688 Base64InputStream in
= new Base64InputStream(new ByteArrayInputStream(
689 getBytes(data
)), false);
691 return IOUtils
.toByteArray(in
);
698 * Unonvert the given data from Base64 format back to a {@link String}.
701 * the data to unconvert
703 * @return the {@link String} represented by the given Base64 {@link String}
705 * @throws IOException
706 * in case of I/O errors
708 public static String
unbase64s(String data
) throws IOException
{
709 return new String(unbase64(data
), "UTF-8");
713 * Return a display {@link String} for the given value, which can be
714 * suffixed with "k" or "M" depending upon the number, if it is big enough.
719 * <li><tt>8 765</tt> becomes "8 k"</li>
720 * <li><tt>998 765</tt> becomes "998 k"</li>
721 * <li><tt>12 987 364</tt> becomes "12 M"</li>
722 * <li><tt>5 534 333 221</tt> becomes "5 G"</li>
726 * the value to convert
728 * @return the display value
730 public static String
formatNumber(long value
) {
731 return formatNumber(value
, 0);
735 * Return a display {@link String} for the given value, which can be
736 * suffixed with "k" or "M" depending upon the number, if it is big enough.
738 * Examples (assuming decimalPositions = 1):
740 * <li><tt>8 765</tt> becomes "8.7 k"</li>
741 * <li><tt>998 765</tt> becomes "998.7 k"</li>
742 * <li><tt>12 987 364</tt> becomes "12.9 M"</li>
743 * <li><tt>5 534 333 221</tt> becomes "5.5 G"</li>
747 * the value to convert
748 * @param decimalPositions
749 * the number of decimal positions to keep
751 * @return the display value
753 public static String
formatNumber(long value
, int decimalPositions
) {
754 long userValue
= value
;
758 if (value
>= 1000000000l) {
760 userValue
= value
/ 1000000000l;
762 } else if (value
>= 1000000l) {
764 userValue
= value
/ 1000000l;
766 } else if (value
>= 1000l) {
768 userValue
= value
/ 1000l;
773 if (decimalPositions
> 0) {
774 deci
= Long
.toString(value
% mult
);
775 int size
= Long
.toString(mult
).length() - 1;
776 while (deci
.length() < size
) {
780 deci
= deci
.substring(0, Math
.min(decimalPositions
, deci
.length()));
781 while (deci
.length() < decimalPositions
) {
788 return Long
.toString(userValue
) + deci
+ suffix
;
792 * The reverse operation to {@link StringUtils#formatNumber(long)}: it will
793 * read a "display" number that can contain a "M" or "k" suffix and return
796 * Of course, the conversion to and from display form is lossy (example:
797 * <tt>6870</tt> to "6.5k" to <tt>6500</tt>).
800 * the value in display form with possible "M" and "k" suffixes,
803 * @return the value as a number, or 0 if not possible to convert
805 public static long toNumber(String value
) {
806 return toNumber(value
, 0l);
810 * The reverse operation to {@link StringUtils#formatNumber(long)}: it will
811 * read a "display" number that can contain a "M" or "k" suffix and return
814 * Of course, the conversion to and from display form is lossy (example:
815 * <tt>6870</tt> to "6.5k" to <tt>6500</tt>).
818 * the value in display form with possible "M" and "k" suffixes,
821 * the default value if it is not possible to convert the given
824 * @return the value as a number, or 0 if not possible to convert
826 public static long toNumber(String value
, long def
) {
829 value
= value
.trim().toLowerCase();
832 if (value
.endsWith("g")) {
833 value
= value
.substring(0, value
.length() - 1).trim();
835 } else if (value
.endsWith("m")) {
836 value
= value
.substring(0, value
.length() - 1).trim();
838 } else if (value
.endsWith("k")) {
839 value
= value
.substring(0, value
.length() - 1).trim();
844 if (value
.contains(".")) {
845 String
[] tab
= value
.split("\\.");
846 if (tab
.length
!= 2) {
847 throw new NumberFormatException(value
);
849 double decimal
= Double
.parseDouble("0."
850 + tab
[tab
.length
- 1]);
851 deci
= ((long) (mult
* decimal
));
854 count
= mult
* Long
.parseLong(value
) + deci
;
855 } catch (Exception e
) {
863 * Return the bytes array representation of the given {@link String} in
867 * the {@link String} to transform into bytes
868 * @return the content in bytes
870 static public byte[] getBytes(String str
) {
872 return str
.getBytes("UTF-8");
873 } catch (UnsupportedEncodingException e
) {
874 // All conforming JVM must support UTF-8
881 * The "remove accents" pattern.
883 * @return the pattern, or NULL if a problem happens
885 private static Pattern
getMarks() {
888 .compile("[\\p{InCombiningDiacriticalMarks}\\p{IsLm}\\p{IsSk}]+");
889 } catch (Exception e
) {
890 // Can fail on Android...
896 // justify List<String> related:
900 * Check if this line ends as a complete line (ends with a "." or similar).
902 * Note that we consider an empty line as full, and a line ending with
903 * spaces as not complete.
908 * @return TRUE if it does
910 static private boolean isFullLine(StringBuilder line
) {
911 if (line
.length() == 0) {
915 char lastCar
= line
.charAt(line
.length() - 1);
925 case '"': // double quotes
937 * Check if this line represent an item in a list or description (i.e.,
938 * check that the first non-space char is "-").
943 * @return TRUE if it is
945 static private boolean isItemLine(String line
) {
946 String spacing
= getItemSpacing(line
);
947 return spacing
!= null && !spacing
.isEmpty()
948 && line
.charAt(spacing
.length()) == '-';
952 * Return all the spaces that start this line (or Empty if none).
955 * the line to get the starting spaces from
957 * @return the left spacing
959 static private String
getItemSpacing(String line
) {
961 for (i
= 0; i
< line
.length(); i
++) {
962 if (line
.charAt(i
) != ' ') {
963 return line
.substring(0, i
);
971 * This line is an horizontal spacer line.
976 * @return TRUE if it is
978 static private boolean isHrLine(CharSequence line
) {
981 for (int i
= 0; i
< line
.length(); i
++) {
982 char car
= line
.charAt(i
);
983 if (car
== ' ' || car
== '\t' || car
== '*' || car
== '-'
984 || car
== '_' || car
== '~' || car
== '=' || car
== '/'
996 // Deprecated functions, please do not use //
999 * @deprecated please use {@link StringUtils#zip64(byte[])} or
1000 * {@link StringUtils#base64(byte[])} instead.
1003 * the data to encode
1005 * TRUE to zip it before Base64 encoding it, FALSE for Base64
1008 * @return the encoded data
1010 * @throws IOException
1011 * in case of I/O error
1014 public static String
base64(String data
, boolean zip
) throws IOException
{
1015 return base64(getBytes(data
), zip
);
1019 * @deprecated please use {@link StringUtils#zip64(String)} or
1020 * {@link StringUtils#base64(String)} instead.
1023 * the data to encode
1025 * TRUE to zip it before Base64 encoding it, FALSE for Base64
1028 * @return the encoded data
1030 * @throws IOException
1031 * in case of I/O error
1034 public static String
base64(byte[] data
, boolean zip
) throws IOException
{
1039 Base64InputStream b64
= new Base64InputStream(new ByteArrayInputStream(
1042 return IOUtils
.readSmallStream(b64
);
1049 * @deprecated please use {@link Base64OutputStream} and
1050 * {@link GZIPOutputStream} instead.
1053 * NOT USED ANYMORE, it is always considered FALSE now
1056 public static OutputStream
base64(OutputStream data
, boolean zip
,
1057 boolean breakLines
) throws IOException
{
1058 OutputStream out
= new Base64OutputStream(data
);
1060 out
= new java
.util
.zip
.GZIPOutputStream(out
);
1067 * Unconvert the given data from Base64 format back to a raw array of bytes.
1069 * Will automatically detect zipped data and also uncompress it before
1070 * returning, unless ZIP is false.
1072 * @deprecated DO NOT USE ANYMORE (bad perf, will be dropped)
1075 * the data to unconvert
1077 * TRUE to also uncompress the data from a GZIP format
1078 * automatically; if set to FALSE, zipped data can be returned
1080 * @return the raw data represented by the given Base64 {@link String},
1081 * optionally compressed with GZIP
1083 * @throws IOException
1084 * in case of I/O errors
1087 public static byte[] unbase64(String data
, boolean zip
) throws IOException
{
1088 byte[] buffer
= unbase64(data
);
1094 GZIPInputStream zipped
= new GZIPInputStream(
1095 new ByteArrayInputStream(buffer
));
1097 ByteArrayOutputStream out
= new ByteArrayOutputStream();
1099 IOUtils
.write(zipped
, out
);
1100 return out
.toByteArray();
1107 } catch (Exception e
) {
1113 * Unconvert the given data from Base64 format back to a raw array of bytes.
1115 * Will automatically detect zipped data and also uncompress it before
1116 * returning, unless ZIP is false.
1118 * @deprecated DO NOT USE ANYMORE (bad perf, will be dropped)
1121 * the data to unconvert
1123 * TRUE to also uncompress the data from a GZIP format
1124 * automatically; if set to FALSE, zipped data can be returned
1126 * @return the raw data represented by the given Base64 {@link String},
1127 * optionally compressed with GZIP
1129 * @throws IOException
1130 * in case of I/O errors
1133 public static InputStream
unbase64(InputStream data
, boolean zip
)
1134 throws IOException
{
1135 return new ByteArrayInputStream(unbase64(IOUtils
.readSmallStream(data
),
1140 * @deprecated DO NOT USE ANYMORE (bad perf, will be dropped)
1143 public static byte[] unbase64(byte[] data
, int offset
, int count
,
1144 boolean zip
) throws IOException
{
1145 byte[] dataPart
= Arrays
.copyOfRange(data
, offset
, offset
+ count
);
1146 return unbase64(new String(dataPart
, "UTF-8"), zip
);
1150 * @deprecated DO NOT USE ANYMORE (bad perf, will be dropped)
1153 public static String
unbase64s(String data
, boolean zip
) throws IOException
{
1154 return new String(unbase64(data
, zip
), "UTF-8");
1158 * @deprecated DO NOT USE ANYMORE (bad perf, will be dropped)
1161 public static String
unbase64s(byte[] data
, int offset
, int count
,
1162 boolean zip
) throws IOException
{
1163 return new String(unbase64(data
, offset
, count
, zip
), "UTF-8");