001/* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016package org.opengion.fukurou.util; 017 018import java.awt.Color; 019import java.io.PrintWriter; 020import java.io.StringWriter; 021import java.io.UnsupportedEncodingException; 022import java.net.URLEncoder; 023import java.net.URLDecoder; 024import java.util.ArrayList; 025import java.util.Arrays; 026import java.util.Enumeration; 027import java.util.HashMap; 028import java.util.Iterator; 029import java.util.Map; 030import java.util.StringTokenizer; 031import java.util.Locale ; // 5.7.2.3 (2014/01/31) 032import java.nio.charset.Charset; // 5.5.2.6 (2012/05/25) 033 034 035/** 036 * StringUtil.java は、共通的に使用される String関連メソッドを集約した、クラスです。 037 * 038 * @og.group ユーティリティ 039 * 040 * @version 4.0 041 * @author Kazuhiko Hasegawa 042 * @since JDK5.0, 043 */ 044public final class StringUtil { 045 046 /** バッファの初期容量を通常より多い目に設定します。(200) */ 047 private static final int BUFFER_MIDDLE = 200; 048 049 /** システム依存の改行記号をセットします。 */ 050 private static final String CR = System.getProperty("line.separator"); 051 052 /** 053 * プラットフォーム依存のデフォルトの Charset です。 054 * プラットフォーム依存性を考慮する場合、エンコード指定で作成しておく事をお勧めします。 055 * 056 * @og.rev 5.5.2.6 (2012/05/25) findbugs対応 057 */ 058 public static final Charset DEFAULT_CHARSET = Charset.defaultCharset() ; 059 060 /** 061 * code39 のチェックデジット計算に使用する モジュラス43 の変換表です。 062 * 063 */ 064 private static final String MODULUS_43 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" ; 065 066 /** 067 * getUnicodeEscape で使用する桁合わせ用文字列配列です。 068 * Unicodeの HexString 変換後の桁に応じて、埋め合わせします。 069 * 070 */ 071 private static final String[] UTF_STR = { "�", "�", "�", "�", "&#x" }; 072 073 // 4.0.3.0 (2007/12/26) 色コードにPURPLE を追加 074 // 5.7.8.0 (2014/07/04) 透明追加 075 private static final Map<String,Color> CLR_MAP; 076 static { 077 CLR_MAP = new HashMap<String,Color>(); 078 CLR_MAP.put( "BLACK" ,Color.BLACK ); 079 CLR_MAP.put( "BLUE" ,Color.BLUE ); 080 CLR_MAP.put( "CYAN" ,Color.CYAN ); 081 CLR_MAP.put( "DARK_GRAY" ,Color.DARK_GRAY ); 082 CLR_MAP.put( "GRAY" ,Color.GRAY ); 083 CLR_MAP.put( "GREEN" ,Color.GREEN ); 084 CLR_MAP.put( "LIGHT_GRAY" ,Color.LIGHT_GRAY ); 085 CLR_MAP.put( "MAGENTA" ,Color.MAGENTA ); 086 CLR_MAP.put( "ORANGE" ,Color.ORANGE ); 087 CLR_MAP.put( "PINK" ,Color.PINK ); 088 CLR_MAP.put( "RED" ,Color.RED ); 089 CLR_MAP.put( "WHITE" ,Color.WHITE ); 090 CLR_MAP.put( "YELLOW" ,Color.YELLOW ); 091 CLR_MAP.put( "PURPLE" ,new Color( 8388736 ) ); // #800080 092 CLR_MAP.put( "TRANSPARENT" ,new Color( 255,255,255,0 ) ); // 5.7.8.0 (2014/07/04) 透明追加 093 } 094 095 // 5.10.0.1 (2018/06/15) 096 private static final String[][] ESC_ARY = new String[][] { 097 { "<", "<" } 098 ,{ "<", "<" } 099 ,{ ">", ">" } 100 ,{ ">", ">" } }; 101 102 /** 103 * デフォルトコンストラクターをprivateにして、 104 * オブジェクトの生成をさせないようにする。 105 * 106 */ 107 private StringUtil() {} 108 109 /** 110 * UTF-8 で、URLエンコードを行います。 111 * このメソッドは、JDK1.4 以上でないと使用できません。 112 * 113 * @param value エンコードする文字列 114 * 115 * @return 指定の文字コードでURLエンコードされた文字列 116 */ 117 public static String urlEncode( final String value ) { 118 if( value == null ) { return ""; } 119 120 try { 121 return URLEncoder.encode( value,"UTF-8" ); 122 } 123 catch( UnsupportedEncodingException ex ) { 124 String errMsg = "UnsupportedEncodingException [UTF-8]" + CR 125 + ex.getMessage() ; 126 throw new RuntimeException( errMsg,ex ); 127 } 128 catch( RuntimeException ex2 ) { // 3.6.0.0 (2004/09/17) 129 String errMsg = "予期せぬエラー value=[" + value + "] , encode=[UTF-8]" + CR 130 + ex2.getMessage(); 131 throw new RuntimeException( errMsg,ex2 ); 132 } 133 } 134 135 /** 136 * UTF-8 でURLエンコードされた文字列をデコードします。 137 * このメソッドは、JDK1.4 以上でないと使用できません。 138 * 139 * @og.rev 5.4.5.0 追加 140 * @param value デコードする文字列 141 * 142 * @return デコードされた文字列 143 */ 144 public static String urlDecode( final String value ) { 145 try { 146 return URLDecoder.decode( value,"UTF-8" ); 147 } 148 catch( UnsupportedEncodingException ex ) { 149 String errMsg = "UnsupportedEncodingException [UTF-8]" + CR 150 + ex.getMessage() ; 151 throw new RuntimeException( errMsg,ex ); 152 } 153 catch( RuntimeException ex2 ) { // 3.6.0.0 (2004/09/17) 154 String errMsg = "予期せぬエラー value=[" + value + "] , encode=[UTF-8]" + CR 155 + ex2.getMessage(); 156 throw new RuntimeException( errMsg,ex2 ); 157 } 158 } 159 160 /** 161 * 文字列の後ろのスペースを削除します。 162 * String クラスの trim()メソッドは、文字列の両方のスペースを削除しますが、 163 * この rTrim( String ) は、後ろの半角スペースのみ、詰めます。 164 * 注意:'\u0020' (スペース文字) より小さい文字を切り取ります。 165 * 166 * @param str 元の文字列 167 * 168 * @return 後ろの半角スペースを詰めた、新しい文字列 169 */ 170 public static String rTrim( final String str ) { 171 if( str == null ) { return null; } 172 int count = str.length(); 173 174 int len = count; 175 176 while ( 0 < len && str.charAt(len-1) <= ' ' ) { 177 len--; 178 } 179 return (len < count) ? str.substring(0, len) : str; 180 } 181 182 /** 183 * 文字列の後ろから、" .0" の文字を削除した数字型文字列を返します。 184 * 数字型文字列は、入力文字列の後ろの スペース、小数点、ゼロを削除します。 185 * また、先頭が、"." で始まる場合は、"0" を追加します。 186 * 例: "123.00" ⇒ "123" , ".123" ⇒ "0.123" 187 * 188 * @og.rev 3.8.8.1 (2007/01/10) 新規作成 189 * 190 * @param str 元の文字列 191 * 192 * @return 数字文字列化された、新しい文字列 193 */ 194 public static String toNumber( final String str ) { 195 if( str == null ) { return null; } 196 197 String rtn = str.trim() ; 198 199 int adrs = rtn.indexOf( '.' ); 200 int count = rtn.length(); 201 int len = count; 202 203 if( adrs >= 0 ) { 204 while ( adrs < len && ".0".indexOf( rtn.charAt(len-1) ) >= 0 ) { 205 len--; 206 } 207 } 208 209 if( len < count ) { rtn = rtn.substring(0, len); } 210 if( adrs == 0 ) { rtn = "0" + rtn; } 211 212 return rtn ; 213 } 214 215 /** 216 * 文字列の前方のゼロ(0)を削除します。 217 * 先頭の0を削除するまえに、trim して、スペースを削除しておきます。 218 * 219 * @og.rev 3.5.4.5 (2004/01/23) 新規追加 220 * 221 * @param in 元の文字列 222 * 223 * @return 前方のゼロ(0)を削除した、新しい文字列 224 */ 225 public static String lTrim0( final String in ) { 226 if( in == null ) { return null; } 227 String str = in.trim(); 228 int count = str.length(); 229 230 int len = 0; 231 232 while ( count > len && str.charAt(len) == '0' ) { 233 len++; 234 } 235 236 if( len == 0 ) { return str; } // 先頭がゼロでない。 237 else if( len == count ) { return "0"; } // すべてがゼロ 238 else if( str.charAt(len) == '.' ) { return "0" + str.substring(len); } 239 else { return str.substring(len); } 240 } 241 242 /** 243 * 文字列配列の各要素の後ろのスペースを削除します。 244 * 個々の配列要素に対して、rTrim( String str ) を適用します。 245 * 元の文字列配列に直接作用するのではなく、新しい文字列配列に 246 * 結果をコピーして返します。 247 * ただし、元の文字列配列が、null か、length == 0 の場合は、 248 * 元の文字列配列(アドレス)を返します。 249 * 注意:'\u0020' (スペース文字) より小さい文字を切り取ります。 250 * 251 * @param str 元の文字列 252 * 253 * @return 後ろの半角スペースを詰めた、新しい文字列 254 */ 255 public static String[] rTrims( final String[] str ) { 256 if( str == null || str.length == 0 ) { return str; } 257 258 String[] rtn = new String[ str.length ]; 259 for( int i=0; i<str.length; i++ ) { 260 rtn[i] = rTrim( str[i] ); 261 } 262 return rtn ; 263 } 264 265 /** 266 * 文字列の前後のダブルクオートを取り外します。 267 * 前後にダブルクオートが入っていなければ、そのままの文字列を返します。 268 * 前後に入っていない(片方のみなど)場合も、そのままの文字列を返します。 269 * 270 * @param str 元の文字列 271 * 272 * @return ダブルクオートを取り外した新しい文字列 273 */ 274 public static String csvOutQuote( final String str ) { 275 if( str == null ) { return null; } 276 int end = str.length(); 277 278 if( end < 2 || str.charAt(0) != '"' || str.charAt( end-1 ) != '"' ) { 279 return str; 280 } 281 282 return str.substring( 1,end-1 ) ; 283 } 284 285 /** 286 * 内部で使われる byte[] から String 生成 メソッド 287 * 288 * @param byteValue 変換するバイト列 289 * @param start 変換開始アドレス 290 * @param length 変換バイト数 291 * @param encode 変換する文字エンコード 292 * 293 * @return 変換後文字列 294 */ 295 public static String makeString( final byte[] byteValue, final int start, final int length,final String encode ) { 296 297 if( encode.startsWith( "Unicode" ) ) { 298 String errMsg = "Unicode文字列は、変換できません。[" + encode + "]" + CR; 299 throw new RuntimeException( errMsg ); 300 } 301 302 String rtn = null; 303 if( byteValue != null ) { 304 try { 305 // encode コードで変換されている byte[] を、String に変換。 306 rtn = new String( byteValue,start,length,encode ); 307 } catch( UnsupportedEncodingException ex ) { // 変換コードが存在しないエラー 308 String errMsg = "文字変換コードが存在しません。[" + encode + "]" + CR 309 + ex.getMessage() ; 310 throw new RuntimeException( errMsg,ex ); 311 } 312 } 313 return rtn; 314 } 315 316 /** 317 * 指定の文字列をバイトコードに変換します。 318 * 引数の文字列が null の場合は、return は、byte[0] を返します。 319 * 320 * @param value 変換するストリング値 321 * @param encode 変換する文字エンコード 322 * 323 * @return 変換後文字列 324 */ 325 public static byte[] makeByte( final String value,final String encode ) { 326 byte[] rtnByte = new byte[0]; 327 if( value != null ) { 328 try { 329 rtnByte = value.getBytes( encode ); // byte[] に encode コードで変換。 330 } catch( UnsupportedEncodingException ex ) { // 変換コードが存在しないエラー 331 String errMsg = "文字変換コードが存在しません。[" + encode + "]" + CR 332 + ex.getMessage(); 333 throw new RuntimeException( errMsg,ex ); 334 } 335 } 336 return rtnByte; 337 } 338 339 /** 340 * 半角スペースで固定長(半角換算の数)に変換した文字列を返します。 341 * 半角スペース埋めは、文字が半角、全角混在でもかまいません。 342 * 内部にセットした文字列は、変化しません。 343 * 344 * @param str Fill埋めする文字列 345 * @param su_fill Fill埋めする文字列の長さ。(半角換算の数) 346 * 347 * @return Fill埋めした新しいStringを返す。 348 */ 349 public static String stringXFill( final String str,final int su_fill ) { 350 char[] charValue ; 351 352 if( str == null ) { charValue = new char[0]; } 353 else { charValue = str.toCharArray(); } 354 int len = charValue.length; 355 356 if( su_fill < len ) { 357 String errMsg = "元の文字数がフォームより長いです。(数字が壊れます。)" 358 + "su_fill[" + su_fill + "], len[" + len + "]" + CR 359 + "input=[" + str + "]" + CR; 360 throw new RuntimeException( errMsg ); 361 } 362 363 char[] charbuf = new char[ su_fill ]; // 移す char 配列を新規作成 364 Arrays.fill( charbuf,' ' ); 365 System.arraycopy( charValue,0,charbuf,0,len ); 366 367 return new String( charbuf ); // コピーした配列全てを文字列に変換 368 } 369 370 /** 371 * 半角スペースで固定長(半角換算の数)に変換した文字列を返します。 372 * 半角スペース埋めは、文字が半角、全角混在でもかまいません。 373 * 内部にセットした文字列は、変化しません。 374 * 375 * @param str Fill埋めする文字列 376 * @param su_fill Fill埋めする文字列の長さ。(半角換算の数) 377 * @param encode Fill埋めする文字列の文字エンコード 378 * 379 * @return Fill埋めした新しいStringを返す。 380 */ 381 public static String stringFill( final String str,final int su_fill,final String encode ) { 382 if( su_fill < 0 ) { 383 String errMsg = "指定文字数が負です。[" + su_fill + "]"; 384 throw new RuntimeException( errMsg ); 385 } 386 387 byte[] byteValue = makeByte( str,encode ); 388 int len = byteValue.length; 389 390 // 内部文字列が指定長より長い場合 391 if( len >= su_fill ) { 392 return makeString( byteValue,0,su_fill,encode ); 393 } 394 else { 395 byte[] space = makeByte( " ",encode ); 396 int spaceLen = space.length ; 397 if( spaceLen == 4 ) { // encode が、UnicodeLittle の場合の特殊処理 398 space[0] = space[2]; 399 space[1] = space[3]; 400 spaceLen = 2; 401 } 402 byte[] bytebuf = new byte[ su_fill ]; 403 for( int i=0; i<len; i++ ) { bytebuf[i] = byteValue[i]; } 404 405 int k = 0; 406 for( int j=len; j<su_fill; j++ ) { // 余った部分は、スペース埋め 407 if( k >= spaceLen ) { k = 0; } 408 bytebuf[j] = space[k++]; 409 } 410 return makeString( bytebuf,0,su_fill,encode ); // 新たに、すべての長さの部分文字列を作成する。 411 } 412 } 413 414 /** 415 * 整数のフォーム( 12 で、整数部 12桁を表す)に合った新しい文字列を作り、それを返します。 416 * 実行できるのは、整数の String に対してのみです。 417 * 内部にセットした文字列は、変化しません。 418 * 419 * String str = StringUtil.intFill( "123",10 ); 420 * 421 * 実行結果:"0000000123" 422 * 423 * @param str 整数の String 424 * @param su_fill フォームを表す数字 ( 12 で、整数部 12桁を表す) 425 * 426 * @return 整数のフォームに合った文字列 427 */ 428 public static String intFill( final String str,final int su_fill ) { 429 if( su_fill < 0 ) { 430 String errMsg = "指定文字数が負です。[" + su_fill + "]"; 431 throw new RuntimeException( errMsg ); 432 } 433 434 char[] charbuf = new char[ su_fill ]; // 移す char 配列を新規作成 435 Arrays.fill( charbuf,'0' ); 436 437 if( str == null ) { return new String( charbuf ); } 438 439 char[] charValue = str.toCharArray(); 440 int len = charValue.length; 441 442 if( su_fill < len ) { 443 String errMsg = "元の文字数がフォームより長いです。(数字が壊れます。) su_fill[" + su_fill + "], len[" + len + "]"; 444 throw new RuntimeException( errMsg ); 445 } 446 447 System.arraycopy( charValue,0,charbuf,su_fill-len,len ); 448 449 return new String( charbuf ); // コピーした配列全てを文字列に変換 450 } 451 452 /** 453 * 全角スペースで固定長(半角換算の数)に変換した文字列を返します。 454 * 455 * @param str Fill埋めする文字列 456 * @param su_fill Fill埋めする文字列の長さ。(半角換算の数) 457 * @param encode Fill埋めする文字列の文字エンコード 458 * 459 * @return 全角スペースでFill埋めした新しいStringを返す。 460 */ 461 public static String stringKFill( final String str,final int su_fill,final String encode ) { 462 if( su_fill < 0 ) { 463 String errMsg = "指定文字数が負です。[" + su_fill + "]"; 464 throw new RuntimeException( errMsg ); 465 } 466 467 byte[] byteValue = makeByte( str,encode ); 468 int len = byteValue.length; 469 470 // 内部文字列が指定長より長い場合 471 if( len >= su_fill ) { 472 return makeString( byteValue,0,su_fill,encode ); 473 } 474 else { 475 byte[] space = makeByte( " ",encode ); 476 int spaceLen = space.length ; 477 byte[] bytebuf = new byte[ su_fill ]; 478 for( int i=0; i<len; i++ ) { bytebuf[i] = byteValue[i]; } 479 int k = 0; 480 for( int j=len; j<su_fill; j++ ) { // 余った部分は、スペース埋め 481 if( k >= spaceLen ) { k = 0; } 482 bytebuf[j] = space[k++]; 483 } 484 return makeString( bytebuf,0,su_fill,encode ); // 新たに、すべての長さの部分文字列を作成する。 485 } 486 } 487 488 /** 489 * 小数点のフォームに合った新しい文字列を作り、文字列を返します。 490 * 現在は、小数点が頭に付いたり、最後に付く場合の対応はしていません。 491 * フォームは、12.4 で、 000000000010.1000 という形で、ピリオドを含みます。 492 * 493 * // 半角 整数部 10 桁 小数部 5桁で固定長の文字を得る。 494 * String str = StringUtil.realFill( "123.45" ,10.5 ) ; 495 * 496 * 実行結果:0000000123.45000 497 * 498 * @param str 整数の String 499 * @param su_fill フォームを表す実数 ( 12.4 で、整数部 12桁、小数部 4桁 計17桁 ) 500 * 501 * @return value 小数点のフォーム文字列 502 */ 503 public static String realFill( final String str,final double su_fill ) { 504 if( su_fill < 0 ) { 505 String errMsg = "指定文字数が負です。[" + su_fill + "]"; 506 throw new RuntimeException( errMsg ); 507 } 508 509 int su_seisu = (int)(su_fill); // 指定のフォームの整数部を取り出す。 510 int su_shosu = (int)(su_fill*10 - su_seisu*10); // 小数部を取り出しす。 511 char[] charbuf = new char[ su_seisu + su_shosu + 1 ]; // 移す char 配列 512 Arrays.fill( charbuf,'0' ); 513 514 if( str == null ) { 515 charbuf[su_seisu] = '.' ; 516 return new String( charbuf ); 517 } 518 519 char[] charValue = str.toCharArray(); 520 int len = charValue.length; 521 522 // 検査する文字列の加工(検査文字列は、インデックスの値とバイト数で文字数を求める。) 523 // 小数点の位置を求める。 本当は、String クラスの indexOf で求めず、byte[] で検索すべきである。 524 int valueindex = str.indexOf( '.' ); 525 if( valueindex < 0 ) { // valueform 自体が、合っていない。 526 String errMsg = "元の文字列に小数点が、含まれません。"; 527 throw new RuntimeException( errMsg ); 528 } 529 int su_valueseisu = valueindex; // 整数部の文字数は、小数点の位置と同じ 530 int su_valueshosu = len - valueindex - 1 ; // 小数部の文字数は、全文字数−整数文字数−1 531 532 // フォームの整数文字数 ー 加工文字の整数文字部 = 転送先配列位置 533 int to_index = su_seisu - su_valueseisu; 534 if( to_index < 0 ) { 535 String errMsg = "元の数字が、フォームより長いです。(数字が壊れます。) form[" + su_fill + "]"; 536 throw new RuntimeException( errMsg ); 537 } 538 int end_index; 539 // 転送先配列終了位置は、お互いの小数部の文字数により、短い方を選ぶ。 540 if( su_shosu < su_valueshosu ) { end_index = su_seisu + su_shosu + 1; } 541 else { end_index = su_seisu + su_valueshosu + 1; } 542 543 int from_index = 0; 544 while( to_index < end_index ) { 545 charbuf[to_index++] = charValue[from_index++]; // 転送(移し替え) 546 } 547 return new String( charbuf ); // コピーした配列全てを文字列に変換 548 } 549 550 /** 551 * ストリングの部分文字列を,別の文字列に置換えたストリングを返します。 552 * 例えば,リターンコードを< br />に置換えて,画面上に改行表示させるが可能です。 553 * 554 * @og.rev 5.0.0.1 (2009/08/15) 不要なオブジェクトの生成を抑制する。 555 * 556 * @param target 元の文字列 557 * @param from 置換元部分文字列 558 * @param to 置換先部分文字列 559 * 560 * @return 置換えた文字列 561 */ 562 public static String replace( final String target,final String from,final String to ) { 563 if( target == null || from == null || to == null || target.indexOf( from ) < 0 ) { return target; } 564 565 StringBuilder strBuf = new StringBuilder( target.length() ); 566 567 int start = 0; 568 int end = target.indexOf( from,start ); 569 while( end >= 0 ) { 570 strBuf.append( target.substring( start,end ) ); 571 strBuf.append( to ); 572 start = end + from.length(); 573 end = target.indexOf( from,start ); 574 } 575 576 if( start > 0 ) { 577 strBuf.append( target.substring( start ) ); 578 return strBuf.toString(); 579 } 580 else { 581 return target; // 3.4.0.2 (2003/09/05) 582 } 583 } 584 585 /** 586 * 引数の AA:01 BB:02 CC:03 … 形式の、元値:新値のスペース区切り文字列を元に、 587 * 元値を新値に置き換えます。 588 * これは、部分置換ではなく、完全一致で処理します。 589 * caseStr が null や、マッチしなかった場合は、元の値を返します。 590 * その場合、ignoreCase=true としている場合は、元の文字列 も大文字に変換されて返されます。 591 * 592 * ゼロ文字列を元値や新値で使用することは可能ですが、スペースを使用することはできません。 593 * 594 * @og.rev 5.7.2.3 (2014/01/31) 新規追加 595 * 596 * @param target 元の文字列 597 * @param caseStr 置換リスト(AA:01 BB:02 CC:03 … 形式)。null の場合は、比較しない。 598 * @param ignoreCase true:大文字として比較 / false:そのまま比較 599 * 600 * @return 元の文字列を置き換えた結果。置換リストに存在しなければ、元の文字列を返す。 601 */ 602 public static String caseReplace( final String target,final String caseStr,final boolean ignoreCase ) { 603 if( target == null ) { return target; } 604 605 String rtn = ignoreCase ? target.toUpperCase(Locale.JAPAN) : target ; 606 607 if( caseStr != null ) { 608 String caseTmp = " " + caseStr.trim() + " " ; // CASE文字列の形式をそろえる。 609 610 int adrs = caseTmp.indexOf( " " + rtn + ":" ); // 前スペースと後ろコロンで、単語を確定する。 611 if( adrs >= 0 ) { 612 int st = caseTmp.indexOf( ':' , adrs+1 ); // 最初のコロンの位置。元値:新値 の 新値 の取出 613 int ed = caseTmp.indexOf( ' ' , st+1 ); // コロンの次から、最初のスペースの位置 614 if( st >= 0 && ed >= 0 ) { 615 rtn = caseTmp.substring( st+1,ed ); // コロンの次から、スペースの前までを切り出す。 616 } 617 } 618 } 619 620 return rtn ; 621 } 622 623 /** 624 * String型の配列から、カンマ(,)で連結されたString を作成します。 625 * これは,配列を表示用に変換する為のものです。 626 * array2line( array, ",", 0 ); と同等です。 627 * 628 * @param array 元の文字列配列 629 * 630 * @return 一列に変換した文字列(引数がnullの場合は、長さ0の文字列を返す) 631 */ 632 public static String array2csv( final String[] array ) { 633 return array2line( array, ",", 0 ); 634 } 635 636 /** 637 * String型の配列から、セパレーターで連結されたString を作成します。 638 * これは,配列を表示用に変換する為のものです。 639 * 640 * @param array 元の文字列配列 641 * @param separator 区切り記号 642 * 643 * @return 一列に変換した文字列(引数がnullの場合は、長さ0の文字列を返す) 644 */ 645 public static String array2line( final String[] array,final String separator ) { 646 return array2line( array, separator,0 ); 647 } 648 649 /** 650 * String型の配列から、セパレーターで連結されたString を作成します。 651 * これは,配列を表示用に変換する為のものです。 652 * 653 * @param array 元の文字列配列 654 * @param separator 区切り記号 655 * @param start 配列の連結開始アドレス 656 * 657 * @return 一列に変換した文字列(引数がnullの場合は、長さ0の文字列を返す) 658 */ 659 public static String array2line( final String[] array,final String separator,final int start ) { 660 if( array == null || array.length <= start ) { return ""; } 661 662 StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 663 664 rtn.append( valueOf( array[start] ) ); 665 for(int i=start+1; i < array.length; i++) { 666 rtn.append( separator ); 667 rtn.append( valueOf( array[i] ) ); 668 } 669 return rtn.toString(); 670 } 671 672 /** 673 * Enumerationから、オブジェクト配列データを返します。 674 * これは,Enumerationを表示用に変換する為のものです。 675 * 676 * @param enume 元のEnumeration 677 * 678 * @return オブジェクト配列 679 */ 680 public static Object[] enume2Array( final Enumeration<?> enume ) { // 4.3.3.6 (2008/11/15) Generics警告対応 681 if( enume == null || ! enume.hasMoreElements() ) { return new Object[0]; } 682 683 ArrayList<Object> obj = new ArrayList<Object>(); 684 685 while( enume.hasMoreElements() ) { 686 obj.add( enume.nextElement() ); 687 } 688 return obj.toArray(); 689 } 690 691 /** 692 * Enumerationから、オブジェクト配列データを返します。 693 * これは,Enumerationを表示用に変換する為のものです。 694 * 695 * @param enume 元のEnumeration 696 * @param objs - 配列が十分な大きさを持つ場合は、Vector の要素が格納される配列。 697 * そうでない場合は、要素を格納するために同じ実行時の型の新しい配列が割り当てられる 698 * @return オブジェクト配列 699 */ 700 public static Object[] enume2Array( final Enumeration<?> enume,final Object[] objs ) { // 4.3.3.6 (2008/11/15) Generics警告対応 701 if( enume == null || ! enume.hasMoreElements() ) { return objs ; } 702 703 ArrayList<Object> list = new ArrayList<Object>(); 704 705 while( enume.hasMoreElements() ) { 706 list.add( enume.nextElement() ); 707 } 708 return list.toArray( objs ); 709 } 710 711 /** 712 * Iteratorから、セパレーターで連結されたString を作成します。 713 * これは,Enumerationを表示用に変換する為のものです。 714 * 715 * @param ite 元のIterator 716 * @param separator 区切り記号 717 * 718 * @return 一列に変換した文字列 719 */ 720 public static String iterator2line( final Iterator<?> ite,final String separator ) { 721 if( ite == null || ! ite.hasNext() ) { return ""; } 722 723 StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 724 725 rtn.append( valueOf( ite.next() ) ); 726 while( ite.hasNext() ) { 727 rtn.append( separator ); 728 rtn.append( valueOf( ite.next() ) ); 729 } 730 return rtn.toString(); 731 } 732 733 /** 734 * カンマ(,)で連結された String を、配列に分解して、その値を返します。 735 * これは,たとえば、AAA,BBB,CCC などのリソースデータを受けてから配列に入れ直して、 736 * メニューなりリストを作成するのに便利です。 737 * 要素が空の場合は、必ずカンマの間にスペースを入れて記述してください。 738 * 分割後の文字列の前後のスペースは、削除されます。 739 * 740 * @param csvData 元のデータ 741 * 742 * @return 文字列配列(引数がnull、ゼロ文字列の場合は、サイズ0の配列を返す) 743 */ 744 public static String[] csv2Array( final String csvData ) { 745 return csv2Array( csvData, ',', 0 ); 746 } 747 748 /** 749 * 区切り文字で連結された String を、配列に分解して、その値を返します。 750 * これは,たとえば、AAA,BBB,CCC などのリソースデータを受けてから配列に入れ直して、 751 * メニューなりリストを作成するのに便利です。 752 * 連続した区切り文字は、1文字に分割します。 753 * 分割後の文字列の前後のスペースは、削除されます。 754 * 755 * @param csvData 元のデータ 756 * @param separator 区切り文字 757 * 758 * @return 文字列配列(引数がnull、ゼロ文字列の場合は、サイズ0の配列を返す) 759 */ 760 public static String[] csv2Array( final String csvData,final char separator ) { 761 return csv2Array( csvData,separator,0 ); 762 } 763 764 /** 765 * 区切り文字で連結された String を、配列に分解して、その値を返します。 766 * これは,たとえば、AAA,BBB,CCC などのリソースデータを受けてから配列に入れ直して、 767 * メニューなりリストを作成するのに便利です。 768 * 連続した区切り文字は、1文字に分割します。 769 * 分割後の文字列の前後のスペースは、削除されます。 770 * 第3の引数は、リターンする配列の個数を指定します。ただし、第一引数がNULLや、ゼロ文字列 771 * などの不正な情報の場合は、通常と同じく 長さゼロの配列を返します。 772 * len=0 を指定すると分解したデータの個数分の配列を作成します。指定の長さが短い場合は、 773 * そこまで分のみ取り込みます。指定の長さが長い場合は、余分に配列を作成します。 774 * セットされる値は、"" です。 775 * 776 * @og.rev 3.8.5.1 (2006/05/08) 設定配列の数を指定できるように変更 777 * @og.rev 3.8.8.2 (2007/01/26) 分割後の値の前後のスペースは削除します。 778 * 779 * @param csvData 元のデータ 780 * @param separator 区切り文字 781 * @param len 指定の長さの配列で返します。 782 * 783 * @return 文字列配列(引数がnull、ゼロ文字列の場合は、サイズ0の配列を返す) 784 */ 785 public static String[] csv2Array( final String csvData,final char separator, final int len ) { 786 if( csvData == null || csvData.length() == 0 ) { return new String[0] ; } 787 788 CSVTokenizer token = new CSVTokenizer( csvData,separator ); 789 790 int count = (len > 0 ) ? len : token.countTokens() ; 791 String[] rtn = new String[ count ]; 792 int i = 0; 793 for( ; i<count && token.hasMoreTokens() ; i++ ) { 794 rtn[i] = token.nextToken().trim(); // 3.8.8.2 (2007/01/26) 795 } 796 for( ; i<count; i++ ) { 797 rtn[i] = "" ; 798 } 799 800 return rtn; 801 } 802 803 /** 804 * 区切り文字で連結された String を、配列に分解して、その値を返します。 805 * これは,たとえば、AAA,BBB,CCC などのリソースデータを受けてから配列に入れ直して、 806 * メニューなりリストを作成するのに便利です。 807 * csv2Array と異なり、連続した区切り文字は、分割せずにトークンのみ切り出します。 808 * トークンは、カンマ(,)のみで区切り、その後 trim() により 809 * 前後のスペースを削除します。 810 * 811 * @param csvData 元のデータ 812 * 813 * @return 文字列配列 814 */ 815 public static String[] csv2ArrayOnly( final String csvData ) { 816 if( csvData == null || csvData.length() == 0 ) { return new String[0] ; } 817 818 StringTokenizer token = new StringTokenizer( csvData,"," ); 819 820 ArrayList<String> list = new ArrayList<String>(); 821 while( token.hasMoreTokens() ) { 822 String temp = token.nextToken().trim(); 823 if( temp.length() > 0 ) { list.add( temp ); } 824 } 825 826 return list.toArray( new String[list.size()] ); 827 } 828 829 /** 830 * カンマ(,)、ハイフン(-)で連結された String を、配列に分解して、その値を返す処理のスペシャル版です。 831 * 0,1,3,5-8,10-* などの数字文字列から、必要な数字をピックアップした文字配列を返します。 832 * 引数の maxNo は、"*" が指定された場合の、最大の数値です。 833 * よって、"*" は、単独(1文字)では、0-maxNo を表し、N-* では、N-maxNo を意味します。 834 * カンマ区切りで指定される値は、基本的に数字で、重複(1,1,2,2)、逆転(3,2,1)で指定できます。 835 * 5-3 と指定した場合は、5,4,3 に分解されます。逆順に登録されます。 836 * 重複削除、昇順並べ替え等が、必要な場合は、取得後の配列を操作してください。 837 * 838 * @og.rev 5.5.7.2 (2012/10/09) 新規追加 839 * @og.rev 5.9.12.4 (2016/09/30) アルファベットの対応を廃止し、数字配列のみサポートします。 840 * 841 * @param csvData 0,1,3,5-8,10-* などのCSV-ハイフン文字列 842 * @param maxNo "*" が指定された場合の、最大数 843 * @return 文字列配列(引数がnull、ゼロ文字列の場合は、サイズ0の配列を返す) 844 */ 845 public static String[] csv2ArrayExt( final String csvData , final int maxNo ) { 846 if( csvData == null || csvData.length() == 0 ) { return new String[0] ; } 847 848 String strData = csvData.replace( "-*" , "-" + maxNo ); // まず、N-* 形式を、N-maxNo に変換します。 849 strData = strData.replace( "*" , "0-" + maxNo ); // その後、"*" 単独(1文字)を、0-maxNo に変換します。 850 851 ArrayList<String> noList = new ArrayList<String>(); 852 853 String[] nos = strData.split( "," ); // カンマで分解。N , N-M , N-* のどれか 854 for( int i=0; i<nos.length; i++ ) { 855 String sno = nos[i] ; 856 int hai = sno.indexOf( '-' ); 857 // ハイフンが含まれているときは前後に分解して、間を埋める 858 if( hai > 0 ) { 859 String st1 = sno.substring( 0,hai ); // 先頭からハイフンまで 860 String st2 = sno.substring( hai+1 ); // ハイフンから最後まで 861 // 5.9.12.4 (2016/09/30) アルファベット対応をやめる 862// if( st1.length() == 1 && st2.length() == 1 ) { // ともに1文字の場合は、char化して処理。(英数字処理) 863// char ch1 = st1.charAt(0); 864// char ch2 = st2.charAt(0); 865// if( ch1 < ch2 ) { while( ch1 <= ch2 ) { noList.add( String.valueOf(ch1++) ); } } 866// else { while( ch1 >= ch2 ) { noList.add( String.valueOf(ch1--) ); } } 867// } 868// else { 869 int ch1 = Integer.parseInt( st1 ); 870 int ch2 = Integer.parseInt( st2 ); 871 if( ch1 < ch2 ) { while( ch1 <= ch2 ) { noList.add( String.valueOf(ch1++) ); } } 872 else { while( ch1 >= ch2 ) { noList.add( String.valueOf(ch1--) ); } } 873// } 874 } 875 else { 876 noList.add( String.valueOf(sno) ); 877 } 878 } 879 return noList.toArray( new String[noList.size()] ) ; 880 } 881 882 /** 883 * Integer限定版です。 884 * V6では返り値の型変更をしていますが、V5では一旦別名にしておきます。 885 * 886 * @og.rev 5.9.0.0 (2015/09/04) 新規追加 887 * @og.rev 5.9.12.4 (2016/09/30) アルファベットの対応を廃止し、数字配列のみサポートします。 888 * 889 * @param csvData 0,1,3,5-8,10-* などのCSV-ハイフン文字列 890 * @param maxNo "*" が指定された場合の、最大数 891 * @return 文字列配列(引数がnull、ゼロ文字列の場合は、サイズ0の配列を返す) 892 */ 893 public static Integer[] csv2ArrayExt2( final String csvData , final int maxNo ) { 894 if( csvData == null || csvData.length() == 0 ) { return new Integer[0] ; } 895 896 String strData = csvData.replace( "-*" , "-" + maxNo ); // まず、N-* 形式を、N-maxNo に変換します。 897 strData = strData.replace( "*" , "0-" + maxNo ); // その後、"*" 単独(1文字)を、0-maxNo に変換します。 898 899 ArrayList<Integer> noList = new ArrayList<Integer>(); 900 901 String[] nos = strData.split( "," ); // カンマで分解。N , N-M , N-* のどれか 902 for( int i=0; i<nos.length; i++ ) { 903 String sno = nos[i] ; 904 int hai = sno.indexOf( '-' ); 905 // ハイフンが含まれているときは前後に分解して、間を埋める 906 if( hai > 0 ) { 907 String st1 = sno.substring( 0,hai ); // 先頭からハイフンまで 908 String st2 = sno.substring( hai+1 ); // ハイフンから最後まで 909 // 5.9.12.4 (2016/09/30) アルファベット対応をやめる 910// if( st1.length() == 1 && st2.length() == 1 ) { // ともに1文字の場合は、char化して処理。(英数字処理) 911// char ch1 = st1.charAt(0); 912// char ch2 = st2.charAt(0); 913// if( ch1 < ch2 ) { while( ch1 <= ch2 ) { noList.add( Integer.valueOf(ch1++) ); } } 914// else { while( ch1 >= ch2 ) { noList.add( Integer.valueOf(ch1--) ); } } 915// } 916// else { 917 int ch1 = Integer.parseInt( st1 ); 918 int ch2 = Integer.parseInt( st2 ); 919 if( ch1 < ch2 ) { while( ch1 <= ch2 ) { noList.add( Integer.valueOf(ch1++) ); } } 920 else { while( ch1 >= ch2 ) { noList.add( Integer.valueOf(ch1--) ); } } 921// } 922 } 923 else { 924 noList.add( Integer.valueOf(sno) ); 925 } 926 } 927 return noList.toArray( new Integer[noList.size()] ) ; 928 } 929 930 /** 931 * Object 引数の文字列表現を返します。 932 * これは,String.valueOf とほぼ同じ動作をしますが、引数が null の場合に、 933 * "null" という文字列を返すのではなく、なにもない文字列 "" を返します。 934 * 935 * @param obj 文字列表現すべき元のオブジェクト 936 * 937 * @return 引数が null の場合は、"" に等しい文字列。そうでない場合は、obj.toString() の値 938 */ 939 public static String valueOf( final Object obj ) { 940 if( obj == null ) { return ""; } 941 else { return obj.toString(); } 942 } 943 944 /** 945 * HTML上のエスケープ文字を変換します。 946 * 947 * HTMLで表示する場合にきちんとエスケープ文字に変換しておかないと 948 * Script を実行されたり、不要なHTMLコマンドを潜り込まされたりするため、 949 * セキュリティーホールになる可能性があるので、注意してください。 950 * 951 * @param input HTMLエスケープ前の文字列 952 * 953 * @return エスケープ文字に変換後の文字列 954 */ 955 public static String htmlFilter( final String input ) { 956 if( input == null || input.length() == 0 ) { return ""; } 957 StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 958 char ch; 959 for(int i=0; i<input.length(); i++) { 960 ch = input.charAt(i); 961 switch( ch ) { 962 case '<' : rtn.append("<"); break; 963 case '>' : rtn.append(">"); break; 964 case '"' : rtn.append("""); break; 965 case '\'' : rtn.append("'"); break; 966 case '&' : rtn.append("&"); break; 967 default : rtn.append(ch); 968 } 969 } 970 return rtn.toString() ; 971 } 972 973 /** 974 * XML上のエスケープ文字を変換します。 975 * 976 * HTMLとの違いはアポストロフィです。 977 * 978 * @og.rev 5.8.2.2 (2014/12/19) 新規作成 979 * 980 * @param input XMLエスケープ前の文字列 981 * 982 * @return エスケープ文字に変換後の文字列 983 */ 984 public static String xmlFilter( final String input ) { 985 if( input == null || input.length() == 0 ) { return ""; } 986 StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 987 char ch; 988 for(int i=0; i<input.length(); i++) { 989 ch = input.charAt(i); 990 switch( ch ) { 991 case '<' : rtn.append("<"); break; 992 case '>' : rtn.append(">"); break; 993 case '"' : rtn.append("""); break; 994 case '\'' : rtn.append("'"); break; 995 case '&' : rtn.append("&"); break; 996 default : rtn.append(ch); 997 } 998 } 999 return rtn.toString() ; 1000 } 1001 1002 /** 1003 * JavaScript 等の引数でのクオート文字をASCII変換します。 1004 * 1005 * JavaScript の引数の値に、ダブルクオート(")、シングルクオート(')が 1006 * 含まれると、文字列を表す為に前後に指定しているクオートと混乱し、 1007 * データを表現できないケースがあります。その場合には、クオート文字を 1008 * ASCII文字に置き換える事で、指定の文字を渡すことが可能になります。 1009 * ここでは、引数文字列に、ダブルクオート(")、シングルクオート(')が、 1010 * 含まれると、それぞれ、ASCII コード(¥x22、¥x27)に置き換えます。 1011 * なお、null は、ゼロ文字列に変換して返します。 1012 * 1013 * @param input 入力文字列 1014 * 1015 * @return クオート文字をASCII文字に置き換えた文字列 1016 */ 1017 public static String quoteFilter( final String input ) { 1018 if( input == null || input.length() == 0 ) { return ""; } 1019 if( input.indexOf( '\'' ) < 0 && input.indexOf( '"' ) < 0 ) { return input; } 1020 1021 StringBuilder rtn = new StringBuilder(); 1022 char ch; 1023 for(int i=0; i<input.length(); i++) { 1024 ch = input.charAt(i); 1025 switch( ch ) { 1026 case '"' : rtn.append( "\\x22" ); break; 1027 case '\'' : rtn.append( "\\x27" ); break; 1028 default : rtn.append( ch ); 1029 } 1030 } 1031 return rtn.toString() ; 1032 } 1033 1034 /** 1035 * JSON形式で出力する場合のためのエスケープ処理です。 1036 * 1037 * 1038 * @og.rev 5.9.6.4(2016/03/25) 新規作成 1039 * 1040 * @param input XMLエスケープ前の文字列 1041 * 1042 * @return エスケープ文字に変換後の文字列 1043 */ 1044 public static String jsonFilter( final String input ) { 1045 if( input == null || input.length() == 0 ) { return ""; } 1046 StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 1047 char ch; 1048 for(int i=0; i<input.length(); i++) { 1049 ch = input.charAt(i); 1050 switch( ch ) { 1051 case '"' : rtn.append("\\\""); break; 1052 case '\\' : rtn.append("\\\\"); break; 1053 case '/' : rtn.append("\\/"); break; 1054 case '\b' : rtn.append("\\b"); break; 1055 case '\f' : rtn.append("\\f"); break; 1056 case '\n' : rtn.append("\\n"); break; 1057 case '\r' : rtn.append("\\r"); break; 1058 case '\t' : rtn.append("\\t"); break; 1059 default : rtn.append(ch); 1060 } 1061 } 1062 return rtn.toString() ; 1063 } 1064 1065 /** 1066 * 特殊文字のエスケープを元に戻す処理です。 1067 * 元に戻すことで、htmlとして、使用します。 1068 * scriptタグは動作しないようにしています。 1069 * またignoreで指定したタグを除いて<にします。 1070 * 1071 * @og.rev 5.9.33.0 (2018/06/01) 新規作成 1072 * @og.rev 5.10.0.1 (2018/06/15) 修正 1073 * 1074 * @param input 特殊文字がエスケープされた文字列 1075 * @param ignore 変換しないタグ 1076 * 1077 * @return エスケープ前の文字列 1078 */ 1079 public static String escapeFilter( final String input, final String ignore ) { 1080 if( input == null || input.length() == 0 ) { return ""; } 1081 String output = input; 1082 1083 1084 for( final String[] trg : ESC_ARY ) { 1085 output = replace( output, trg[0], trg[1] ); 1086 } 1087 1088 // XSS対策 1089 // jquery.cleditor.jsと同様の対応。 1090 // スクリプトは実行させない 1091 output = output.replaceAll("<(?=/?(?i)script)", "<"); 1092 1093 // <と>の表示対応 1094 // jquery.cleditor.custom.jsのupdateFrame(TextRich用)に同様処理を実装。(エスケープ文字の\有無が異なります) 1095 //strong|font|a|br|p|span|div 1096 // 指定のタグ前方の<以外の<は、<に変換する。 1097 output = output.replaceAll("<(?!/?(?i)("+ignore+")( |>|/))", "<"); 1098 1099 return output; 1100 } 1101 1102 /** 1103 * 所定のキャラクタコードを取り除いた文字列を作成します。 1104 * 1105 * 実現したい機能は、String#replace( 'x','' ) 的な表現です。 1106 * つまり、指定のキャラクタを取り除きたいのですが、上記コマンドでは、 1107 * コンパイル時にエラーが発生します。 1108 * 取り除きたいキャラクタコードが存在しない場合は、指定の文字列を 1109 * そのまま返します。 1110 * 1111 * @param value 処理対象の文字列 1112 * @param ch 取り除きたいキャラクタ 1113 * 1114 * @return 処理後の文字列 1115 */ 1116 public static String deleteChar( final String value,final char ch ) { 1117 if( value == null || value.indexOf( ch ) < 0 ) { return value; } 1118 char[] chs = value.toCharArray() ; 1119 int j=0; 1120 for( int i=0;i<chs.length; i++ ) { 1121 if( chs[i] == ch ) { continue; } 1122 chs[j] = chs[i]; 1123 j++; 1124 } 1125 return String.valueOf( chs,0,j ); 1126 } 1127 1128 /** 1129 * 文字列に含まれる、特定の文字の個数をカウントして返します。 1130 * 1131 * @og.rev 5.2.0.0 (2010/09/01) 1132 * 1133 * @param value 処理対象の文字列 1134 * @param ch カウントする文字 1135 * 1136 * @return カウント数 1137 */ 1138 public static int countChar( final String value,final char ch ) { 1139 if( value == null || value.indexOf( ch ) < 0 ) { return 0; } 1140 char[] chs = value.toCharArray() ; 1141 int cnt=0; 1142 for( int i=0;i<chs.length; i++ ) { 1143 if( chs[i] == ch ) { cnt++; } 1144 } 1145 return cnt; 1146 } 1147 1148 /** 1149 * CODE39 の 文字列を作成します。 1150 * 1151 * CODE39 は、『0〜9, A〜Z,-,・, ,$,/,+,%』のコードが使用できる 1152 * バーコードの体系です。通常 * で始まり * で終了します。 1153 * また、チェックデジット に、モジュラス43 が使われます。 1154 * ここでは、指定の文字列の前後に、* を付与し、必要であれば 1155 * チェックデジットも付与します。 1156 * 指定の入力文字列には、* を付けないでください。 1157 * 1158 * @param value 処理対象の文字列 1159 * @param checkDigit チェックデジットの付与(true:付ける/false:付けない) 1160 * 1161 * @return 処理後の文字列 1162 */ 1163 public static String code39( final String value,final boolean checkDigit ) { 1164 String rtn = ( value == null ) ? "" : value ; 1165 if( ! checkDigit ) { return "*" + rtn + "*"; } 1166 1167 int kei = 0; 1168 int cd; 1169 for( int i=0; i<rtn.length(); i++ ) { 1170 cd = MODULUS_43.indexOf( rtn.charAt(i) ); 1171 if( cd < 0 ) { 1172 String errMsg = "指定の文字中に、CODE39 規定外文字が使用されています。[" + rtn.charAt(i) + "]" ; 1173 throw new RuntimeException( errMsg ); 1174 } 1175 kei += cd ; 1176 } 1177 char digit = MODULUS_43.charAt( kei % 43 ); 1178 1179 return "*" + rtn + digit + "*" ; 1180 } 1181 1182 /** 1183 * 引数 in が、null または、ゼロ文字列の場合は、デフォルト値 def を返します。 1184 * もちろん、in も def も null の場合は、null を返します。 1185 * 1186 * @param in 基準となる文字列 1187 * @param def デフォルト文字列 1188 * 1189 * @return ( in != null ) ? in : def ; 1190 */ 1191 public static String nval( final String in,final String def ) { 1192 return ( in == null || in.length() == 0 ) ? def : in ; 1193 } 1194 1195 /** 1196 * 引数 in が、null または、ゼロ文字列の場合は、デフォルト値 def を返します。 1197 * 1198 * @param in 基準となる文字列 1199 * @param def デフォルト数字 1200 * 1201 * @return 引数 in を変換した数字。変換できない場合は デフォルト値 def 1202 */ 1203 public static int nval( final String in,final int def ) { 1204 return ( in == null || in.length() == 0 ) ? def : Integer.parseInt( in ) ; 1205 } 1206 1207 /** 1208 * 引数 in が、null または、ゼロ文字列の場合は、デフォルト値 def を返します。 1209 * 1210 * @param in 基準となる文字列 1211 * @param def デフォルト数字 1212 * 1213 * @return 引数 in を変換した数字。変換できない場合は デフォルト値 def 1214 */ 1215 public static long nval( final String in,final long def ) { 1216 return ( in == null || in.length() == 0 ) ? def : Long.parseLong( in ) ; 1217 } 1218 1219 /** 1220 * 引数 in が、null または、ゼロ文字列の場合は、デフォルト値 def を返します。 1221 * 通常は、"true" または、 "TRUE" 文字列を、論理値の true に変換します。 1222 * ただし、文字列長が 1文字の場合のみ、"0" 以外を true に変換します。 1223 * 1224 * @param in 基準となる文字列 1225 * @param def デフォルト論理値 1226 * 1227 * @return 引数 in を変換した論理値。変換できない場合は デフォルト値 def 1228 */ 1229 public static boolean nval( final String in,final boolean def ) { 1230 boolean rtn = def; 1231 if( in != null && in.length() != 0 ) { 1232 rtn = "true".equalsIgnoreCase( in ) ; 1233 if( in.length() == 1 ) { rtn = ! "0".equals( in ); } 1234 } 1235 return rtn ; 1236 } 1237 1238 /** 1239 * 引数 in が、null、"_"、ゼロ文字列の場合は、デフォルト値 def を返します。 1240 * 1241 * さらに、メモリ領域を節約する為、intern() の結果を返します。 1242 * 1243 * @og.rev 5.2.2.0 (2010/11/01) "_" の取り扱い変更 1244 * 1245 * @param in 基準となる文字列 1246 * @param def デフォルト文字列 1247 * 1248 * @return null、"_"、ゼロ文字列の場合は、デフォルト文字列を、そうでなければ、入力文字を返す。 1249 */ 1250 public static String nval2( final String in,final String def ) { 1251 return ( in == null || in.length() == 0 || "_".equals( in ) ) ? def : in.intern() ; 1252 } 1253 1254 /** 1255 * 引数 in が、null または、ゼロ文字列の場合は、デフォルト値 def を返します。 1256 * ただし、NULL代替文字(_)は デフォルト値 def2 に置き換えます。 1257 * 1258 * さらに、メモリ領域を節約する為、intern() の結果を返します。 1259 * 1260 * @og.rev 5.2.2.0 (2010/11/01) "_" の取り扱い変更 1261 * 1262 * @param in 基準となる文字列 1263 * @param def デフォルト文字列 1264 * @param def2 NULL代替文字(_)の場合のデフォルト文字列 1265 * 1266 * @return NULL文字列関係の場合は、ゼロ文字列を、そうでなければ、入力文字を返す。 1267 */ 1268 public static String nval2( final String in,final String def,final String def2 ) { 1269 return ( in == null || in.length() == 0 ) ? def : ( "_".equals( in ) ? def2 : in.intern() ) ; 1270 } 1271 1272 /** 1273 * 引数 in が、null または、ゼロ文字列、またはすべて空白文字の場合は、true を返します。 1274 * それ以外は false を返します。 1275 * 1276 * 注意は、オールスペースやタブ文字、改行文字も true になります。 1277 * 1278 * @param in 基準となる文字列 1279 * 1280 * @return NULL文字列関係の場合は、true を、そうでなければ、false を返す。 1281 */ 1282 public static boolean isNull( final String in ) { 1283 if( in == null || in.length() == 0 ) { return true; } 1284 1285 // String.trim().length()==0 の高速版 1286 for( int i=0; i<in.length(); i++ ) { 1287 if( !Character.isWhitespace( in.charAt(i) ) ) { 1288 return false; 1289 } 1290 } 1291 return true; 1292 } 1293 1294 /** 1295 * Throwable の printStackTrace() 結果を文字列に変換して返します。 1296 * 1297 * @param th printStackTraceすべき元のThrowableオブジェクト 1298 * 1299 * @return Throwableの詳細メッセージ( th.printStackTrace() ) 1300 */ 1301 public static String stringStackTrace( final Throwable th ) { 1302 if( th == null ) { return null; } 1303 1304 StringWriter sw = new StringWriter(); 1305 th.printStackTrace( new PrintWriter( sw ) ); 1306 1307 return String.valueOf( sw ); 1308 } 1309 1310 /** 1311 * Throwable の printStackTrace() 結果の内、opengion に関する箇所だけを文字列に変換して返します。 1312 * 1313 * printStackTrace() すると、膨大なメッセージが表示されるため、その中の、"org.opengion" を 1314 * 含む箇所だけを、抜粋します。 1315 * 1316 * @og.rev 5.7.2.0 (2014/01/10) 新規作成 1317 * 1318 * @param th 元のThrowableオブジェクト 1319 * 1320 * @return Throwableの詳細メッセージ( StackTraceElement の抜粋 ) 1321 */ 1322 public static String ogStackTrace( final Throwable th ) { 1323 if( th == null ) { return null; } 1324 1325 StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 1326 1327 StackTraceElement[] eles = th.getStackTrace(); 1328 if( eles.length > 0 ) { 1329 rtn.append( " " ).append( eles[0].toString() ).append( CR ); 1330 } 1331 1332 for( int i=1; i<eles.length; i++ ) { 1333 String cls = eles[i].getClassName(); 1334 if( cls.indexOf( "org.opengion" ) >= 0 ) { 1335 rtn.append( " at " ).append( eles[i].toString() ).append( CR ); 1336 } 1337 } 1338 1339 return rtn.toString(); 1340 } 1341 1342 /** 1343 * 大きな浮動小数点数について、カンマ編集を行います。 1344 * 1345 * このメソッドでは、1.23 E12 などの数字は扱いません。通常の 1346 * 数字とピリオドで構成された文字列のみ、変換対象になります。 1347 * (ただし、不正な文字列を与えてもエラーチェックはしていません。) 1348 * minFraction には、少数点部に与える固定値を指定します。入力文字列が 1349 * その桁数より少ない場合は、0埋めします。 1350 * 多い場合でもカットしません。 1351 * minFraction が 0 の場合は、少数点は付きません。 1352 * ".12" などの少数点は、必ず先頭に 0 が付きます。 1353 * 入力文字列が null か、ゼロ文字列時は、そのまま入力データを返します。 1354 * 1355 * <pre> 1356 * DecimalFormat format = new DecimalFormat( "#,##0.00########" ); 1357 * double dd = Double.parseDouble( val ); 1358 * return format.format( dd ); 1359 * </pre> 1360 * に対して、minFraction分の少数以下のゼロの指定と、inに ',' が 1361 * 含まれた処理を追加した感じになります。 1362 * 1363 * @og.rev 4.0.0.0 (2007/10/26) 空白のトリム処理を追加 1364 * 1365 * @param in 変換元の文字列 1366 * @param minFraction 変換時の少数点以下の固定桁数 1367 * 1368 * @return カンマ編集後の数字型文字列 1369 */ 1370 public static String numberFormat( final String in, final int minFraction ) { 1371 if( in == null || in.length() == 0 ) { return in ; } 1372 1373 // 4.0.0.0 (2007/10/26) 1374 String tmp = in.trim(); 1375 1376 if( tmp.length() == 0 ) { return tmp ; } 1377 1378 char[] chs = tmp.toCharArray(); 1379 int pos = 0; 1380 1381 // 整数部の設定 1382 boolean firstZero = true; 1383 StringBuilder buf1 = new StringBuilder(); 1384 while( pos < chs.length ) { 1385 char ch = chs[pos++]; 1386 if( ch == '.' ) { break; } 1387 else if( ch != '-' && ch != ',' && ( ch != '0' || !firstZero )) { 1388 buf1.append( ch ); 1389 firstZero = false; 1390 } 1391 } 1392 if( buf1.length() == 0 ) { 1393 buf1.append( '0' ); 1394 } 1395 1396 for( int i=buf1.length()-3; i>0; i-=3 ) { 1397 buf1.insert( i,',' ); 1398 } 1399 if( chs[0] == '-' ) { buf1.insert( 0,'-' ); } 1400 1401 // 少数部の設定 1402 // 3.6.0.3 (2004/10/05) 桁数が多い場合でもカットしない 1403 StringBuilder buf2 = new StringBuilder(); 1404 while( pos < chs.length ) { 1405 buf2.append( chs[pos++] ); 1406 } 1407 1408 while( buf2.length() < minFraction ) { 1409 buf2.append( '0' ); 1410 } 1411 1412 if( buf2.length() > 0 ) { 1413 buf1.append( '.' ).append( buf2 ); 1414 } 1415 1416 return buf1.toString(); 1417 } 1418 1419 /** 1420 * 識別id に応じた オブジェクトを作成します。 1421 * 作成するには、デフォルトコンストラクターが必要です。 1422 * 1423 * @param cls 作成するクラスのフルネーム 1424 * 1425 * @return オブジェクト 1426 * @throws RuntimeException 何らかのエラーが発生した場合 1427 */ 1428 public static Object newInstance( final String cls ) { 1429 return newInstance( cls,Thread.currentThread().getContextClassLoader() ); 1430 } 1431 1432 /** 1433 * 指定されたクラスローダを使って、識別id に応じた オブジェクトを作成します。 1434 * 作成するには、デフォルトコンストラクターが必要です。 1435 * initialize パラメータは true 相当(それまでに初期化されていない場合だけ初期化)です。 1436 * 1437 * @param cls 作成するクラスのフルネーム 1438 * @param loader 作成するクラスのクラスローダ 1439 * 1440 * @return オブジェクト 1441 * @throws RuntimeException 何らかのエラーが発生した場合 1442 */ 1443 public static Object newInstance( final String cls,final ClassLoader loader ) { 1444 try { 1445 return Class.forName( cls,true,loader ).newInstance(); 1446 } 1447 catch( ClassNotFoundException ex1 ) { 1448 String errMsg = "クラスが見つかりません。class=[" + cls + "]" + CR 1449 + ex1.getMessage() ; 1450 throw new RuntimeException( errMsg,ex1 ); 1451 } 1452 catch( LinkageError ex2 ) { 1453 String errMsg = "リンケージが失敗しました。class=[" + cls + "]" + CR 1454 + ex2.getMessage(); 1455 throw new RuntimeException( errMsg,ex2 ); 1456 } 1457 catch( InstantiationException ex3 ) { 1458 String errMsg = "インスタンスの生成が失敗しました。class=[" + cls + "]" + CR 1459 + ex3.getMessage() ; 1460 throw new RuntimeException( errMsg,ex3 ); 1461 } 1462 catch( IllegalAccessException ex4 ) { 1463 String errMsg = "クラスまたは初期化子にアクセスできません。class=[" + cls + "]" + CR 1464 + ex4.getMessage(); 1465 throw new RuntimeException( errMsg,ex4 ); 1466 } 1467 catch( RuntimeException ex5 ) { // 3.6.0.0 (2004/09/17) 1468 String errMsg = "予期せぬエラー class=[" + cls + "]" + CR 1469 + ex5.getMessage() ; 1470 throw new RuntimeException( errMsg,ex5 ); 1471 } 1472 } 1473 1474 /** 1475 * 指定のURL文字列同士を連結させます。 1476 * そのとき、後方URLが、絶対パスの場合は、連結せず 後方URLを返します。 1477 * 第2引数以降は、絶対パス判定をせず直前のURLの末尾判定のみで連結します。 1478 * 1479 * 絶対パスかどうかは、通常のファイル属性と同様に、先頭が、'/' (UNIX)または、 1480 * 2文字目が、":" (Windows)の場合、または、先頭が "\" (ネットワークパス)で 1481 * 始まる場合で判断します。 1482 * 連結時に、前方URLの末尾に "/" を付加します。 1483 * 1484 * 処理の互換性確保のため、第3引数の可変長引数を追加しています。 1485 * 1486 * @og.rev 5.0.0.1 (2009/08/15) 不要なオブジェクトの生成を抑制する。 1487 * @og.rev 5.6.5.2 (2013/06/21) 第3引数を可変長引数に変更 1488 * 1489 * @param url1 先頭URL文字列 1490 * @param url2 後方URL文字列(絶対パスの場合は、返り値) 1491 * @param urls 後方URL文字列 1492 * 1493 * @return URL文字列同士の連結結果 url1 + url2(url2が絶対パスの場合は、url2から連結開始) 1494 */ 1495 public static String urlAppend( final String url1,final String url2,final String... urls ) { 1496 StringBuilder rtnUrl = new StringBuilder( 200 ); 1497 1498 if( url2 == null || url2.length() == 0 ) { rtnUrl.append( url1 ) ; } 1499 else if( ( url1 == null || url1.length() == 0 ) || 1500 ( url2.charAt(0) == '/' ) || // 実ディレクトリが UNIX 1501 ( url2.length() > 1 && url2.charAt(1) == ':' ) || // 実ディレクトリが Windows 1502 ( url2.charAt(0) == '\\' ) ) { // 実ディレクトリが ネットワークパス 1503 rtnUrl.append( url2 ) ; 1504 } 1505 else { 1506 char ch = url1.charAt( url1.length()-1 ) ; 1507 if( ch == '/' || ch == '\\' ) { 1508 rtnUrl.append( url1 ).append( url2 ) ; 1509 } 1510 else { 1511 rtnUrl.append( url1 ).append( "/" ).append( url2 ) ; 1512 } 1513 } 1514 1515 // ここからが、追加分 1516 for( String url : urls ) { 1517 if( url != null && url.length() > 0 ) { 1518 char ch = rtnUrl.charAt( rtnUrl.length()-1 ) ; 1519 if( ch == '/' || ch == '\\' ) { 1520 rtnUrl.append( url ) ; 1521 } 1522 else { 1523 rtnUrl.append( "/" ).append( url ) ; 1524 } 1525 } 1526 } 1527 1528 return rtnUrl.toString() ; 1529 } 1530 1531 /** 1532 * Unicode文字列の値を HTML のエスケープ記号(&#xZZZZ;)に変換します。 1533 * 1534 * SJIS(JA16SJIS) で作成されたデータベースに、(NVARCHAR2)を使用して中国語等を登録するのは 1535 * 非常に複雑でかつ、リスクが大きい処理になります。 1536 * ORACLE殿でも、自信を持っては勧められない機能とのコメントを頂いています。 1537 * そこで、HTMLでのエスケープ文字を使用して、Unicodeを文字列化して登録する為の 1538 * DBType として、新規に作成します。 1539 * ここでは、入力文字を、キャラクタ(char)型に分解し、(&#xZZZZ;)に変換していきます。 1540 * よって、通常に1文字(Shift-JISで2Byte,UTF-8で3Byte)が、8Byteになります。 1541 * この変換された文字列を、HTML上でそのまま取り出すと、元のUnicode文字に戻る為、 1542 * 通常のShift-JISでは、扱えない文字(中国語など)でも表示可能になります。 1543 * ここでは、2バイト文字のみ、変換しています。 1544 * 1545 * @param value 変換前の文字列 1546 * 1547 * @return HTMLのエスケープ記号(&#xZZZZ;) 1548 */ 1549 public static String getUnicodeEscape( final String value ) { 1550 if( value == null || value.length() == 0 ) { return ""; } 1551 1552 StringBuilder rtn = new StringBuilder( value.length() * 4 ); 1553 1554 for( int i=0; i<value.length(); i++ ) { 1555 char ch = value.charAt(i); 1556 1557 if( ch > 0xff ) { 1558 String hex = Integer.toHexString( (int)ch ) ; 1559 rtn.append( UTF_STR[hex.length()] ).append( hex ).append( ";" ); 1560 } 1561 else { 1562 rtn.append( ch ); 1563 } 1564 } 1565 1566 return rtn.toString(); 1567 } 1568 1569 /** 1570 * HTML のエスケープ記号(&#xZZZZ;)をUnicode文字列に戻します。 1571 * 1572 * HTMLでのエスケープ文字を使用して登録された文字を、Unicodeに戻します。 1573 * (&#xZZZZ;)の8Byteを、もとのキャラクタコードに戻し、合成します。 1574 * ここでは、通常の文字列に混在したエスケープ文字も戻せるようにします。 1575 * 1576 * @param value HTMLのエスケープ記号(&#xZZZZ;)を含む文字列 1577 * 1578 * @og.rev 5.9.5.3 (2016/02/26) 無限ループ対応 1579 * 1580 * @return 通常のUnicode文字列 1581 */ 1582 public static String getReplaceEscape( final String value ) { 1583 if( value == null || value.length() == 0 ) { return ""; } 1584 1585 StringBuilder rtn = new StringBuilder( value ); 1586 1587 int st = rtn.indexOf( "&#" ); 1588 while( st >= 0 ) { 1589 if( st+7 < rtn.length() && rtn.charAt( st+7 ) == ';' ) { 1590 int ch = Integer.parseInt( rtn.substring( st+3,st+7 ),16 ); 1591 rtn.replace( st,st+8, Character.toString( (char)ch ) ); 1592 } 1593// st = rtn.indexOf( "&#",st ); 1594 st = rtn.indexOf( "&#",st + 1 ); // 5.9.5.3 (2016/02/26) 無限ループ対応 1595 } 1596 1597 return rtn.toString(); 1598 } 1599 1600 /** 1601 * 文字列をdoubleに変換します。 1602 * 1603 * これは、Double.parseDouble( value ) と、ほぼ同じ動作を行います。 1604 * 内部的には、引数の カンマ(,) を削除した文字列を、Double.parseDouble( value ) 1605 * に渡します。 1606 * また、引数が、null,ゼロ文字列,'_' の時には、0.0 を返します。 1607 * 1608 * @param value doubleに変換する元の文字列 1609 * 1610 * @return 変換後のdouble数値 1611 */ 1612 public static double parseDouble( final String value ) { 1613 double rtn ; 1614 1615 if( value == null || value.length() == 0 || value.equals( "_" ) ) { 1616 rtn = 0.0d; 1617 } 1618 else if( value.indexOf( ',' ) < 0 ) { 1619 rtn = Double.parseDouble( value ); 1620 } 1621 else { 1622 char[] chs = value.toCharArray() ; 1623 int j=0; 1624 for( int i=0;i<chs.length; i++ ) { 1625 if( chs[i] == ',' ) { continue; } 1626 chs[j] = chs[i]; 1627 j++; 1628 } 1629 rtn = Double.parseDouble( String.valueOf( chs,0,j ) ); 1630 } 1631 1632 return rtn ; 1633 } 1634 1635 /** 1636 * カラーキーワードより、Colorオブジェクトを作成します。 1637 * 1638 * 指定文字列は、java.awt.Color クラスのstatic フィールド名で指定します。 1639 * BLACK , BLUE , CYAN , DARK_GRAY , GRAY , GREEN , LIGHT_GRAY , 1640 * MAGENTA , ORANGE , PINK , RED , WHITE , YELLOW , PURPLE , TRANSPARENT(透明) が指定できます。 1641 * また、先頭に、# を付ける事で、#XXXXXX形式の16bitRGB表記 でも指定可能です。 1642 * static フィールド名のMapを管理していますが、存在しない場合は、エラーになります。 1643 * 1644 * @og.rev 3.8.9.1 (2007/06/29) 新規作成 1645 * @og.rev 4.1.1.0 (2008/02/04) CLR_MAP に存在しない場合はエラーにします。 1646 * 1647 * @param value java.awt.Color フィールドを示す文字列または、#XXXXXX形式の16bitRGB表記 1648 * 1649 * @return Colorオブジェクト 1650 * @see java.awt.Color#BLACK 1651 */ 1652 public static Color getColorInstance( final String value ) { 1653 final Color clr ; 1654 1655 if( value.startsWith("#") ) { 1656 int code = Integer.parseInt( value.substring(1),16 ); 1657 clr = new Color( code ); 1658 } 1659 else { 1660 clr = CLR_MAP.get( value ); 1661 if( clr == null ) { 1662 String errMsg = "指定の色コードは使用できません Color=[" + value + "]" + CR 1663 + "ColorMap=" + CLR_MAP.keySet().toString(); 1664 throw new RuntimeException( errMsg ); 1665 } 1666 } 1667 1668 return clr; 1669 } 1670 1671 /** 1672 * 引数からspanタグを取り除いて返します。 1673 * 1674 * 引数が、<span ・・・>XXXX</span>形式の場合、XXXX のみ出力します。 1675 * 1676 * @og.rev 4.3.4.3 (2008/12/22) TableWriterで利用していたものを移動 1677 * @og.rev 5.9.11.1 (2016/08/10) spanだけでなく、pre,textareaも除外するようにしておく 1678 * 1679 * @param data 元のString文字列 1680 * 1681 * @return spanタグが取り除かれた文字列 1682 */ 1683 public static String spanCut( final String data ) { 1684 String rtn = data; 1685 if( data != null ){ 1686 if( data.startsWith( "<span" ) ) { 1687 int st = data.indexOf( '>' ); 1688 int ed = data.indexOf( "</span>",st ); 1689 rtn = data.substring( st+1,ed ); 1690 } 1691 else if( data.startsWith( "<pre" ) ) { // 5.9.11.1 本来はV6のようにするべきだが、V5は暫定的な対応にしておく 1692 int st = data.indexOf( '>' ); 1693 int ed = data.indexOf( "</pre>",st ); 1694 rtn = data.substring( st+1,ed ); 1695 } 1696 else if( data.startsWith( "<textarea" ) ) { 1697 int st = data.indexOf( '>' ); 1698 int ed = data.indexOf( "</textarea>",st ); 1699 rtn = data.substring( st+1,ed ); 1700 } 1701 } 1702 1703 return rtn ; 1704 } 1705 1706 /** 1707 * 簡易CSS形式のフォーマットを、Mapにセットします。 1708 * 1709 * 簡易CSS形式とは、セレクタのない、{ プロパティ1 : 値1 ; ・・・ } 形式とします。 1710 * これを、プロパティ1 と 値1 のMap にセットする処理を行います。 1711 * コメントは、削除されます。また、同一プロパティが記述されている場合は、後処理を採用します。 1712 * 1713 * なお、入力テキストが、null か、{…} が存在しない場合は、null を返します。 1714 * 1715 * @og.rev 5.6.5.2 (2013/06/21) 新規追加 1716 * 1717 * @param cssText 簡易CSS形式のフォーマット文字列 1718 * 1719 * @return パース結果のMap 1720 */ 1721 public static Map<String,String> cssParse( final String cssText ) { 1722 Map<String,String> map = null; 1723 1724 if( cssText != null ) { 1725 // まずコメントを削除します。 1726 StringBuilder buf = new StringBuilder( cssText ); 1727 1728 int ad1 = buf.indexOf( "/*" ); 1729 while( ad1 >= 0 ) { 1730 int ad2 = buf.indexOf( "*/" , ad1 ); 1731 if( ad2 < 0 ) { buf = buf.delete( ad1,buf.length() ); break; } // 閉じてなければ以降を全削除 1732 buf = buf.delete( ad1,ad2+2 ); 1733 ad1 = buf.indexOf( "/*" ); // コメントは削除されたので、初めから検索する。 1734 } 1735 1736 // 処理対象は、{ 〜 } の間の文字列。 1737 ad1 = buf.indexOf( "{" ); 1738 int ad2 = buf.indexOf( "}",ad1 ); 1739 if( ad1 >= 0 && ad2 > 0 ) { 1740 String tempText = buf.substring( ad1+1,ad2 ); // これが処理対象の文字列 1741 1742 String[] recode = tempText.split( ";" ); // KEY1 : VAL1; の ; で分割する。 1743 1744 for( int i=0; i<recode.length; i++ ) { 1745 int ad = recode[i].indexOf( ':' ); 1746 if( ad > 0 ) { 1747 String key = recode[i].substring( 0,ad ).trim(); 1748 String val = recode[i].substring( ad+1 ).trim(); 1749 if( key.isEmpty() || val.isEmpty() ) { continue; } 1750 1751 if( map == null ) { map = new HashMap<String,String>(); } // 対象データがある時だけMapを作りたかったので。 1752 map.put( key,val ); 1753 } 1754 } 1755 } 1756 } 1757 return map ; 1758 } 1759 1760 /** 1761 * 引数から空白文字を削除して返します。 1762 * 1763 * 1764 * @og.rev 5.6.9.4 (2013/10/31) TableWriterで利用していたものを移動 1765 * 1766 * @param data 元のString文字列 1767 * 1768 * @return 空白文字が取り除かれた文字列 1769 */ 1770 public static String deleteWhitespace( final String data ) { 1771 if( data == null || data.length() == 0 ){ 1772 return data; 1773 } 1774 return data.replaceAll( "\\s", "" ) ; 1775 } 1776 1777 /** 1778 * 引数から指定文字の分のバイト数で切った文字列を返します。 1779 * 文字列のバイト数は指定のエンコードでカウントします。 1780 * (文字の途中で切れる事はありません) 1781 * 1782 * 1783 * @og.rev 5.9.1.3 (2015/10/30) 新規作成 1784 * 1785 * @param org 元のString文字列 1786 * @param cutBytes 切るバイト数 1787 * @param enc 文字列のエンコード 1788 * 1789 * @return バイト数で切った文字列 1790 */ 1791 public static String cut( String org, int cutBytes, String enc ) { 1792 try { 1793 if ( org == null || org.length() == 0 || cutBytes <= 0 || org.getBytes(enc).length <= cutBytes ) { 1794 return org; 1795 } 1796 1797 StringBuilder cutSb = new StringBuilder(); 1798 StringBuilder tmpSb = new StringBuilder(); 1799 1800 for (int i = 0; i < org.length(); i++) { 1801 String cut = org.substring(i, i + 1); 1802 if (cutBytes < tmpSb.toString().getBytes(enc).length + cut.getBytes(enc).length) { 1803 cutSb.append(tmpSb.toString()); 1804 break; 1805 } 1806 tmpSb.append(cut); 1807 } 1808 return cutSb.toString(); 1809 1810 } 1811 catch (UnsupportedEncodingException e) { 1812 e.printStackTrace(); 1813 return org; 1814 } 1815 } 1816 1817 /** 1818 * 引数から指定文字の分のバイト数で切った文字列を返します。 1819 * バイト数のカウントはUTF-8として行います。 1820 * 1821 * 1822 * @og.rev 5.9.1.3 (2015/10/30) 新規作成 1823 * 1824 * @param org 元のString文字列 1825 * @param cutBytes 切るバイト数 1826 * 1827 * @return バイト数で切った文字列 1828 */ 1829 public static String cut( String org, int cutBytes ) { 1830 return cut( org, cutBytes, "UTF-8"); 1831 } 1832}