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 org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 019import java.lang.reflect.InvocationTargetException; // Ver7.0.0.0 020import java.io.UnsupportedEncodingException; 021import java.net.URLEncoder; 022import java.net.URLDecoder; 023import java.util.ArrayList; 024import java.util.Arrays; 025import java.util.Enumeration; 026import java.util.StringJoiner; // 6.4.4.2 (2016/04/01) 027import java.util.concurrent.ConcurrentMap; // 6.4.3.3 (2016/03/04) 028import java.util.concurrent.ConcurrentHashMap; // 6.4.3.1 (2016/02/12) refactoring 029import java.util.Iterator; 030import java.util.StringTokenizer; 031import java.util.Locale ; // 5.7.2.3 (2014/01/31) 032import java.text.DecimalFormat; // 6.2.0.0 (2015/02/27) 033import java.util.function.UnaryOperator ; // 6.9.2.1 (2018/03/12) 034 035import static org.opengion.fukurou.system.HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 036import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.4.2.0 (2016/01/29) ローカル定義をやめて、HybsConst を使用する様に変更。 037import org.opengion.fukurou.system.ThrowUtil; // 6.4.2.0 (2016/01/29) package変更 fukurou.util → fukurou.system 038 039/** 040 * StringUtil.java は、共通的に使用される String関連メソッドを集約した、クラスです。 041 * 042 * @og.group ユーティリティ 043 * 044 * @version 4.0 045 * @author Kazuhiko Hasegawa 046 * @since JDK5.0, 047 */ 048public final class StringUtil { 049 050 /** 051 * code39 のチェックデジット計算に使用する モジュラス43 の変換表です。 052 * 053 */ 054 private static final String MODULUS_43 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" ; 055 056 /** 057 * getUnicodeEscape で使用する桁合わせ用文字列配列です。 058 * Unicodeの HexString 変換後の桁に応じて、埋め合わせします。 059 * 060 */ 061 private static final String[] UTF_STR = { "�", "�", "�", "�", "&#x" }; 062 063 // 4.0.3.0 (2007/12/26) 色コードにPURPLE を追加 064 // 5.7.8.0 (2014/07/04) 透明追加 065 // 6.0.2.1 (2014/09/26) ColorMap クラスに移動 066 067 // 6.2.0.0 (2015/02/27) #numberFormat( String , int ) で使用するフォーマット変換オブジェクト 068 private static final DecimalFormat[] FMT1 = new DecimalFormat[] { 069 new DecimalFormat( "#,##0" ) , 070 new DecimalFormat( "#,##0.0" ) , 071 new DecimalFormat( "#,##0.00" ) , 072 new DecimalFormat( "#,##0.000" ) , 073 new DecimalFormat( "#,##0.0000" ) } ; 074 075 private static final String ZERO = "00000000000000000000" ; // ゼロ埋めの種 076 077 /** 078 * デフォルトコンストラクターをprivateにして、 079 * オブジェクトの生成をさせないようにする。 080 * 081 */ 082 private StringUtil() {} 083 084 /** 085 * UTF-8 で、URLエンコードを行います。 086 * このメソッドは、JDK1.4 以上でないと使用できません。 087 * 088 * @param value エンコードする文字列 089 * 090 * @return 指定の文字コードでURLエンコードされた文字列 091 * @see #urlEncode2( String ) 092 * @og.rtnNotNull 093 */ 094 public static String urlEncode( final String value ) { 095 if( value == null ) { return ""; } 096 097 try { 098 return URLEncoder.encode( value,"UTF-8" ); 099 } 100 catch( final UnsupportedEncodingException ex ) { 101 final String errMsg = "UnsupportedEncodingException [UTF-8]" + CR 102 + ex.getMessage() ; 103 throw new OgRuntimeException( errMsg,ex ); 104 } 105 catch( final RuntimeException ex2 ) { // 3.6.0.0 (2004/09/17) 106 final String errMsg = "予期せぬエラー value=[" + value + "] , encode=[UTF-8]" + CR 107 + ex2.getMessage(); 108 throw new OgRuntimeException( errMsg,ex2 ); 109 } 110 } 111 112 private static final String UN_CHANGE = ":/?=&._~" ; 113 114 /** 115 * UTF-8 で、ASCII以外の文字の、URLエンコードします。 116 * 117 * 00 ~ 7F までのコードは、変換しません。 118 * 119 * これは、日本語ファイル名の直リンクなど、URLエンコードが必要ですが、 120 * http:// などのURL の場合は、':' , '/' は、エンコードしたくありません。 121 * また、openGion では、[カラム] などの特殊な変数を渡して、処理させているので 122 * それらのキーワードも変換してほしくありません。 123 * ただし、"%" と、";" は、変換します。 124 * 125 * @og.rev 6.2.0.1 (2015/03/06) ASCII以外の文字の、URLエンコードを行う。 126 * @og.rev 6.9.0.0 (2018/01/31) 半角の中でも ':' , '/' , '?' , '=' , '&' , '.' , '_' , '~' 以外の文字は置き換えます。 127 * 128 * @param value エンコードする文字列 129 * 130 * @return 指定の文字コードでURLエンコードされた文字列(ASCII は省く) 131 * @see #urlEncode( String ) 132 * @og.rtnNotNull 133 */ 134 public static String urlEncode2( final String value ) { 135 if( value == null ) { return ""; } 136 137 final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 138 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); 139 140 for( int i=0; i<value.length(); i++ ) { 141 final char ch = value.charAt(i); 142// if( ch > 0x7f ) { buf.append( ch ); } // ASCII以外は、とりあえず貯めておく 143 if( ch > 0x7f || UN_CHANGE.indexOf( ch ) < 0 ) { buf.append( ch ); } // ASCII以外は、とりあえず貯めておく 144 else { 145 if( buf.length() > 0 ) { // 前回のデータが残っている 146 rtn.append( urlEncode( buf.toString() ) ); // ASCII以外のurlEncode処理と追加 147 buf.setLength(0); // 初期化 148 } 149 rtn.append( ch ); 150 // // ファイル名に、";" や "%" が存在すると、認識できないため、半角文字でも変換しておきます。 151 // if( ch == ';' ) { rtn.append( "%3B" ); } // 特殊処理 152 // else if( ch == '%' ) { rtn.append( "%25" ); } 153 // else { rtn.append( ch ); } // ASCII文字の追加 154 } 155 } 156 157 if( buf.length() > 0 ) { // 残っている分 158 rtn.append( urlEncode( buf.toString() ) ); // ASCII以外のurlEncode処理と追加 159 } 160 161 return rtn.toString(); 162 } 163 164 /** 165 * UTF-8 でURLエンコードされた文字列をデコードします。 166 * このメソッドは、JDK1.4 以上でないと使用できません。 167 * 168 * @og.rev 5.4.5.0 追加 169 * @param value デコードする文字列 170 * 171 * @return デコードされた文字列 172 */ 173 public static String urlDecode( final String value ) { 174 try { 175 return URLDecoder.decode( value,"UTF-8" ); 176 } 177 catch( final UnsupportedEncodingException ex ) { 178 final String errMsg = "UnsupportedEncodingException [UTF-8]" + CR 179 + ex.getMessage() ; 180 throw new OgRuntimeException( errMsg,ex ); 181 } 182 catch( final RuntimeException ex2 ) { // 3.6.0.0 (2004/09/17) 183 final String errMsg = "予期せぬエラー value=[" + value + "] , encode=[UTF-8]" + CR 184 + ex2.getMessage(); 185 throw new OgRuntimeException( errMsg,ex2 ); 186 } 187 } 188 189 /** 190 * 文字列の後ろのスペースを削除します。 191 * String クラスの trim()メソッドは、文字列の両方のスペースを削除しますが、 192 * この rTrim( String ) は、後ろの半角スペースのみ、詰めます。 193 * 注意:'\u0020' (スペース文字) より小さい文字を切り取ります。 194 * 195 * @param str 元の文字列 196 * 197 * @return 後ろの半角スペースを詰めた、新しい文字列 198 */ 199 public static String rTrim( final String str ) { 200 if( str == null ) { return null; } 201 final int count = str.length(); 202 203 int len = count; 204 205 while( 0 < len && str.charAt(len-1) <= ' ' ) { 206 len--; 207 } 208 return len < count ? str.substring(0, len) : str; 209 } 210 211 /** 212 * 文字列の後ろから、" .0" の文字を削除した数字型文字列を返します。 213 * 数字型文字列は、入力文字列の後ろの スペース、小数点、ゼロを削除します。 214 * また、先頭が、"." で始まる場合は、"0" を追加します。 215 * 例: "123.00" ⇒ "123" , ".123" ⇒ "0.123" 216 * 217 * @og.rev 3.8.8.1 (2007/01/10) 新規作成 218 * 219 * @param str 元の文字列 220 * 221 * @return 数字文字列化された、新しい文字列 222 */ 223 public static String toNumber( final String str ) { 224 if( str == null ) { return null; } 225 226 String rtn = str.trim() ; 227 228 final int adrs = rtn.indexOf( '.' ); 229 final int count = rtn.length(); 230 int len = count; 231 232 if( adrs >= 0 ) { 233 while( adrs < len && ".0".indexOf( rtn.charAt(len-1) ) >= 0 ) { 234 len--; 235 } 236 } 237 238 if( len < count ) { rtn = rtn.substring(0, len); } 239 if( adrs == 0 ) { rtn = "0" + rtn; } 240 241 return rtn ; 242 } 243 244 /** 245 * 文字列の前方のゼロ(0)を削除します。 246 * 先頭の0を削除するまえに、trim して、スペースを削除しておきます。 247 * すべてがゼロ(0)の場合は、"0" を返します。 248 * 小数点( 0.01 など )の場合は、先頭の 0 がすべて消えるとまずいので、 249 * "0." 部分は、残します。 250 * 251 * @og.rev 3.5.4.5 (2004/01/23) 新規追加 252 * 253 * @param inStr 元の文字列 254 * 255 * @return 前方のゼロ(0)を削除した、新しい文字列 256 */ 257 public static String lTrim0( final String inStr ) { 258 if( inStr == null ) { return null; } 259 final String str = inStr.trim(); 260 final int count = str.length(); 261 262 int len = 0; 263 while( count > len && str.charAt(len) == '0' ) { 264 len++; 265 } 266 267 if( len == 0 ) { return str; } // 先頭がゼロでない。 268 else if( len == count ) { return "0"; } // すべてがゼロ 269 else if( str.charAt(len) == '.' ) { return "0" + str.substring(len); } 270 else { return str.substring(len); } 271 } 272 273 /** 274 * 文字列配列の各要素の後ろのスペースを削除します。 275 * 個々の配列要素に対して、rTrim( String str ) を適用します。 276 * 元の文字列配列に直接作用するのではなく、新しい文字列配列に 277 * 結果をコピーして返します。 278 * ただし、元の文字列配列が、null か、length == 0 の場合は、 279 * 元の文字列配列(アドレス)を返します。 280 * 注意:'\u0020' (スペース文字) より小さい文字を切り取ります。 281 * 282 * @param str 元の文字列配列(可変長引数) 283 * 284 * @return 後ろの半角スペースを詰めた、新しい文字列配列 285 */ 286 public static String[] rTrims( final String... str ) { 287 // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。 288 if( str == null || str.length == 0 ) { return str; } 289 290 String[] rtn = new String[str.length]; // str.length == 0 の場合、長さゼロの新しい配列を返す。 291 for( int i=0; i<str.length; i++ ) { 292 rtn[i] = rTrim( str[i] ); 293 } 294 return rtn ; 295 } 296 297 /** 298 * 文字列の前後のダブルクオートを取り外します。 299 * 前後にダブルクオートが入っていなければ、そのままの文字列を返します。 300 * 前後に入っていない(片方のみなど)場合も、そのままの文字列を返します。 301 * ※ 先頭に、'0 が含まれる場合は、カンマを削除します。 302 * 従来は、ダブルクオートしてから、rTrim してましたが、trim してから、 303 * ダブルクオート外しを行います。 304 * 305 * @og.rev 6.2.1.0 (2015/03/13) 先頭に、'0 が含まれる場合は、カンマを削除 306 * 307 * @param str 元の文字列 308 * 309 * @return ダブルクオートを取り外した新しい文字列 310 */ 311 public static String csvOutQuote( final String str ) { 312 if( str == null ) { return null; } 313 314 // 6.2.1.0 (2015/03/13) 先頭に、'0 が含まれる場合は、カンマを削除 315 String rtn = str.trim(); // ①前後のスペース削除 316 if( rtn.startsWith( "'0" ) ) { rtn = rtn.substring(1); } // ②先頭の'0 のカンマ外し 317 else { 318 final int end = rtn.length(); // ③前後のダブルクオート外し 319 if( end >= 2 && str.charAt(0) == '"' && str.charAt( end-1 ) == '"' ) { 320 rtn = rtn.substring( 1,end-1 ); 321 } 322 } 323 return rtn; 324 } 325 326 /** 327 * 内部で使われる byte[] から String 生成 メソッド。 328 * 329 * @param byteValue 変換するバイト列 330 * @param start 変換開始アドレス 331 * @param length 変換バイト数 332 * @param encode 変換する文字エンコード 333 * 334 * @return 変換後文字列 335 */ 336 public static String makeString( final byte[] byteValue, final int start, final int length,final String encode ) { 337 338 if( encode.startsWith( "Unicode" ) ) { 339 final String errMsg = "Unicode文字列は、変換できません。[" + encode + "]" + CR; 340 throw new OgRuntimeException( errMsg ); 341 } 342 343 String rtn = null; 344 if( byteValue != null ) { 345 try { 346 // encode コードで変換されている byte[] を、String に変換。 347 rtn = new String( byteValue,start,length,encode ); 348 } catch( final UnsupportedEncodingException ex ) { // 変換コードが存在しないエラー 349 final String errMsg = "文字変換コードが存在しません。[" + encode + "]" + CR 350 + ex.getMessage() ; 351 throw new OgRuntimeException( errMsg,ex ); 352 } 353 } 354 return rtn; 355 } 356 357 /** 358 * 指定の文字列をバイトコードに変換します。 359 * 引数の文字列が null の場合は、return は、byte[0] を返します。 360 * 361 * @param value 変換するストリング値 362 * @param encode 変換する文字エンコード 363 * 364 * @return 変換後文字列 365 */ 366 public static byte[] makeByte( final String value,final String encode ) { 367 byte[] rtnByte = new byte[0]; 368 if( value != null ) { 369 try { 370 rtnByte = value.getBytes( encode ); // byte[] に encode コードで変換。 371 } catch( final UnsupportedEncodingException ex ) { // 変換コードが存在しないエラー 372 final String errMsg = "文字変換コードが存在しません。[" + encode + "]" + CR 373 + ex.getMessage(); 374 throw new OgRuntimeException( errMsg,ex ); 375 } 376 } 377 return rtnByte; 378 } 379 380 /** 381 * 半角スペースで固定長(半角換算の数)に変換した文字列を返します。 382 * 半角スペース埋めは、文字が半角、全角混在でもかまいません。 383 * 内部にセットした文字列は、変化しません。 384 * 385 * @param str Fill埋めする文字列 386 * @param su_fill Fill埋めする文字列の長さ。(半角換算の数) 387 * 388 * @return Fill埋めした新しいStringを返す。 389 * @og.rtnNotNull 390 */ 391 public static String stringXFill( final String str,final int su_fill ) { 392 char[] charValue ; 393 394 if( str == null ) { charValue = new char[0]; } 395 else { charValue = str.toCharArray(); } 396 final int len = charValue.length; 397 398 if( su_fill < len ) { 399 final String errMsg = "元の文字数がフォームより長いです。(数字が壊れます。)" 400 + "su_fill[" + su_fill + "], len[" + len + "]" + CR 401 + "input=[" + str + "]" + CR; 402 throw new OgRuntimeException( errMsg ); 403 } 404 405 final char[] charbuf = new char[ su_fill ]; // 移す char 配列を新規作成 406 Arrays.fill( charbuf,' ' ); 407 System.arraycopy( charValue,0,charbuf,0,len ); 408 409 return new String( charbuf ); // コピーした配列全てを文字列に変換 410 } 411 412 /** 413 * 半角スペースで固定長(半角換算の数)に変換した文字列を返します。 414 * 半角スペース埋めは、文字が半角、全角混在でもかまいません。 415 * 内部にセットした文字列は、変化しません。 416 * 417 * @og.rev 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。 418 * 419 * @param str Fill埋めする文字列 420 * @param su_fill Fill埋めする文字列の長さ。(半角換算の数) 421 * @param encode Fill埋めする文字列の文字エンコード 422 * 423 * @return Fill埋めした新しいStringを返す。 424 */ 425 public static String stringFill( final String str,final int su_fill,final String encode ) { 426 if( su_fill < 0 ) { 427 final String errMsg = "指定文字数が負です。[" + su_fill + "]"; 428 throw new OgRuntimeException( errMsg ); 429 } 430 431 final byte[] byteValue = makeByte( str,encode ); 432 final int len = byteValue.length; 433 434 // 内部文字列が指定長より長い場合 435 if( len >= su_fill ) { 436 return makeString( byteValue,0,su_fill,encode ); 437 } 438 else { 439 byte[] space = makeByte( " ",encode ); 440 int spaceLen = space.length ; 441 if( spaceLen == 4 ) { // encode が、UnicodeLittle の場合の特殊処理 442 space[0] = space[2]; 443 space[1] = space[3]; 444 spaceLen = 2; 445 } 446 byte[] bytebuf = new byte[su_fill]; 447 // 6.3.6.0 (2015/08/16) System.arraycopy が使える箇所は、置き換えます。 448 System.arraycopy( byteValue,0,bytebuf,0,len ); // 6.3.6.0 (2015/08/16) 449 450 int k = 0; 451 for( int j=len; j<su_fill; j++ ) { // 余った部分は、スペース埋め 452 if( k >= spaceLen ) { k = 0; } 453 bytebuf[j] = space[k++]; 454 } 455 return makeString( bytebuf,0,su_fill,encode ); // 新たに、すべての長さの部分文字列を作成する。 456 } 457 } 458 459 /** 460 * 整数のフォーム( 12 で、整数部 12桁を表す)に合った新しい文字列を作り、それを返します。 461 * 実行できるのは、整数の String に対してのみです。 462 * 内部にセットした文字列は、変化しません。 463 * 桁数がオーバーする場合は、RuntimeException を throw します。 464 * 465 * String str = StringUtil.intFill( "123",10 ); 466 * 467 * 実行結果:"0000000123" 468 * 469 * @param str 整数の String 470 * @param su_fill フォームを表す正の数字 ( 12 で、整数部 12桁を表す) 471 * 472 * @return 整数のフォームに合った文字列 473 * @og.rtnNotNull 474 * @see #intFill( int ,int ) 475 * @throws RuntimeException su_fill が、負の数か、元の文字数がフォームより長い場合、エラー 476 */ 477 public static String intFill( final String str,final int su_fill ) { 478 if( su_fill < 0 ) { 479 final String errMsg = "指定文字数が負です。[" + su_fill + "]"; 480 throw new OgRuntimeException( errMsg ); 481 } 482 483 final char[] charbuf = new char[ su_fill ]; // 移す char 配列を新規作成 484 Arrays.fill( charbuf,'0' ); 485 486 if( str == null ) { return new String( charbuf ); } 487 488 final char[] charValue = str.toCharArray(); 489 final int len = charValue.length; 490 491 if( su_fill < len ) { 492 final String errMsg = "元の文字数がフォームより長いです。(数字が壊れます。) su_fill[" + su_fill + "], len[" + len + "]"; 493 throw new OgRuntimeException( errMsg ); 494 } 495 496 System.arraycopy( charValue,0,charbuf,su_fill-len,len ); 497 498 return new String( charbuf ); // コピーした配列全てを文字列に変換 499 } 500 501 /** 502 * 整数のフォーム( 12 で、整数部 12桁を表す)に合った新しい文字列を作り、それを返します。 503 * 実行できるのは、正の整数に対してのみです。 504 * 桁数がオーバーする場合は、オーバーしたまま返します。 505 * 506 * String str = StringUtil.intFill( 123,10 ); 507 * 508 * 実行結果:"0000000123" 509 * 510 * @og.rev 6.0.2.4 (2014/10/17) 新規追加 511 * 512 * @param num 正の整数 513 * @param su_fill フォームを表す数字 ( 12 で、整数部 12桁を表す) 514 * 515 * @return 整数のフォームに合った文字列 516 * @see #intFill( String ,int ) 517 * @throws RuntimeException su_fill または、num が、負の数の場合、エラー 518 */ 519 public static String intFill( final int num,final int su_fill ) { 520 if( num < 0 || su_fill < 0 ) { 521 final String errMsg = "指定文字数が負です。num=[" + num + "] , su_fill=[" + su_fill + "]"; 522 throw new OgRuntimeException( errMsg ); 523 } 524 525 String rtn = String.valueOf( num ); 526 527 final int len = su_fill - rtn.length(); // 桁の不足分を算出 528 if( len > 0 ) { 529 rtn = "00000000000000000000".substring( 0,len ) + rtn ; 530 } 531 532 return rtn; 533 } 534 535 /** 536 * 全角スペースで固定長(半角換算の数)に変換した文字列を返します。 537 * 538 * @param str Fill埋めする文字列 539 * @param su_fill Fill埋めする文字列の長さ。(半角換算の数) 540 * @param encode Fill埋めする文字列の文字エンコード 541 * 542 * @return 全角スペースでFill埋めした新しいStringを返す。 543 */ 544 public static String stringKFill( final String str,final int su_fill,final String encode ) { 545 if( su_fill < 0 ) { 546 final String errMsg = "指定文字数が負です。[" + su_fill + "]"; 547 throw new OgRuntimeException( errMsg ); 548 } 549 550 final byte[] byteValue = makeByte( str,encode ); 551 final int len = byteValue.length; 552 553 // 内部文字列が指定長より長い場合 554 if( len >= su_fill ) { 555 return makeString( byteValue,0,su_fill,encode ); 556 } 557 else { 558 final byte[] bytebuf = new byte[ su_fill ]; 559 System.arraycopy( byteValue, 0, bytebuf, 0, len ); // 6.3.9.0 (2015/11/06) System.arraycopy is more efficient(PMD) 560 561 final byte[] space = makeByte( " ",encode ); 562 final int spaceLen = space.length ; 563 int k = 0; 564 for( int j=len; j<su_fill; j++ ) { // 余った部分は、スペース埋め 565 if( k >= spaceLen ) { k = 0; } 566 bytebuf[j] = space[k++]; 567 } 568 return makeString( bytebuf,0,su_fill,encode ); // 新たに、すべての長さの部分文字列を作成する。 569 } 570 } 571 572 /** 573 * 小数点のフォームに合った新しい文字列を作り、文字列を返します。 574 * 現在は、小数点が頭に付いたり、最後に付く場合の対応はしていません。 575 * フォームは、12.4 で、 000000000010.1000 という形で、ピリオドを含みます。 576 * 577 * // 半角 整数部 10 桁 小数部 5桁で固定長の文字を得る。 578 * String str = StringUtil.realFill( "123.45" ,10.5 ) ; 579 * 580 * 実行結果:0000000123.45000 581 * 582 * @param str 整数の String 583 * @param su_fill フォームを表す実数 ( 12.4 で、整数部 12桁、小数部 4桁 計17桁 ) 584 * 585 * @return value 小数点のフォーム文字列 586 * @og.rtnNotNull 587 */ 588 public static String realFill( final String str,final double su_fill ) { 589 if( su_fill < 0 ) { 590 final String errMsg = "指定文字数が負です。[" + su_fill + "]"; 591 throw new OgRuntimeException( errMsg ); 592 } 593 594 final int su_seisu = (int)(su_fill); // 指定のフォームの整数部を取り出す。 595 final int su_shosu = (int)(su_fill*10 - su_seisu*10); // 小数部を取り出しす。 596 char[] charbuf = new char[ su_seisu + su_shosu + 1 ]; // 移す char 配列 597 Arrays.fill( charbuf,'0' ); 598 599 if( str == null ) { 600 charbuf[su_seisu] = '.' ; 601 return new String( charbuf ); 602 } 603 604 // 検査する文字列の加工(検査文字列は、インデックスの値とバイト数で文字数を求める。) 605 // 小数点の位置を求める。 本当は、String クラスの indexOf で求めず、byte[] で検索すべきである。 606 final int valueindex = str.indexOf( '.' ); 607 if( valueindex < 0 ) { // valueform 自体が、合っていない。 608 final String errMsg = "元の文字列に小数点が、含まれません。"; 609 throw new OgRuntimeException( errMsg ); 610 } 611 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid declaring a variable if it is unreferenced before a possible exit point. 612 613 // フォームの整数文字数 ー 加工文字の整数文字部 = 転送先配列位置 614 int toIndex = su_seisu - valueindex; // 6.4.1.1 (2016/01/16) 615 if( toIndex < 0 ) { 616 final String errMsg = "元の数字が、フォームより長いです。(数字が壊れます。) form[" + su_fill + "]"; 617 throw new OgRuntimeException( errMsg ); 618 } 619 int endIndex; 620 // 転送先配列終了位置は、お互いの小数部の文字数により、短い方を選ぶ。 621 final char[] charValue = str.toCharArray(); 622 final int su_valueshosu = charValue.length - valueindex - 1 ; // 小数部の文字数は、全文字数-整数文字数-1 623 if( su_shosu < su_valueshosu ) { endIndex = su_seisu + su_shosu + 1; } 624 else { endIndex = su_seisu + su_valueshosu + 1; } 625 626 int fromIndex = 0; 627 while( toIndex < endIndex ) { 628 charbuf[toIndex++] = charValue[fromIndex++]; // 転送(移し替え) 629 } 630 return new String( charbuf ); // コピーした配列全てを文字列に変換 631 } 632 633 /** 634 * ストリングの部分文字列を,別の文字列に置換えたストリングを返します。 635 * 例えば,リターンコードを< br />に置換えて,画面上に改行表示させるが可能です。 636 * 637 * @og.rev 5.0.0.1 (2009/08/15) 不要なオブジェクトの生成を抑制する。 638 * 639 * @param target 元の文字列 640 * @param from 置換元部分文字列 641 * @param to 置換先部分文字列 642 * 643 * @return 置換えた文字列 644 */ 645 public static String replace( final String target,final String from,final String to ) { 646 if( target == null || from == null || to == null || target.indexOf( from ) < 0 ) { return target; } 647 648 final StringBuilder strBuf = new StringBuilder( target.length() ); 649 650 int start = 0; 651 int end = target.indexOf( from,start ); 652 while( end >= 0 ) { 653 strBuf.append( target.substring( start,end ) ); 654 strBuf.append( to ); 655 start = end + from.length(); 656 end = target.indexOf( from,start ); 657 } 658 659 if( start > 0 ) { 660 strBuf.append( target.substring( start ) ); 661 return strBuf.toString(); 662 } 663 else { 664 return target; // 3.4.0.2 (2003/09/05) 665 } 666 } 667 668 /** 669 * 変数の置き換え処理を行います。 670 * 671 * 変換元の文字列から、prefix と、suffix で囲まれた文字列をピックアップして、 672 * func で指定の関数を、適用します。 673 * 変換元の文字列に、複数含まれていてもかまいません。 674 * 675 * これは、単純な変数ではなく、${env.XXX} の XXX を環境変数に置き換えたり、 676 * {@DATE.XXXX} を、日付文字列に置き換えたりする場合に、使用できます。 677 * 例えば、環境変数 の置き換えは、 678 * replaceText( orgText , "${env." , "}" , System::getenv ); 679 * とします。 680 * 日付関数の置き換えは、 681 * replaceText( orgText , "{@DATE." , "}" , HybsDateUtil::getDateFormat ); 682 * とします。 683 * orgTxt , prefix , suffix , func は必須で、null,ゼロ文字列、空白文字等の判定で、 684 * true の場合は、変換元の文字列 をそのまま返します。 685 * 686 * @og.rev 6.9.2.1 (2018/03/12) 新規追加 687 * 688 * @param orgTxt 変換元の文字列 689 * @param prefix 変換処理を行うキーワードの先頭文字列 690 * @param suffix 変換処理を行うキーワードの終了文字列 691 * @param func 変換処理を行う、関数型インタフェース 692 * @return 置換処理したテキスト 693 */ 694 public static String replaceText( final String orgTxt,final String prefix,final String suffix,final UnaryOperator<String> func ) { 695 if( isEmpty( orgTxt,prefix,suffix ) || func == null ) { return orgTxt; } 696 697 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); 698 699 // 環境変数の処理 700 int st0 = 0; 701 int st1 = orgTxt.indexOf( prefix ); 702 final int preLen = prefix.length() ; 703 final int sufLen = suffix.length() ; 704 while( st1 >= 0 ) { 705 final int ed = orgTxt.indexOf( suffix , st1 ); 706 if( ed >= 0 ) { 707 buf.append( orgTxt.substring( st0,st1 ) ); 708 final String key = orgTxt.substring( st1 + preLen , ed ); 709 buf.append( func.apply( key ) ); 710 711 st0 = ed + sufLen ; // suffix の長さ分 712 st1 = orgTxt.indexOf( prefix,st0 ); 713 } 714 else { 715 final String errMsg = orgTxt + "の、prefix[" + prefix + "] と、suffix[" + suffix + "]の整合性が取れていません。" ; 716 throw new OgRuntimeException( errMsg ); 717 } 718 } 719 720 return buf.append( orgTxt.substring( st0 ) ).toString(); 721 } 722 723 /** 724 * 引数の AA:01 BB:02 CC:03 … 形式の、元値:新値のスペース区切り文字列を元に、 725 * 元値を新値に置き換えます。 726 * これは、部分置換ではなく、完全一致で処理します。 727 * caseStr が null や、マッチしなかった場合は、元の値を返します。 728 * その場合、ignoreCase=true としている場合は、元の文字列 も大文字に変換されて返されます。 729 * 730 * ゼロ文字列を元値や新値で使用することは可能ですが、スペースを使用することはできません。 731 * 732 * @og.rev 5.7.2.3 (2014/01/31) 新規追加 733 * 734 * @param target 元の文字列 735 * @param caseStr 置換リスト(AA:01 BB:02 CC:03 … 形式)。null の場合は、比較しない。 736 * @param ignoreCase true:大文字として比較 / false:そのまま比較 737 * 738 * @return 元の文字列を置き換えた結果。置換リストに存在しなければ、元の文字列を返す。 739 */ 740 public static String caseReplace( final String target,final String caseStr,final boolean ignoreCase ) { 741 if( target == null ) { return target; } 742 743 String rtn = ignoreCase ? target.toUpperCase(Locale.JAPAN) : target ; 744 745 if( caseStr != null ) { 746 final String caseTmp = " " + caseStr.trim() + " " ; // CASE文字列の形式をそろえる。 747 748 final int adrs = caseTmp.indexOf( " " + rtn + ":" ); // 前スペースと後ろコロンで、単語を確定する。 749 if( adrs >= 0 ) { 750 final int st = caseTmp.indexOf( ':' , adrs+1 ); // 最初のコロンの位置。元値:新値 の 新値 の取出 751 final int ed = caseTmp.indexOf( ' ' , st+1 ); // コロンの次から、最初のスペースの位置 752 if( st >= 0 && ed >= 0 ) { 753 rtn = caseTmp.substring( st+1,ed ); // コロンの次から、スペースの前までを切り出す。 754 } 755 } 756 } 757 758 return rtn ; 759 } 760 761 /** 762 * String型の配列から、カンマ(,)で連結されたString を作成します。 763 * これは,配列を表示用に変換する為のものです。 764 * array2line( array, ",", 0 ); と同等です。 765 * 766 * @param array 元の文字列配列(可変長引数) 767 * 768 * @return 一列に変換した文字列(引数がnullの場合は、長さ0の文字列を返す) 769 * @og.rtnNotNull 770 */ 771 public static String array2csv( final String... array ) { 772 return array2line( array, ",", 0 ); 773 } 774 775 /** 776 * String型の配列から、セパレーターで連結されたString を作成します。 777 * これは,配列を表示用に変換する為のものです。 778 * 779 * @param array 元の文字列配列 780 * @param separator 区切り記号 781 * 782 * @return 一列に変換した文字列(引数がnullの場合は、長さ0の文字列を返す) 783 * @og.rtnNotNull 784 */ 785 public static String array2line( final String[] array,final String separator ) { 786 return array2line( array, separator,0 ); 787 } 788 789 /** 790 * String型の配列から、セパレーターで連結されたString を作成します。 791 * これは,配列を表示用に変換する為のものです。 792 * 793 * @param array 元の文字列配列 794 * @param separator 区切り記号 795 * @param start 配列の連結開始アドレス 796 * 797 * @return 一列に変換した文字列(引数がnullの場合は、長さ0の文字列を返す) 798 * @og.rtnNotNull 799 */ 800 public static String array2line( final String[] array,final String separator,final int start ) { 801 if( array == null || array.length <= start ) { return ""; } 802 803 final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 804 805 rtn.append( valueOf( array[start] ) ); 806 for( int i=start+1; i<array.length; i++ ) { 807 rtn.append( separator ); 808 rtn.append( valueOf( array[i] ) ); 809 } 810 return rtn.toString(); 811 } 812 813 /** 814 * Enumerationから、オブジェクト配列データを返します。 815 * これは,Enumerationを表示用に変換する為のものです。 816 * 817 * @param enume 元のEnumeration 818 * 819 * @return オブジェクト配列 820 * @og.rtnNotNull 821 */ 822 public static Object[] enume2Array( final Enumeration<?> enume ) { // 4.3.3.6 (2008/11/15) Generics警告対応 823 if( enume == null || ! enume.hasMoreElements() ) { return new Object[0]; } 824 825 final ArrayList<Object> obj = new ArrayList<>(); 826 827 while( enume.hasMoreElements() ) { 828 obj.add( enume.nextElement() ); 829 } 830 return obj.toArray(); 831 } 832 833 /** 834 * Enumerationから、オブジェクト配列データを返します。 835 * これは,Enumerationを表示用に変換する為のものです。 836 * 837 * @param enume 元のEnumeration 838 * @param objs - 配列が十分な大きさを持つ場合は、Vector の要素が格納される配列。 839 * そうでない場合は、要素を格納するために同じ実行時の型の新しい配列が割り当てられる 840 * @return オブジェクト配列 841 */ 842 public static Object[] enume2Array( final Enumeration<?> enume,final Object[] objs ) { // 4.3.3.6 (2008/11/15) Generics警告対応 843 if( enume == null || ! enume.hasMoreElements() ) { return objs ; } 844 845 final ArrayList<Object> list = new ArrayList<>(); 846 847 while( enume.hasMoreElements() ) { 848 list.add( enume.nextElement() ); 849 } 850 return list.toArray( objs ); 851 } 852 853 /** 854 * Iteratorから、セパレーターで連結されたString を作成します。 855 * これは,Enumerationを表示用に変換する為のものです。 856 * 857 * @param ite 元のIterator 858 * @param separator 区切り記号 859 * 860 * @return 一列に変換した文字列 861 * @og.rtnNotNull 862 */ 863 public static String iterator2line( final Iterator<?> ite,final String separator ) { 864 if( ite == null || ! ite.hasNext() ) { return ""; } 865 866 final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 867 868 rtn.append( valueOf( ite.next() ) ); 869 while( ite.hasNext() ) { 870 rtn.append( separator ); 871 rtn.append( valueOf( ite.next() ) ); 872 } 873 return rtn.toString(); 874 } 875 876 /** 877 * カンマ(,)で連結された String を、配列に分解して、その値を返します。 878 * これは,たとえば、AAA,BBB,CCC などのリソースデータを受けてから配列に入れ直して、 879 * メニューなりリストを作成するのに便利です。 880 * 要素が空の場合は、必ずカンマの間にスペースを入れて記述してください。 881 * 分割後の文字列の前後のスペースは、削除されます。 882 * 883 * @param csvData 元のデータ 884 * 885 * @return 文字列配列(引数がnull、ゼロ文字列の場合は、サイズ0の配列を返す) 886 * @og.rtnNotNull 887 */ 888 public static String[] csv2Array( final String csvData ) { 889 return csv2Array( csvData, ',', 0 ); 890 } 891 892 /** 893 * 区切り文字で連結された String を、配列に分解して、その値を返します。 894 * これは,たとえば、AAA,BBB,CCC などのリソースデータを受けてから配列に入れ直して、 895 * メニューなりリストを作成するのに便利です。 896 * 連続した区切り文字は、1文字に分割します。 897 * 分割後の文字列の前後のスペースは、削除されます。 898 * 899 * @param csvData 元のデータ 900 * @param separator 区切り文字 901 * 902 * @return 文字列配列(引数がnull、ゼロ文字列の場合は、サイズ0の配列を返す) 903 * @og.rtnNotNull 904 */ 905 public static String[] csv2Array( final String csvData,final char separator ) { 906 return csv2Array( csvData,separator,0 ); 907 } 908 909 /** 910 * 区切り文字で連結された String を、配列に分解して、その値を返します。 911 * これは,たとえば、AAA,BBB,CCC などのリソースデータを受けてから配列に入れ直して、 912 * メニューなりリストを作成するのに便利です。 913 * 連続した区切り文字は、1文字に分割します。 914 * 分割後の文字列の前後のスペースは、削除されます。 915 * 第3の引数は、リターンする配列の個数を指定します。 916 * len=0 だけは特別で、分解したデータの個数分の配列を作成します。指定の長さが短い場合は、 917 * そこまで分のみ取り込みます。指定の長さが長い場合は、余分に配列を作成します。 918 * データがNULLや、ゼロ文字列の場合は、長さゼロの配列を返します。 919 * セットされる値は、"" です。 920 * 921 * @og.rev 3.8.5.1 (2006/05/08) 設定配列の数を指定できるように変更 922 * @og.rev 3.8.8.2 (2007/01/26) 分割後の値の前後のスペースは削除します。 923 * @og.rev 6.4.5.1 (2016/04/28) CSVTokenizer のインターフェースを、Iterator に変更。 924 * @og.rev 6.8.5.0 (2018/01/09) 引数lenを最大配列長として処理します。 925 * 926 * @param csvData 元のデータ 927 * @param separator 区切り文字 928 * @param len 指定の最大長さの配列で返します(-1の場合は、オリジナルの長さの配列か、長さゼロの配列)。 929 * 930 * @return 文字列配列(引数がnull、ゼロ文字列の場合は、サイズ(len)の配列を返す) 931 * @og.rtnNotNull 932 */ 933 public static String[] csv2Array( final String csvData,final char separator, final int len ) { 934// if( csvData == null || csvData.isEmpty() ) { 935 if( isEmpty( csvData ) ) { // 6.9.2.1 (2018/03/12) isEmpty 置き換え 936 final String[] rtn = new String[len] ; 937 Arrays.fill( rtn,"" ); 938 return rtn; 939 } 940 941 final CSVTokenizer token = new CSVTokenizer( csvData,separator ); 942 943 final int count = len > 0 ? len : token.countTokens() ; 944 945 final String[] rtn = new String[count]; 946 int i = 0; 947 for( ; i<count && token.hasNext() ; i++ ) { 948 rtn[i] = token.next().trim(); // 3.8.8.2 (2007/01/26) 949 } 950 for( ; i<count; i++ ) { 951 rtn[i] = "" ; 952 } 953 954 return rtn; 955 956 } 957 958 /** 959 * 区切り文字で連結された String を、配列に分解して、その値を返します。 960 * これは,#csv2Array( String,char,int ) メソッドで、分割時のデータが 961 * ゼロ文字列の場合に、セットする初期値です。 962 * 元のデータがnull、ゼロ文字列の場合は、defVal がセットされた サイズlenの配列を返します。 963 * 964 * データ数が、指定の len より少ない場合、先のメソッドでは、ゼロ文字列を追加していましたが、 965 * ここでは、初期値の defVal をセットします。 966 * また、分解後、trim() されたデータが、ゼロ文字列の場合も、defVal をセットします。 967 * 968 * @og.rev 6.8.5.0 (2018/01/09) CSVTokenizer のインターフェースを、Iterator に変更。 969 * 970 * @param csvData 元のデータ 971 * @param separator 区切り文字 972 * @param len 指定の長さの配列で返します。 973 * @param defVal 分割したデータが、ゼロ文字列の場合の初期値 974 * 975 * @return 文字列配列(引数がnull、ゼロ文字列の場合は、サイズ0の配列を返す) 976 * @og.rtnNotNull 977 */ 978 public static String[] csv2Array( final String csvData,final char separator, final int len , final String defVal ) { 979 // 処理の中で対応しても良いが、オリジナルを尊重しておきます。 980 final String[] rtn = csv2Array( csvData,separator,len ); 981 982 for( int i=0; i<rtn.length; i++ ) { 983 if( rtn[i].isEmpty() ) { rtn[i] = defVal ; } 984 } 985 986 return rtn; 987 988 } 989 990 /** 991 * 区切り文字で連結された String を、配列に分解して、その値を返します。 992 * これは,たとえば、AAA,BBB,CCC などのリソースデータを受けてから配列に入れ直して、 993 * メニューなりリストを作成するのに便利です。 994 * csv2Array と異なり、連続した区切り文字は、分割せずにトークンのみ切り出します。 995 * トークンは、カンマ(,)のみで区切り、その後 trim() により 996 * 前後のスペースを削除します。 997 * 998 * @param csvData 元のデータ 999 * 1000 * @return 文字列配列 1001 * @og.rtnNotNull 1002 */ 1003 public static String[] csv2ArrayOnly( final String csvData ) { 1004// if( csvData == null || csvData.isEmpty() ) { return new String[0] ; } 1005 if( isEmpty( csvData ) ) { return new String[0]; } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1006 1007 final StringTokenizer token = new StringTokenizer( csvData,"," ); 1008 1009 final ArrayList<String> list = new ArrayList<>(); 1010 while( token.hasMoreTokens() ) { 1011 final String temp = token.nextToken().trim(); 1012 if( temp.length() > 0 ) { list.add( temp ); } 1013 } 1014 1015 return list.toArray( new String[list.size()] ); 1016 } 1017 1018 /** 1019 * カンマ(,)、ハイフン(-)で連結された String を、配列に分解して、その値を返す処理のスペシャル版です。 1020 * 0,1,3,5-8,10-* などの数字文字列から、必要な数字をピックアップした数字配列を返します。 1021 * 引数の maxNo は、"*" が指定された場合の、最大の数値です。 1022 * よって、"*" は、単独(1文字)では、0-maxNo を表し、N-* では、N-maxNo を意味します。 1023 * CSV形式で指定される値は、基本的に数字で、重複(1,1,2,2)、逆転(3,2,1)で指定できます。 1024 * 5-3 と指定した場合は、5,4,3 に分解されます。逆順に登録されます。 1025 * 重複削除、昇順並べ替え等が、必要な場合は、取得後の配列を操作してください。 1026 * 1027 * @og.rev 5.5.7.2 (2012/10/09) 新規追加 1028 * @og.rev 6.2.6.0 (2015/06/19) アルファベットの対応を廃止し、数字配列のみサポートします。 1029 * 1030 * @param csvData 0,1,3,5-8,10-* などのCSV-ハイフン文字列 1031 * @param maxNo "*" が指定された場合の、最大数 1032 * @return 数字配列(引数がnull、ゼロ文字列の場合は、サイズ0の配列を返す) 1033 * @og.rtnNotNull 1034 */ 1035 public static Integer[] csv2ArrayExt( final String csvData , final int maxNo ) { 1036// if( csvData == null || csvData.isEmpty() ) { return new Integer[0] ; } 1037 if( isEmpty( csvData ) ) { return new Integer[0]; } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1038 1039 String strData = csvData.replace( "-*" , "-" + maxNo ); // まず、N-* 形式を、N-maxNo に変換します。 1040 strData = strData.replace( "*" , "0-" + maxNo ); // その後、"*" 単独(1文字)を、0-maxNo に変換します。 1041 1042 final ArrayList<Integer> noList = new ArrayList<>(); 1043 1044 final String[] nos = strData.split( "," ); // カンマで分解。N , N-M , N-* のどれか 1045 for( int i=0; i<nos.length; i++ ) { 1046 final String sno = nos[i] ; 1047 final int hai = sno.indexOf( '-' ); 1048 // ハイフンが含まれているときは前後に分解して、間を埋める 1049 if( hai > 0 ) { 1050 int ch1 = Integer.parseInt( sno.substring( 0,hai ) ); // 先頭からハイフンまで 1051 final int ch2 = Integer.parseInt( sno.substring( hai+1 ) ); // ハイフンから最後まで 1052 if( ch1 < ch2 ) { while( ch1 <= ch2 ) { noList.add( ch1++ ); } } 1053 else { while( ch1 >= ch2 ) { noList.add( ch1-- ); } } 1054 1055 // また、一文字だけの場合は、アルファベット(a-z,A-Zなど)も指定する事が可能です。 1056 // アルファベットの場合は、"*" は指定できません。 1057 // final String st1 = sno.substring( 0,hai ); // 先頭からハイフンまで 1058 // final String st2 = sno.substring( hai+1 ); // ハイフンから最後まで 1059 // if( st1.length() == 1 && st2.length() == 1 ) { // ともに1文字の場合は、char化して処理。(英数字処理) 1060 // char ch1 = st1.charAt(0); 1061 // final char ch2 = st2.charAt(0); 1062 // if( ch1 < ch2 ) { while( ch1 <= ch2 ) { noList.add( String.valueOf(ch1++ ) ); } } 1063 // else { while( ch1 >= ch2 ) { noList.add( String.valueOf(ch1--) ); } } 1064 // } 1065 // else { 1066 // int ch1 = Integer.parseInt( st1 ); 1067 // final int ch2 = Integer.parseInt( st2 ); 1068 // if( ch1 < ch2 ) { while( ch1 <= ch2 ) { noList.add( String.valueOf(ch1++ ) ); } } 1069 // else { while( ch1 >= ch2 ) { noList.add( String.valueOf(ch1--) ); } } 1070 // } 1071 } 1072 else { 1073 noList.add( Integer.valueOf( sno ) ); 1074 } 1075 } 1076 return noList.toArray( new Integer[noList.size()] ) ; 1077 } 1078 1079 /** 1080 * Object 引数の文字列表現を返します。 1081 * これは,String.valueOf とほぼ同じ動作をしますが、引数が null の場合に、 1082 * "null" という文字列を返すのではなく、なにもない文字列 "" を返します。 1083 * 1084 * @param obj 文字列表現すべき元のオブジェクト 1085 * 1086 * @return 引数が null の場合は、"" に等しい文字列。そうでない場合は、obj.toString() の値 1087 * @og.rtnNotNull 1088 */ 1089 public static String valueOf( final Object obj ) { 1090 // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method 1091 return obj == null ? "" : obj.toString(); 1092 } 1093 1094 /** 1095 * HTML上のエスケープ文字を変換します。 1096 * 1097 * HTMLで表示する場合にきちんとエスケープ文字に変換しておかないと 1098 * Script を実行されたり、不要なHTMLコマンドを潜り込まされたりするため、 1099 * セキュリティーホールになる可能性があるので、注意してください。 1100 * 1101 * @og.rev 5.8.2.2 (2014/12/19) アポストロフィの対応 1102 * @og.rev 6.2.2.3 (2015/04/10) htmlフィルターに、BR→改行処理機能を追加。互換性の為のメソッド。 1103 * 1104 * @param input HTMLエスケープ前の文字列 1105 * 1106 * @return エスケープ文字に変換後の文字列 1107 * @og.rtnNotNull 1108 */ 1109 public static String htmlFilter( final String input ) { 1110 return htmlFilter( input , false ); 1111 } 1112 1113 /** 1114 * HTML上のエスケープ文字を変換します。 1115 * 1116 * HTMLで表示する場合にきちんとエスケープ文字に変換しておかないと 1117 * Script を実行されたり、不要なHTMLコマンドを潜り込まされたりするため、 1118 * セキュリティーホールになる可能性があるので、注意してください。 1119 * 1120 * 引数のフラグは、BR→改行コード の変換処理を行うかどうかを指定します。 1121 * true が、変換処理を行うです。 1122 * titleなどのTips表示する場合、改行は、「\n(改行コード)」で行います。 1123 * (HTMLで取り扱うので、&#13;&#10; の方が良いかもしれない。 1124 * その場合は、エスケープ処理と順番を入れ替えないと、そのまま表示されてしまう。) 1125 * 一方、タグ等で改行を行うには、<BR/> で改行を指定します。 1126 * 改行については、「\n」文字列を指定する事で統一します。 1127 * 1128 * @og.rev 5.8.2.2 (2014/12/19) アポストロフィの対応 1129 * @og.rev 6.2.2.3 (2015/04/10) htmlフィルターに、BR→改行処理機能を追加。 1130 * @og.rev 6.2.5.0 (2015/06/05) htmlフィルターで、BR→改行処理が、引数間違いの為うまくできていなかった。 1131 * 1132 * @param input HTMLエスケープ前の文字列 1133 * @param flag [true:BR変換する/false:BR変換しない] 1134 * 1135 * @return エスケープ文字に変換後の文字列 1136 * @og.rtnNotNull 1137 */ 1138 public static String htmlFilter( final String input , final boolean flag ) { 1139// if( input == null || input.isEmpty() ) { return ""; } 1140 if( isEmpty( input ) ) { return ""; } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1141 1142 String temp = input ; 1143 if( flag ) { 1144 temp = temp.replaceAll( "<[bB][rR][\\s/]*>" , "\n" ); // <br/> を置き換える。 1145 temp = temp.replaceAll( "\\\\n" , "\n" ); //「\n」という文字列を置き換える。 1146 } 1147 1148 final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 1149 char ch; 1150 for( int i=0; i<temp.length(); i++ ) { 1151 ch = temp.charAt(i); // 6.2.5.0 (2015/06/05) バグ 1152 switch( ch ) { 1153 case '<' : rtn.append("<"); break; 1154 case '>' : rtn.append(">"); break; 1155 case '"' : rtn.append("""); break; 1156 case '\'' : rtn.append("'"); break; // 5.8.2.2 (2014/12/19) アポストロフィの対応 1157 case '&' : rtn.append("&"); break; 1158 default : rtn.append(ch); break; // 6.0.2.5 (2014/10/31) break追記 1159 } 1160 } 1161 return rtn.toString() ; 1162 } 1163 1164 /** 1165 * 「\n」という文字列を、BRタグに変換します。 1166 * 1167 * titleなどのTips表示する場合、改行は、「\n」で行います。 1168 * 一方、タグ等で改行を行うには、<BR/> で改行を指定します。 1169 * BRタグは、リソーステーブル等に書き込みにくい為、また、本当の改行コードも 1170 * 書き込みにくい為、改行については、「\n」文字列を指定する事で対応できるように 1171 * 統一します。 1172 * 1173 * @og.rev 6.2.2.3 (2015/04/10) 「\n」という文字列を、BRタグに変換する処理を追加 1174 * 1175 * @param input BR,\n変換前の文字列 1176 * 1177 * @return 変換後の文字列 1178 * @og.rtnNotNull 1179 */ 1180 public static String yenN2br( final String input ) { 1181 // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method 1182// return input == null || input.isEmpty() ? "" : input.replaceAll( "\\\\n" , "<br/>" ); // \n ではなく、「\n」という文字列と変換 1183 return isEmpty( input ) ? "" : input.replaceAll( "\\\\n" , "<br/>" ); // \n ではなく、「\n」という文字列と変換 // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1184 } 1185 1186 /** 1187 * JavaScript 等の引数でのクオート文字をASCII変換します。 1188 * 1189 * JavaScript の引数の値に、ダブルクオート(")、シングルクオート(')が 1190 * 含まれると、文字列を表す為に前後に指定しているクオートと混乱し、 1191 * データを表現できないケースがあります。その場合には、クオート文字を 1192 * ASCII文字に置き換える事で、指定の文字を渡すことが可能になります。 1193 * ここでは、引数文字列に、ダブルクオート(")、シングルクオート(')が、 1194 * 含まれると、それぞれ、ASCII コード(¥x22、¥x27)に置き換えます。 1195 * なお、null は、ゼロ文字列に変換して返します。 1196 * 1197 * @param input 入力文字列 1198 * 1199 * @return クオート文字をASCII文字に置き換えた文字列 1200 * @og.rtnNotNull 1201 */ 1202 public static String quoteFilter( final String input ) { 1203// if( input == null || input.isEmpty() ) { return ""; } 1204 if( isEmpty( input ) ) { return ""; } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1205 if( input.indexOf( '\'' ) < 0 && input.indexOf( '"' ) < 0 ) { return input; } 1206 1207 final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 1208 char ch; 1209 for( int i=0; i<input.length(); i++ ) { 1210 ch = input.charAt(i); 1211 switch( ch ) { 1212 case '"' : rtn.append( "\\x22" ); break; 1213 case '\'' : rtn.append( "\\x27" ); break; 1214 default : rtn.append( ch ); break; // 6.0.2.5 (2014/10/31) break追記 1215 } 1216 } 1217 return rtn.toString() ; 1218 } 1219 1220 /** 1221 * JSON形式で出力する場合のためのエスケープ処理です。 1222 * 1223 * @og.rev 5.9.6.4(2016/03/25) 新規作成 1224 * 1225 * @param input XMLエスケープ前の文字列 1226 * 1227 * @return エスケープ文字に変換後の文字列 1228 */ 1229 public static String jsonFilter( final String input ) { 1230// if( input == null || input.length() == 0 ) { return ""; } 1231 if( isEmpty( input ) ) { return ""; } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1232 1233 final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 1234 for(int i=0; i<input.length(); i++) { 1235 final char ch = input.charAt(i); 1236 switch( ch ) { 1237 case '"' : rtn.append("\\\""); break; 1238 case '\\' : rtn.append("\\\\"); break; 1239 case '/' : rtn.append("\\/"); break; 1240 case '\b' : rtn.append("\\b"); break; 1241 case '\f' : rtn.append("\\f"); break; 1242 case '\n' : rtn.append("\\n"); break; 1243 case '\r' : rtn.append("\\r"); break; 1244 case '\t' : rtn.append("\\t"); break; 1245 default : rtn.append(ch); break; 1246 } 1247 } 1248 return rtn.toString() ; 1249 } 1250 1251 /** 1252 * 所定のキャラクタコードを取り除いた文字列を作成します。 1253 * 1254 * 実現したい機能は、String#replace( 'x','' ) 的な表現です。 1255 * つまり、指定のキャラクタを取り除きたいのですが、上記コマンドでは、 1256 * コンパイル時にエラーが発生します。 1257 * 取り除きたいキャラクタコードが存在しない場合は、指定の文字列を 1258 * そのまま返します。 1259 * 1260 * @param value 処理対象の文字列 1261 * @param ch 取り除きたいキャラクタ 1262 * 1263 * @return 処理後の文字列 1264 */ 1265 public static String deleteChar( final String value,final char ch ) { 1266 if( value == null || value.indexOf( ch ) < 0 ) { return value; } 1267 char[] chs = value.toCharArray() ; 1268 int j=0; 1269 for( int i=0;i<chs.length; i++ ) { 1270 // 6.3.9.0 (2015/11/06) true/false を変更します。 1271 if( chs[i] != ch ) { chs[j++] = chs[i]; } 1272 } 1273 return String.valueOf( chs,0,j ); 1274 } 1275 1276 /** 1277 * 文字列に含まれる、特定の文字の個数をカウントして返します。 1278 * 1279 * @og.rev 5.2.0.0 (2010/09/01) 1280 * 1281 * @param value 処理対象の文字列 1282 * @param ch カウントする文字 1283 * 1284 * @return カウント数 1285 */ 1286 public static int countChar( final String value,final char ch ) { 1287 if( value == null || value.indexOf( ch ) < 0 ) { return 0; } 1288 final char[] chs = value.toCharArray() ; 1289 int cnt=0; 1290 for( int i=0;i<chs.length; i++ ) { 1291 if( chs[i] == ch ) { cnt++; } 1292 } 1293 return cnt; 1294 } 1295 1296 /** 1297 * CODE39 の 文字列を作成します。 1298 * 1299 * CODE39 は、『0~9, A~Z,-,・, ,$,/,+,%』のコードが使用できる 1300 * バーコードの体系です。通常 * で始まり * で終了します。 1301 * また、チェックデジット に、モジュラス43 が使われます。 1302 * ここでは、指定の文字列の前後に、* を付与し、必要であれば 1303 * チェックデジットも付与します。 1304 * 指定の入力文字列には、* を付けないでください。 1305 * 1306 * @param value 処理対象の文字列 1307 * @param checkDigit チェックデジットの付与(true:付ける/false:付けない) 1308 * 1309 * @return 処理後の文字列 1310 * @og.rtnNotNull 1311 */ 1312 public static String code39( final String value,final boolean checkDigit ) { 1313 final String rtn = ( value == null ) ? "" : value ; 1314 if( ! checkDigit ) { return "*" + rtn + "*"; } 1315 1316 int kei = 0; 1317 int cd; 1318 for( int i=0; i<rtn.length(); i++ ) { 1319 cd = MODULUS_43.indexOf( rtn.charAt(i) ); 1320 if( cd < 0 ) { 1321 final String errMsg = "指定の文字中に、CODE39 規定外文字が使用されています。[" + rtn.charAt(i) + "]" ; 1322 throw new OgRuntimeException( errMsg ); 1323 } 1324 kei += cd ; 1325 } 1326 final char digit = MODULUS_43.charAt( kei % 43 ); 1327 1328 return "*" + rtn + digit + "*" ; 1329 } 1330 1331 /** 1332 * 引数 inStr が、null または、ゼロ文字列の場合は、デフォルト値 def を返します。 1333 * もちろん、inStr も def も null の場合は、null を返します。 1334 * 1335 * ※ 影響範囲が大きいので、空白文字の判定は入れません。 1336 * 1337 * @param inStr 基準となる文字列 1338 * @param def デフォルト文字列 1339 * 1340 * @return 引数 inStr が、null または、ゼロ文字列の場合は、デフォルト値を返す。 1341 */ 1342 public static String nval( final String inStr,final String def ) { 1343// return inStr == null || inStr.isEmpty() ? def : inStr ; 1344 return isEmpty( inStr ) ? def : inStr ; // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1345 } 1346 1347 /** 1348 * 引数 inStr が、null または、ゼロ文字列、空白文字列の場合は、デフォルト値 def を返します。 1349 * 1350 * 数値変換なので、空白文字列の場合も、デフォルト値を使用します。 1351 * 1352 * @param inStr 基準となる文字列 1353 * @param def デフォルト数字 1354 * 1355 * @return 引数 inStr を変換した数字(int)。変換できない場合は デフォルト値 def 1356 */ 1357 public static int nval( final String inStr,final int def ) { 1358// return inStr == null || inStr.isEmpty() ? def : Integer.parseInt( inStr ) ; 1359 return isNull( inStr ) ? def : Integer.parseInt( inStr ) ; // 6.9.2.1 (2018/03/12) isNull 置き換え 1360 } 1361 1362 /** 1363 * 引数 inStr が、null または、ゼロ文字列、空白文字列の場合は、デフォルト値 def を返します。 1364 * 1365 * @param inStr 基準となる文字列 1366 * @param def デフォルト数字 1367 * 1368 * @return 引数 inStr を変換した数字(long)。変換できない場合は デフォルト値 def 1369 */ 1370 public static long nval( final String inStr,final long def ) { 1371// return inStr == null || inStr.isEmpty() ? def : Long.parseLong( inStr ) ; 1372 return isNull( inStr ) ? def : Long.parseLong( inStr ) ; // 6.9.2.1 (2018/03/12) isNull 置き換え 1373 } 1374 1375 /** 1376 * 引数 inStr が、null または、ゼロ文字列、空白文字列の場合は、デフォルト値 def を返します。 1377 * 1378 * @og.rev 6.9.2.1 (2018/03/12) 新規追加 1379 * 1380 * @param inStr 基準となる文字列 1381 * @param def デフォルト数字 1382 * 1383 * @return 引数 inStr を変換した数字(double)。変換できない場合は デフォルト値 def 1384 */ 1385 public static double nval( final String inStr,final double def ) { 1386 return isNull( inStr ) ? def : Double.parseDouble( inStr ) ; // 6.9.2.1 (2018/03/12) isNull 置き換え 1387 } 1388 1389 /** 1390 * 引数 inStr が、null または、ゼロ文字列、空白文字列の場合は、デフォルト値 def を返します。 1391 * 通常は、"true" または、 "TRUE" 文字列を、論理値の true に変換します。 1392 * ただし、文字列長が 1文字の場合のみ、"0" 以外を true に変換します。 1393 * 1394 * @og.rev 6.8.0.1 (2017/06/30) つづり間違いに対応するため、厳密にチェックします。 1395 * 1396 * @param inStr 基準となる文字列 1397 * @param def デフォルト論理値 1398 * 1399 * @return 引数 inStr を変換した論理値。変換できない場合は デフォルト値 def 1400 */ 1401 public static boolean nval( final String inStr,final boolean def ) { 1402 // 6.8.0.1 (2017/06/30) つづり間違いに対応するため、厳密にチェックします。 1403 if( inStr != null && inStr.length() > 1 && !"true".equalsIgnoreCase( inStr ) && !"false".equalsIgnoreCase( inStr ) ) { 1404 final String errMsg = "指定の文字列には、true か、false を指定してください。[" + inStr + "]" ; 1405 throw new OgRuntimeException( errMsg ); 1406 } 1407 1408 // 6.4.1.1 (2016/01/16) PMD refactoring. 1409// return inStr == null || inStr.isEmpty() 1410 return isNull( inStr ) // 6.9.2.1 (2018/03/12) isNull 置き換え 1411 ? def 1412 : inStr.length() == 1 1413 ? ! "0".equals( inStr ) 1414 : "true".equalsIgnoreCase( inStr ) ; 1415 1416 } 1417 1418 /** 1419 * 引数 inStr が、null、"_"、ゼロ文字列、空白文字列の場合は、デフォルト値 def を返します。 1420 * 1421 * さらに、メモリ領域を節約する為、intern() の結果を返します。 1422 * ※ #nval(String) との整合性を取るため、空白文字の判定は入れません。 1423 * 1424 * @og.rev 5.2.2.0 (2010/11/01) "_" の取り扱い変更 1425 * 1426 * @param inStr 基準となる文字列 1427 * @param def デフォルト文字列 1428 * 1429 * @return null、ゼロ文字列、"_"の場合は、デフォルト文字列を、そうでなければ、入力文字を返す。 1430 */ 1431 public static String nval2( final String inStr,final String def ) { 1432// return inStr == null || inStr.isEmpty() || "_".equals( inStr ) ? def : inStr.intern() ; 1433 return isEmpty( inStr ) || "_".equals( inStr ) ? def : inStr.intern() ; // 6.9.2.1 (2018/03/12) isNull 置き換え 1434 } 1435 1436 /** 1437 * 引数 inStr が、null または、ゼロ文字列、空白文字列の場合は、デフォルト値 def を返します。 1438 * ただし、NULL代替文字(_)は デフォルト値 def2 に置き換えます。 1439 * 1440 * さらに、メモリ領域を節約する為、intern() の結果を返します。 1441 * ※ #nval(String) との整合性を取るため、空白文字の判定は入れません。 1442 * 1443 * @og.rev 5.2.2.0 (2010/11/01) "_" の取り扱い変更 1444 * 1445 * @param inStr 基準となる文字列 1446 * @param def デフォルト文字列 1447 * @param def2 NULL代替文字(_)の場合のデフォルト文字列 1448 * 1449 * @return null、ゼロ文字列の場合は、def1文字列を、"_"の場合は、def2文字列を、そうでなければ、入力文字を返す。 1450 */ 1451 public static String nval2( final String inStr,final String def,final String def2 ) { 1452// return inStr == null || inStr.isEmpty() ? def : "_".equals( inStr ) ? def2 : inStr.intern() ; 1453 return isEmpty( inStr ) ? def : "_".equals( inStr ) ? def2 : inStr.intern() ; // 6.9.2.1 (2018/03/12) isNull 置き換え 1454 } 1455 1456 /** 1457 * 指定のCharSequence同士を連結させます。 1458 * CharSequenceが、 null の場合は、連結しません。 1459 * すべてが null の場合は、ゼロ文字列が返されます。 1460 * 1461 * ここでは、空白文字やタブ、改行コードも、指定されていれば、連結されます。 1462 * 1463 * @og.rev 6.0.2.4 (2014/10/17) 新規追加 1464 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 1465 * 1466 * @param strs... 可変長CharSequence 1467 * 1468 * @return null以外の文字列が連結された状態 1469 * @see #join( String,CharSequence... ) 1470 * @og.rtnNotNull 1471 */ 1472 public static String nvalAdd( final CharSequence... strs ) { 1473 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); 1474 1475 for( final CharSequence str : strs ) { 1476 if( str != null ) { buf.append( str ); } 1477 } 1478 1479 return buf.toString(); 1480 } 1481 1482 /** 1483 * 最初の null(または、ゼロ文字列) 以外の値を返します。 1484 * nval の 変数が、無制限版です。 1485 * すべてが null(または、ゼロ文字列) の場合は、null が返されます。 1486 * 空白文字、タブや改行コードが来ても、返されます。 1487 * 1488 * @og.rev 6.0.2.4 (2014/10/17) 新規追加 1489 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 1490 * 1491 * @param strs... 可変長CharSequence 1492 * 1493 * @return 最初に現れた、null以外のCharSequenceを、Stringに変換したもの 1494 */ 1495// public static CharSequence coalesce( final CharSequence... strs ) { 1496 public static String coalesce( final CharSequence... strs ) { 1497 for( final CharSequence str : strs ) { 1498// if( str != null && str.length() > 0 ) { return str.toString(); } 1499 if( ! isEmpty( str ) ) { return str.toString(); } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1500 } 1501 1502 return null; 1503 } 1504 1505 /** 1506 * キーワードに対して、可変長引数の文字列が、含まれているかどうかを判定します。 1507 * キーワードが、null でなく、比較先の文字列が、ひとつでも含まれると、true が返ります。 1508 * 大文字小文字は、厳密に判定されます。 1509 * 1510 * key != null && ( key.contains( val1 ) || key.contains( val2 ) ・・・ ) 1511 * の結果と同じです。 1512 * 1513 * @og.rev 6.4.4.2 (2016/04/01) contains 判定を行う新しいメソッドを新規追加します。 1514 * 1515 * @param key キーワード 1516 * @param vals... 比較先の可変長文字列(OR判定) 1517 * 1518 * @return キーワード文字列の中に、比較先文字列がひとつでも含まれると、true 1519 */ 1520 public static boolean contains( final String key , final String... vals ) { 1521 if( key != null && vals != null ) { 1522 for( final String val : vals ) { 1523 if( val != null && key.contains( val ) ) { return true; } // ひとつでも、contains があれば、true 1524 } 1525 } 1526 return false; 1527 } 1528 1529 /** 1530 * 連結文字列を、使用して、可変長引数のCharSequenceを連結して返します。 1531 * 連結文字列が、null の場合は、CharSequenceをそのまま連結していきます。 1532 * 連結する文字列が null の場合は、連結しません。 1533 * 連結文字列は、一番最後は出力されません。 1534 * 処理できない場合は、長さゼロの文字列を返します。 1535 * 1536 * @og.rev 6.4.4.2 (2016/04/01) join 処理を行う新しいメソッドを新規追加します。 1537 * @og.rev 6.4.5.0 (2016/04/08) 引数を可変長CharSequenceに変更 1538 * 1539 * @param delimiter 連結文字列 1540 * @param vals... 連結するCharSequence 1541 * 1542 * @return 連結された結果の文字列 1543 * @see #nvalAdd( CharSequence... ) 1544 * @og.rtnNotNull 1545 */ 1546 public static String join( final String delimiter , final CharSequence... vals ) { 1547 if( delimiter == null ) { return nvalAdd( vals ); } 1548 1549 final StringJoiner sjo = new StringJoiner( delimiter ); 1550 for( final CharSequence val : vals ) { 1551// if( val != null && val.length() > 0 ) { sjo.add( val ); } 1552 if( ! isEmpty( val ) ) { sjo.add( val ); } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1553 } 1554 1555 return sjo.toString(); 1556 } 1557 1558 /** 1559 * 引数 vals が、null または、ゼロ文字列の場合は、true を返します。 1560 * それ以外は false を返します。 1561 * isNull との違いは、スペースやタブ、改行だけの文字列は、null と判定しません。 1562 * 文字列置換などで、スペースやタブなどと置換する場合、null やゼロ文字列では困る場合などの 1563 * 判定で使用します。 1564 * 1565 * @og.rev 6.9.2.1 (2018/03/12) 新規追加 1566 * 1567 * @param vals 判定するCharSequence(可変長引数) 1568 * 1569 * @return NULL文字列関係の場合は、true を、そうでなければ、false を返す。 1570 * @see #isNull( CharSequence... ) 1571 */ 1572 public static boolean isEmpty( final CharSequence... vals ) { 1573 if( vals != null && vals.length > 0 ) { 1574 for( final CharSequence val : vals ) { 1575 if( val == null || val.length()==0 ) { return true; } // val の nullチェック 必要? 1576 } 1577 return false; 1578 } 1579 return true; 1580 } 1581 1582 /** 1583 * 引数 vals が、null または、ゼロ文字列、またはすべて空白文字(スペース、タブ、改行)の場合は、true を返します。 1584 * それ以外は false を返します。 1585 * isNull との違いは、判定前に、trim() 処理を行っているため、スペースやタブ、改行だけの文字列も、null と判定します。 1586 * キーワードとして使用できないケースで、この判定を利用します。 1587 * また、引数は可変長になっており、指定の「どれか」が、成立すれば、true と判定します。 1588 * 処理的には、 val1 == null || val1.trim().length()==0 || val2 == null || val2.trim().length()==0 ・・・ 1589 * 1590 * CharSequence 系の配列自体の null チェックも兼ねています。 1591 * 1592 * 注意は、オールスペースやタブ文字、改行文字も true になります。 1593 * 1594 * @og.rev 6.4.5.0 (2016/04/08) 引数をCharSequenceに変更 1595 * @og.rev 6.9.0.0 (2018/01/31) 引数を可変長引数に変更 1596 * @og.rev 6.9.2.1 (2018/03/12) 新規追加 1597 * 1598 * @param vals 判定するCharSequence(可変長引数) 1599 * 1600 * @return NULL文字列関係の場合は、true を、そうでなければ、false を返す。 1601 * @see #isNotNull( CharSequence... ) 1602 */ 1603 public static boolean isNull( final CharSequence... vals ) { 1604 // 6.9.0.0 (2018/01/31) 引数を可変長引数に変更 1605 if( vals != null && vals.length > 0 ) { 1606 for( final CharSequence val : vals ) { 1607 if( val == null || val.length()==0 ) { return true; } // val の nullチェック 必要? 1608 1609 boolean flag = true; 1610 // String.trim().isEmpty() の高速版 1611 for( int i=0; i<val.length(); i++ ) { 1612 if( !Character.isWhitespace( val.charAt(i) ) ) { // 空白文字でなければ 1613 flag = false; // 小ループを抜ける。 1614 break; 1615 } 1616 } 1617 if( flag ) { return true; } // すべてが空白文字なら、true 1618 } 1619 return false; 1620 } 1621 return true; 1622 } 1623 1624 /** 1625 * 引数 vals が、null または、ゼロ文字列、またはすべて空白文字(スペース、タブ、改行)でない場合は、true を返します。 1626 * 1627 * #isNull( CharSequence... ) の反転です。 1628 * そのため、「すべて」の文字列が、null か、ゼロ文字、空白文字でない場合のみ、true になります。 1629 * isNull の表示上、'!' マークのあるなしは、判別しにくいため、メソッドを用意しています。 1630 * 1631 * @og.rev 6.9.2.1 (2018/03/12) 新規追加 1632 * 1633 * @param vals 判定するCharSequence(可変長引数) 1634 * 1635 * @return NULL文字列関係でない場合は、true を、「どれか」が、NULL文字列関係の場合は、false を返す。 1636 * @see #isNull( CharSequence... ) 1637 */ 1638 public static boolean isNotNull( final CharSequence... vals ) { 1639 return !isNull( vals ); 1640 } 1641 1642 /** 1643 * 浮動小数点数について、カンマ編集を行います。 1644 * 1645 * このメソッドでは、1.23 E12 などの数字は扱いません。通常の 1646 * 数字とピリオドで構成された文字列のみ、変換対象になります。 1647 * (ただし、不正な文字列を与えてもエラーチェックはしていません。) 1648 * minFraction には、小数点部に与える固定値を指定します。入力文字列が 1649 * その桁数より少ない場合は、0埋めします。 1650 * 多い場合は、四捨五入します。 1651 * minFraction が 0 の場合は、小数点は付きません。 1652 * ".12" などの小数点は、必ず先頭に 0 が付きます。 1653 * 入力文字列が null か、ゼロ文字列時は、そのまま入力データを返します。 1654 * 1655 * <pre> 1656 * DecimalFormat format = new DecimalFormat( "#,##0.00########" ); 1657 * double dd = Double.parseDouble( val ); 1658 * return format.format( dd ); 1659 * </pre> 1660 * に対して、minFraction分の小数以下のゼロの指定と、inに ',' が 1661 * 含まれた処理を追加した感じになります。 1662 * 1663 * @og.rev 4.0.0.0 (2007/10/26) 空白のトリム処理を追加 1664 * @og.rev 6.0.4.0 (2014/11/28) 小数点指定が、0 の場合、小数点以下は表示しない 1665 * @og.rev 6.2.0.0 (2015/02/27) 小数点指定の精度に合わせるのと、内部ロジック完全置換 1666 * @og.rev 6.2.0.1 (2015/03/06) 互換性の関係で、nullかゼロ文字列の時は、そのまま、in を返す。 1667 * @og.rev 6.3.6.1 (2015/08/28) throw new OgRuntimeException するのではなく、System.err.println する。 1668 * @og.rev 6.3.8.5 (2015/10/16) ogErrMsgPrint 使用。 1669 * @og.rev 6.4.2.0 (2016/01/29) ogErrMsgPrint メソッドを、ThrowUtil クラスに移動のため、修正 1670 * 1671 * @param inStr 変換元の文字列 1672 * @param minFraction 変換時の小数点以下の固定桁数 1673 * 1674 * @return カンマ編集後の数字型文字列 1675 */ 1676 public static String numberFormat( final String inStr, final int minFraction ) { 1677// if( inStr == null || inStr.isEmpty() ) { return inStr ; } // 6.2.0.1 (2015/03/06) 互換性の関係 1678 if( isNull( inStr ) ) { return inStr ; } // 6.9.2.1 (2018/03/12) isNull 置き換え 1679 1680 String rtn = inStr; 1681 1682 try { 1683 final double dd = StringUtil.parseDouble( rtn ); 1684 1685 if( FMT1.length > minFraction ) { 1686 synchronized( FMT1[minFraction] ) { 1687 rtn = FMT1[minFraction].format( dd ); 1688 } 1689 } 1690 else { 1691 final String fmt = "#,##0." + ZERO.substring( 0,minFraction ); 1692 rtn = new DecimalFormat( fmt ).format( dd ); 1693 } 1694 } 1695 catch( final Throwable th ) { 1696 final String errMsg = "ERROR:" + th.getLocalizedMessage() + CR 1697 + " in=[" + inStr + "] , minFraction=[" + minFraction + "]" ; 1698 // 6.3.8.5 (2015/10/16) ogErrMsgPrint 使用。 1699 System.err.println( ThrowUtil.ogThrowMsg( errMsg,th ) ); // 6.4.2.0 (2016/01/29) 1700 } 1701 1702 return rtn; 1703 } 1704 1705 /** 1706 * 識別id に応じた オブジェクトを作成します。 1707 * 作成するには、デフォルトコンストラクターが必要です。 1708 * 1709 * @param cls 作成するクラスのフルネーム 1710 * 1711 * @return オブジェクト 1712 * @og.rtnNotNull 1713 * @throws RuntimeException 何らかのエラーが発生した場合 1714 */ 1715 public static Object newInstance( final String cls ) { 1716 return newInstance( cls,Thread.currentThread().getContextClassLoader() ); 1717 } 1718 1719 /** 1720 * 指定されたクラスローダを使って、識別id に応じた オブジェクトを作成します。 1721 * 作成するには、デフォルトコンストラクターが必要です。 1722 * initialize パラメータは true 相当(それまでに初期化されていない場合だけ初期化)です。 1723 * 1724 * @og.rev 6.4.3.3 (2016/03/04) リフレクション系の例外の共通クラスに置き換えます。 1725 * @og.rev 6.8.2.3 (2017/11/10) java9対応(cls.newInstance() → cls.getDeclaredConstructor().newInstance()) 1726 * 1727 * @param cls 作成するクラスのフルネーム 1728 * @param loader 作成するクラスのクラスローダ 1729 * 1730 * @return オブジェクト 1731 * @og.rtnNotNull 1732 * @throws RuntimeException 何らかのエラーが発生した場合 1733 */ 1734 public static Object newInstance( final String cls,final ClassLoader loader ) { 1735 try { 1736 return Class.forName( cls,true,loader ).getDeclaredConstructor().newInstance(); // 6.8.2.3 (2017/11/10) 1737 } 1738 catch( final NoSuchMethodException | InvocationTargetException ex ) { // 6.8.2.3 (2017/11/10) 1739 final String errMsg = "指定のメソッド(コンストラクタ)が見つかりませんでした。class=[" + cls + "]" + CR 1740 + ex.getMessage(); 1741 throw new OgRuntimeException( errMsg,ex ); 1742 } 1743 catch( final ReflectiveOperationException ex ) { 1744 final String errMsg = "Class.forName( String,boolean,ClassLoader ).newInstance() 処理に失敗しました class=[" + cls + "]" + CR 1745 + ex.getMessage() ; 1746 throw new OgRuntimeException( errMsg,ex ); 1747 } 1748 } 1749 1750 /** 1751 * 指定のURL文字列同士を連結させます。 1752 * そのとき、後方URLが、絶対パスの場合は、連結せず 後方URLを返します。 1753 * 第2引数以降は、絶対パス判定をせず直前のURLの末尾判定のみで連結します。 1754 * 1755 * 絶対パスかどうかは、通常のファイル属性と同様に、先頭が、'/' (UNIX)または、 1756 * 2文字目が、":" (Windows)の場合、または、先頭が "\" (ネットワークパス)で 1757 * 始まる場合で判断します。 1758 * 連結時に、前方URLの末尾に "/" を付加します。 1759 * 1760 * 処理の互換性確保のため、第3引数の可変長引数を追加しています。 1761 * 1762 * @og.rev 5.0.0.1 (2009/08/15) 不要なオブジェクトの生成を抑制する。 1763 * @og.rev 5.6.5.2 (2013/06/21) 第3引数を可変長引数に変更 1764 * @og.rev 6.4.5.0 (2016/04/08) 引数をCharSequenceに変更 1765 * @og.rev 6.4.7.2 (2016/06/20) 絶対パスの判定を、可変長URLにも適用する。 1766 * 1767 * @param url1 先頭URLCharSequence 1768 * @param urls 後方URL可変長CharSequence(絶対パスの場合は、返り値) 1769 * 1770 * @return URL文字列同士の連結結果 url1 + url2(url2が絶対パスの場合は、url2から連結開始) 1771 * @og.rtnNotNull 1772 */ 1773 public static String urlAppend( final CharSequence url1,final CharSequence... urls ) { 1774 final StringBuilder rtnUrl = new StringBuilder( BUFFER_MIDDLE ); 1775 1776// if( url1 != null && url1.length() > 0 ) { rtnUrl.append( url1 ) ; } 1777 if( isNotNull( url1 ) ) { rtnUrl.append( url1 ) ; } // 6.9.2.1 (2018/03/12) isNotNull 置き換え 1778 1779 // ここからが、追加分 1780 for( final CharSequence url : urls ) { 1781// if( url != null && url.length() > 0 ) { 1782 if( isNotNull( url ) ) { // 6.9.2.1 (2018/03/12) isNotNull 置き換え 1783 if( rtnUrl.length() == 0 || // 戻り値が未設定の場合。 1784 ( url.charAt(0) == '/' ) || // 実ディレクトリが UNIX 1785 ( url.length() > 1 && url.charAt(1) == ':' ) || // 実ディレクトリが Windows 1786 ( url.charAt(0) == '\\' ) ) { // 実ディレクトリが ネットワークパス 1787 rtnUrl.setLength( 0 ); // クリア 1788 rtnUrl.append( url ) ; 1789 } 1790 else { 1791 final char ch = rtnUrl.charAt( rtnUrl.length()-1 ) ; // 必ず、何らかのURLがappend済みのはず。 1792 if( ch == '/' || ch == '\\' ) { 1793 rtnUrl.append( url ) ; 1794 } 1795 else { 1796 rtnUrl.append( '/' ).append( url ) ; // 6.0.2.5 (2014/10/31) char を append する。 1797 } 1798 } 1799 } 1800 } 1801 1802 return rtnUrl.toString() ; 1803 } 1804 1805 /** 1806 * Unicode文字列の値を HTML のエスケープ記号(&#xZZZZ;)に変換します。 1807 * 1808 * SJIS(JA16SJIS) で作成されたデータベースに、(NVARCHAR2)を使用して中国語等を登録するのは 1809 * 非常に複雑でかつ、リスクが大きい処理になります。 1810 * ORACLE殿でも、自信を持っては勧められない機能とのコメントを頂いています。 1811 * そこで、HTMLでのエスケープ文字を使用して、Unicodeを文字列化して登録する為の 1812 * DBType として、新規に作成します。 1813 * ここでは、入力文字を、キャラクタ(char)型に分解し、(&#xZZZZ;)に変換していきます。 1814 * よって、通常に1文字(Shift-JISで2Byte,UTF-8で3Byte)が、8Byteになります。 1815 * この変換された文字列を、HTML上でそのまま取り出すと、元のUnicode文字に戻る為、 1816 * 通常のShift-JISでは、扱えない文字(中国語など)でも表示可能になります。 1817 * ここでは、2バイト文字のみ、変換しています。 1818 * 1819 * @og.rev 6.4.5.0 (2016/04/08) 引数をCharSequenceに変更 1820 * 1821 * @param value 変換前のCharSequence 1822 * 1823 * @return HTMLのエスケープ記号(&#xZZZZ;) 1824 * @og.rtnNotNull 1825 */ 1826 public static String getUnicodeEscape( final CharSequence value ) { 1827// if( value == null || value.length() == 0 ) { return ""; } 1828 if( isEmpty( value ) ) { return ""; } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1829 1830 final StringBuilder rtn = new StringBuilder( value.length() * 4 ); 1831 1832 for( int i=0; i<value.length(); i++ ) { 1833 final char ch = value.charAt(i); 1834 1835 if( ch > 0xff ) { 1836 final String hex = Integer.toHexString( (int)ch ) ; 1837 rtn.append( UTF_STR[hex.length()] ).append( hex ).append( ';' ); // 6.0.2.5 (2014/10/31) char を append する。 1838 } 1839 else { 1840 rtn.append( ch ); 1841 } 1842 } 1843 1844 return rtn.toString(); 1845 } 1846 1847 /** 1848 * HTML のエスケープ記号(&#xZZZZ;)をUnicode文字列に戻します。 1849 * 1850 * HTMLでのエスケープ文字を使用して登録された文字を、Unicodeに戻します。 1851 * (&#xZZZZ;)の8Byteを、もとのキャラクタコードに戻し、合成します。 1852 * ここでは、通常の文字列に混在したエスケープ文字も戻せるようにします。 1853 * 1854 * @og.rev 5.9.5.3 (2016/02/26) 無限ループ対応 1855 * 1856 * @param value HTMLのエスケープ記号(&#xZZZZ;)を含む文字列 1857 * 1858 * @return 通常のUnicode文字列 1859 * @og.rtnNotNull 1860 */ 1861 public static String getReplaceEscape( final String value ) { 1862// if( value == null || value.isEmpty() ) { return ""; } 1863 if( isEmpty( value ) ) { return ""; } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1864 1865 final StringBuilder rtn = new StringBuilder( value ); 1866 1867 int st = rtn.indexOf( "&#" ); 1868 while( st >= 0 ) { 1869 if( st+7 < rtn.length() && rtn.charAt( st+7 ) == ';' ) { 1870 final int ch = Integer.parseInt( rtn.substring( st+3,st+7 ),16 ); 1871 rtn.replace( st,st+8, Character.toString( (char)ch ) ); 1872 } 1873 st = rtn.indexOf( "&#",st + 1 ); // 5.9.5.3 (2016/02/26) 無限ループ対応 1874 } 1875 1876 return rtn.toString(); 1877 } 1878 1879 /** 1880 * 文字列をdoubleに変換します。 1881 * 1882 * これは、Double.parseDouble( value ) と、ほぼ同じ動作を行います。 1883 * 内部的には、引数の カンマ(,) を削除した文字列を、Double.parseDouble( value ) 1884 * に渡します。 1885 * また、引数が、null,ゼロ文字列,'_' の時には、0.0 を返します。 1886 * 1887 * @og.rev 6.3.9.0 (2015/11/06) もう少し判りやすくする。(処理速度は落ちてます。) 1888 * 1889 * @param value doubleに変換する元の文字列 1890 * 1891 * @return 変換後のdouble数値 1892 */ 1893 public static double parseDouble( final String value ) { 1894 double rtn ; 1895 1896// if( value == null || value.isEmpty() || value.equals( "_" ) ) { 1897 if( isNull( value ) || value.equals( "_" ) ) { // 6.9.2.1 (2018/03/12) isNull 置き換え 1898 rtn = 0.0d; 1899 } 1900 else if( value.indexOf( ',' ) < 0 ) { 1901 rtn = Double.parseDouble( value ); 1902 } 1903 else { 1904 // 6.3.9.0 (2015/11/06) もう少し判りやすくする。(処理速度は落ちてます。) 1905 rtn = Double.parseDouble( value.replaceAll( ",","" ) ); 1906 } 1907 1908 return rtn ; 1909 } 1910 1911 /** 1912 * 引数からspanタグを取り除いて返します。 1913 * 1914 * 引数が、<span ・・・>YYYY</span>形式の場合、YYYY のみ出力します。 1915 * この処理では、先頭にspan が一つだけある場合、削除します。 1916 * 複数の span や、div などを削除する場合は、#tagCut(String) メソッドで処理します。 1917 * 1918 * @og.rev 4.3.4.3 (2008/12/22) TableWriterで利用していたものを移動 1919 * 1920 * @param data 元のString文字列 1921 * 1922 * @return spanタグが取り除かれた文字列(引数が null の場合は、そのまま null が返ります) 1923 * @see #tagCut(String) 1924 */ 1925 public static String spanCut( final String data ) { 1926 String rtn = data; 1927 if( data != null && data.startsWith( "<span" ) ) { 1928 final int st = data.indexOf( '>' ); 1929 final int ed = data.indexOf( "</span>",st ); 1930 rtn = data.substring( st+1,ed ); 1931 } 1932 1933 return rtn ; 1934 } 1935 1936 /** 1937 * 引数からタグを取り除いて返します。 1938 * 1939 * 引数が、<xxxx ・・・>YYYY</xxxx>形式の場合、YYYY のみ出力します。 1940 * この処理では、すべてのタグを削除し、BODY部をつなげます。 1941 * <xxxx/> の様な、BODY要素を持たない場合は、ゼロ文字列になります。 1942 * 1943 * @og.rev 6.2.0.0 (2015/02/27) 引数からタグを削除し、BODY文字列を切り出します。 1944 * 1945 * @param data 元のString文字列 1946 * 1947 * @return タグが取り除かれた文字列(引数が null の場合は、そのまま null が返ります) 1948 */ 1949 public static String tagCut( final String data ) { 1950// if( data == null || data.isEmpty() || data.indexOf( '<' ) < 0 ) { return data; } 1951 if( isEmpty( data ) || data.indexOf( '<' ) < 0 ) { return data; } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 1952 1953 final StringBuilder rtn = new StringBuilder( BUFFER_MIDDLE ); 1954 1955 boolean tagOut = true; 1956 for( int i=0; i<data.length(); i++ ) { 1957 final char ch =data.charAt( i ); 1958 if( ch == '<' ) { tagOut = false; continue; } // タグの開始 1959 else if( ch == '>' ) { tagOut = true; continue; } // タグの終了 1960 1961 if( tagOut ) { rtn.append( ch ); } 1962 } 1963 1964 return rtn.toString() ; 1965 } 1966 1967 /** 1968 * 簡易CSS形式のフォーマットを、Mapにセットします。 1969 * 1970 * 簡易CSS形式とは、セレクタのない、{ プロパティ1 : 値1 ; ・・・ } 形式とします。 1971 * これを、プロパティ1 と 値1 のMap にセットする処理を行います。 1972 * コメントは、削除されます。また、同一プロパティが記述されている場合は、後処理を採用します。 1973 * 1974 * なお、入力テキストが、null か、{…} が存在しない場合は、空のMapを返します。 1975 * 1976 * @og.rev 5.6.5.2 (2013/06/21) 新規追加 1977 * @og.rev 6.4.3.1 (2016/02/12) PMD refactoring. HashMap → ConcurrentHashMap に置き換え。 1978 * @og.rev 6.4.3.3 (2016/03/04) 戻すMapが、not null制限つきであることを示すため、ConcurrentMap に置き換えます。 1979 * 1980 * @param cssText 簡易CSS形式のフォーマット文字列 1981 * 1982 * @return パース結果のMap(ConcurrentMap) 1983 * @og.rtnNotNull 1984 */ 1985 public static ConcurrentMap<String,String> cssParse( final String cssText ) { 1986 final ConcurrentMap<String,String> cssMap = new ConcurrentHashMap<>(); 1987 1988 if( cssText != null ) { 1989 // まずコメントを削除します。 1990 StringBuilder buf = new StringBuilder( cssText ); 1991 1992 int ad1 = buf.indexOf( "/*" ); 1993 while( ad1 >= 0 ) { 1994 final int ad2 = buf.indexOf( "*/" , ad1 ); 1995 if( ad2 < 0 ) { buf = buf.delete( ad1,buf.length() ); break; } // 閉じてなければ以降を全削除 1996 buf = buf.delete( ad1,ad2+2 ); 1997 ad1 = buf.indexOf( "/*" ); // コメントは削除されたので、初めから検索する。 1998 } 1999 2000 // 処理対象は、{ ~ } の間の文字列。 2001 ad1 = buf.indexOf( "{" ); 2002 final int ad2 = buf.indexOf( "}",ad1 ); 2003 if( ad1 >= 0 && ad2 > 0 ) { 2004 final String tempText = buf.substring( ad1+1,ad2 ); // これが処理対象の文字列 2005 2006 // 6.4.3.3 (2016/03/04) ちょっとした変更 2007 for( final String recode : tempText.split( ";" ) ) { // KEY1 : VAL1; の ; で分割する。 2008 final int ad = recode.indexOf( ':' ); 2009 if( ad > 0 ) { 2010 final String key = recode.substring( 0,ad ).trim(); 2011 final String val = recode.substring( ad+1 ).trim(); 2012 if( key.isEmpty() || val.isEmpty() ) { continue; } 2013 2014 cssMap.put( key,val ); 2015 } 2016 } 2017 } 2018 } 2019 2020 return cssMap ; 2021 } 2022 2023// /** 2024// * 引数から空白文字を削除して返します。 2025// * 2026// * @og.rev 5.6.9.4 (2013/10/31) TableWriterで利用していたものを移動 2027// * @og.rev 6.9.2.1 (2018/03/12) 使用箇所が、1箇所だけなので、StringUtilから移動する。 2028// * 2029// * @param data 元のString文字列 2030// * 2031// * @return 空白文字が取り除かれた文字列 2032// */ 2033// public static String deleteWhitespace( final String data ) { 2034// // 6.4.1.1 (2016/01/16) PMD refactoring. A method should have only one exit point, and that should be the last statement in the method 2035// return data == null || data.isEmpty() ? data : data.replaceAll( "\\s", "" ) ; // isNull 判定は使えない。 2036// } 2037 2038 /** 2039 * 引数の文字列が、引数の char で始まるかどうか判定します[始まる場合は、true]。 2040 * 2041 * これは、PMDで言う所の、String.startsWith can be rewritten using String.charAt(0) 2042 * の書き換え処理に相当します。 2043 * boolean flag = data != null && data.startsWith( chStr ); 的な処理を、 2044 * boolean flag = data != null && data.length() > 0 && data.charAt(0) == ch; 2045 * に書き換える代わりに、このメソッドを使用します。 2046 * 2047 * 内部ロジックは、上記の相当します。 2048 * 2049 * @og.rev 6.2.0.0 (2015/02/27) 1文字 String.startsWith の String.charAt(0) 変換 2050 * @og.rev 6.4.5.0 (2016/04/08) 引数をCharSequenceに変更 2051 * 2052 * @param data 引数のCharSequence 2053 * @param ch チェックするchar 2054 * 2055 * @return 引数文字列が、nullでなく、ゼロ文字列でなく、引数char で始まる場合は、true 2056 * @see java.lang.String#startsWith(String) 2057 */ 2058 public static boolean startsChar( final CharSequence data , final char ch ) { 2059 return data != null && data.length() > 0 && data.charAt(0) == ch; // スペースも判定対象にするため、isNull は使わない。 2060 } 2061 2062 /** 2063 * 引数から指定文字の分のバイト数で切った文字列を返します。 2064 * 文字列のバイト数は指定のエンコードでカウントします。 2065 * (文字の途中で切れる事はありません) 2066 * 2067 * @og.rev 5.9.1.3 (2015/10/30) 新規作成 2068 * @og.rev 6.4.2.0 (2016/01/29) StringUtil#ogStackTrace(Throwable) を、ThrowUtil##ogStackTrace(Throwable) に変更。 2069 * 2070 * @param org 元のString文字列 2071 * @param cutBytes 切るバイト数 2072 * @param enc 文字列のエンコード 2073 * 2074 * @return バイト数で切った文字列 2075 */ 2076 public static String cut( final String org, final int cutBytes, final String enc ) { 2077 try { 2078// if( org == null || org.length() == 0 || cutBytes <= 0 || org.getBytes(enc).length <= cutBytes ) { // isNul 判定は使いません。 2079// return org; 2080// } 2081 if( isEmpty( org,enc ) || cutBytes <= 0 || org.getBytes(enc).length <= cutBytes ) { return org; } // 6.9.2.1 (2018/03/12) isEmpty 置き換え 2082 2083 final StringBuilder cutSb = new StringBuilder( BUFFER_MIDDLE ); 2084 final StringBuilder tmpSb = new StringBuilder( BUFFER_MIDDLE ); 2085 2086 for( int i=0; i<org.length(); i++ ) { 2087 final String cut = org.substring(i, i + 1); 2088 if( cutBytes < tmpSb.toString().getBytes(enc).length + cut.getBytes(enc).length ) { 2089 cutSb.append( tmpSb.toString() ); 2090 break; 2091 } 2092 tmpSb.append(cut); 2093 } 2094 return cutSb.toString(); 2095 } 2096 catch( final UnsupportedEncodingException ex ) { 2097 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid printStackTrace(); use a logger call instead. 2098 // 6.4.2.0 (2016/01/29) StringUtil#ogStackTrace(Throwable) を、ThrowUtil##ogStackTrace(Throwable) に変更。 2099 final String errMsg = "エンコードが不正のため、バイトカットできません。" 2100 + " org=[" + org + "] , byteSize=[" + cutBytes + "] , encode=[" + enc + "]" ; 2101 2102 System.err.println( ThrowUtil.ogThrowMsg( errMsg,ex ) ); 2103 return org; 2104 } 2105 } 2106 2107 /** 2108 * 引数から指定文字の分のバイト数で切った文字列を返します。 2109 * バイト数のカウントはUTF-8として行います。 2110 * 2111 * @og.rev 5.9.1.3 (2015/10/30) 新規作成 2112 * 2113 * @param org 元のString文字列 2114 * @param cutBytes 切るバイト数 2115 * 2116 * @return バイト数で切った文字列 2117 */ 2118 public static String cut( final String org, final int cutBytes ) { 2119 return cut( org, cutBytes, "UTF-8"); 2120 } 2121}