OSDN Git Service

Ver8.5.2.0
[opengion/opengionV8.git] / uap / webapps / gf / src / org / opengion / fukurou / process / FileLineModel.java
1 /*
2  * Copyright (c) 2009 The openGion Project.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific language
14  * governing permissions and limitations under the License.
15  */
16 package org.opengion.fukurou.process;
17
18 import org.opengion.fukurou.system.OgRuntimeException ;                         // 6.4.2.0 (2016/01/29)
19 import org.opengion.fukurou.system.OgCharacterException ;                       // 6.5.0.1 (2016/10/21)
20 import org.opengion.fukurou.system.DateSet;                                                     // 6.4.2.0 (2016/01/29)
21 import org.opengion.fukurou.system.Closer;
22 import org.opengion.fukurou.util.FileUtil;
23 import org.opengion.fukurou.util.CommentLineParser;
24 import org.opengion.fukurou.util.FileInfo;                                                      // 6.4.0.2 (2015/12/11)
25 import org.opengion.fukurou.security.HybsCryptography ;                         // 5.7.2.1 (2014/01/17)
26 import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.3.1.0 (2015/06/28)
27
28 import java.io.File;
29 import java.io.BufferedReader;
30 import java.io.PrintWriter;
31 import java.io.IOException;
32 import java.nio.charset.CharacterCodingException;                                       // 6.3.1.0 (2015/06/28)
33
34 /**
35  * FileLineModel は、LineModel を継承した ファイルリスト専用の
36  * LineModel の実装クラスです。
37  *
38  * FileLineModel オブジェクトには、ファイル属性(Level,File,Length,Modify,LineCnt,Biko,MD5)
39  * が設定されます。
40  * オプションで、FILEPATH,ADDRESS,FILENAME 属性を文字列で準備できます。(6.3.1.0 (2015/06/28))
41  * ADDRESS は、指定ファイルの親フォルダ。FILENAME はファイル名。FILEPATH は、ファイル名を含む
42  * 完全なファイルパスになります。
43  * ※ 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
44  *    この、新しい属性に、値をセットする場合は、useFilePath="true" をセットしてください。
45  * ※ 6.3.1.1 (2015/07/10) Modify のフォーマット(modifyForm)を、指定可能にします。
46  *    これは、Date型のまま、扱いたい所だが、文字列化しています。
47  *    初期値は、"yyyy/MM/dd HH:mm:ss" です。
48  *
49  * LineCnt と、MD5 は、それぞれ、計算するかどうかのフラグを設定する必要があります。
50  *
51  * ※ useLineCnt=false の場合のLength(文字数)は、File#length() メソッドで求めます。
52  *    一方、useLineCnt=true にすると、行単位に、String#length() を加算するため、
53  *    先のLength(文字数)値とは異なりますのでご注意ください。
54  *
55  * omitCmnt=true にすると、コメント部分を削除した行数と文字数を求めます。
56  * これは、/* から */ の間、// から改行までです。
57  * ただし、"(二重引用符)で囲まれた文字列は、コメントとみなしません。
58  *
59  * 8.1.0.4 (2022/01/28)
60  *  さらに、各行の空行はカウントに含めないことにします。
61  *
62  * データの1行分を FileLineModel に割り当てます。
63  * カラム番号は、0 から始まります。カラム名よりカラム番号を求める場合に、
64  * 存在しない場合は、-1 を返します。
65  * カラム番号が -1 の場合は、処理を行いません。
66  *
67  * 注意:このクラスは、同期処理されていません。
68  *
69  * @version  4.0
70  * @author   Kazuhiko Hasegawa
71  * @since    JDK5.0,
72  */
73 public class FileLineModel extends LineModel {
74         // 5.7.2.1 (2014/01/17) MD5 項目追加
75         // 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
76         private static final String[] KEYS = { "Level","File","Length","Modify","LineCnt","Biko","MD5","FILEPATH","ADDRESS","FILENAME" };
77
78         private static final int LEVEL          = 0;
79         private static final int FILE           = 1;
80         private static final int LENGTH         = 2;
81         private static final int MODIFY         = 3;
82         private static final int LINECNT        = 4;
83         private static final int BIKO           = 5;
84         private static final int MD5            = 6;            // 5.7.2.1 (2014/01/17)
85         private static final int FILEPATH       = 7;            // 6.3.1.0 (2015/06/28)
86         private static final int ADDRESS        = 8;            // 6.3.1.0 (2015/06/28)
87         private static final int FILENAME       = 9;            // 6.3.1.0 (2015/06/28)
88
89         private final boolean useLineCnt ;
90         private final boolean useMD5 ;                          // 5.7.2.1 (2014/01/17) MD5 項目追加
91         private final boolean omitCmnt ;                        // 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)
92         private final boolean useFilePath ;                     // 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性を使う場合は、true
93         private String encode = "JISAutoDetect";        // 5.7.4.0 (2014/03/07) コメント削除時の文字数計算で利用するファイルのエンコード
94         private String modifyForm = "yyyy/MM/dd HH:mm:ss" ;     // 6.3.1.1 (2015/07/10)
95
96         /**
97          * コンストラクターです。
98          * useLineCnt=false , useMD5=false , omitCmnt=false で初期化されます。
99          *
100          * @og.rev 5.7.2.1 (2014/01/17) MD5対応
101          * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)対応
102          * @og.rev 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
103          *
104          */
105         public FileLineModel() {
106                 this( false,false,false,false );                // 6.3.1.0 (2015/06/28)
107         }
108
109         /**
110          * ラインカウントの有無を指定した、コンストラクターです。
111          * useMD5=false , omitCmnt=false で初期化されます。
112          *
113          * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無
114          * @og.rev 5.7.2.1 (2014/01/17) MD5対応
115          * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)対応
116          * @og.rev 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
117          *
118          * @param       isLineCnt       行数カウントの使用有無
119          */
120         public FileLineModel( final boolean isLineCnt ) {
121                 this( isLineCnt,false,false,false );            // 6.3.1.0 (2015/06/28)
122         }
123
124         /**
125          * ラインカウントの有無と、MD5計算の有無を指定した、コンストラクターです。
126          * omitCmnt=false で初期化されます。
127          *
128          * @og.rev 5.7.2.1 (2014/01/17) 新規追加(MD5対応)
129          * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)対応
130          * @og.rev 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加。
131          *
132          * @param       isLineCnt       行数カウントの使用有無
133          * @param       isMD5           ファイルのMD5の使用有無
134          */
135         public FileLineModel( final boolean isLineCnt,final boolean isMD5 ) {
136                 this( isLineCnt,isMD5,false,false );            // 6.3.1.0 (2015/06/28)
137         }
138
139         /**
140          * ラインカウントの有無と、MD5計算の有無と、コメント除外の可否を指定した、コンストラクターです。
141          *
142          * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)
143          * @og.rev 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
144          *
145          * @param       isLineCnt       行数カウントの使用有無
146          * @param       isMD5           ファイルのMD5の使用有無
147          * @param       isOmit          コメント除外の可否(true:除外する)
148          */
149         public FileLineModel( final boolean isLineCnt,final boolean isMD5,final boolean isOmit ) {
150                 this( isLineCnt,isMD5,isOmit,false );   // 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
151         }
152
153         /**
154          * ラインカウントの有無と、MD5計算の有無と、コメント除外の可否と、追加属性可否を指定した、コンストラクターです。
155          *
156          * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)
157          * @og.rev 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
158          * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor
159          *
160          * @param       isLineCnt       行数カウントの使用有無
161          * @param       isMD5           ファイルのMD5の使用有無
162          * @param       isOmit          コメント除外の可否(true:除外する)
163          * @param       isPath          FILEPATH,ADDRESS,FILENAME 属性の可否(true:使用する)
164          */
165         public FileLineModel( final boolean isLineCnt,final boolean isMD5,final boolean isOmit,final boolean isPath ) {
166                 super();
167                 // 4.3.4.4 (2009/01/01)
168                 useLineCnt      = isLineCnt;
169                 useMD5          = isMD5;                                // 5.7.2.1 (2014/01/17)
170                 omitCmnt        = isOmit;                               // 5.7.4.0 (2014/03/07)
171                 useFilePath     = isPath;                               // 5.7.4.0 (2014/03/07)
172                 init( KEYS );
173         }
174
175         /**
176          * LineModel を元に、FileLineModel を構築します。
177          * これは、一旦ファイル等にセーブされた FileLineModel 形式を
178          * 元に戻す簡易コンストラクタです。
179          *
180          * @og.rev 4.2.3.0 (2008/05/26) 新規追加
181          * @og.rev 5.7.2.1 (2014/01/17) MD5の設定処理追加
182          * @og.rev 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
183          * @og.rev 6.4.1.1 (2016/01/16) PMD refactoring. It is a good practice to call super() in a constructor
184          *
185          * @param       model   元のLineModel
186          */
187         public FileLineModel( final LineModel model ) {
188                 super();
189                 // 4.3.4.4 (2009/01/01)
190                 init( model.getNames() );
191
192                 final Object[] obj = model.getValues();
193
194                 setValue( LEVEL   ,Integer.valueOf( (String)obj[LEVEL] ) );
195                 setValue( FILE    ,new File((String)obj[FILE]) );
196                 setValue( LENGTH  ,Long.valueOf( (String)obj[LENGTH] ) );
197                 setValue( MODIFY  ,(String)obj[MODIFY] );
198
199                 final String cnt = (String)obj[LINECNT] ;
200                 useLineCnt = cnt != null && cnt.length() > 0 && ! "null".equalsIgnoreCase( cnt ) ;
201                 if( useLineCnt ) { setValue( LINECNT ,cnt ); }
202
203                 setValue( BIKO  ,(String)obj[BIKO] );
204
205                 // 5.7.2.1 (2014/01/17)
206                 final String md5Data = (String)obj[MD5] ;
207                 useMD5 = md5Data != null && md5Data.length() > 0 && ! "null".equalsIgnoreCase( md5Data ) ;
208                 if( useMD5 ) { setValue( MD5 ,md5Data ); }
209
210                 omitCmnt   = false;                     // 5.7.4.0 (2014/03/07) 既存の LineModel から取得できないので、強制設定します。
211
212                 // 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
213                 // 念のため、配列数をチェックしながら処理します。
214                 if( obj.length > FILEPATH ) {
215                         final String path = (String)obj[FILEPATH] ;
216                         useFilePath = path != null && path.length() > 0 && ! "null".equalsIgnoreCase( path ) ;
217                         if( useFilePath ) {
218                                 setValue( FILEPATH ,path );
219                                 if( obj.length > ADDRESS  ) { setValue( ADDRESS  ,(String)obj[ADDRESS]  ); }
220                                 if( obj.length > FILENAME ) { setValue( FILENAME ,(String)obj[FILENAME] ); }
221                         }
222                 }
223                 else {
224                         useFilePath = false;
225                 }
226         }
227
228         /**
229          * File属性値をセットします。
230          * LEVEL,FILE,LENGTH,MODIFY,LINECNT,MD5 の各属性を設定します。
231          *
232          * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無
233          * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
234          * @og.rev 5.7.2.1 (2014/01/17) MD5計算処理の追加
235          * @og.rev 5.7.4.0 (2014/03/07) コメント除外の可否(true:除外する)対応
236          * @og.rev 5.7.7.1 (2014/06/13) omitCmnt=true(コメント除外する) and useMD5=true(MD5計算する) 場合の処理
237          * @og.rev 6.2.1.0 (2015/03/13) ファイルの削除に失敗するため、削除しない。
238          * @og.rev 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
239          * @og.rev 8.1.2.0 (2022/03/10) getMD5 メソッドを getHash メソッドに変更
240          *
241          * @param       level   ファイルのディレクトリ階層
242          * @param       file    ファイルオブジェクト
243          */
244         public void setFileVals( final int level, final File file ) {
245                 setValue( LEVEL  ,Integer.valueOf( level ) );
246                 setValue( FILE   ,file );
247                 setValue( MODIFY ,DateSet.getDate( file.lastModified(),modifyForm ) );                                  // 6.3.1.1 (2015/07/10)
248
249                 // 5.7.7.1 (2014/06/13) omitCmnt=true(コメント除外する) and useMD5=true(MD5計算する) 場合の処理
250                 // 別にコメント除去されたファイルを作成して、それの MD5 を求める。
251                 File ocFile = null;
252                 if( omitCmnt && useMD5 ) {
253                         try {
254                                 ocFile = File.createTempFile( "temp",".tmp" );
255                                 ocFile.deleteOnExit();                                                          // 一応、このメソッド内で削除しますが、念のため。
256                         }
257                         catch( final IOException ex ) {
258                                 final String errMsg = "コメント除外のMD5計算用 temp ファイルの作成に失敗しました。" + ex.getMessage() ;
259                                 throw new OgRuntimeException( errMsg,ex );
260                         }
261                 }
262
263                 if( useLineCnt || omitCmnt ) {
264                         final long[] cntVals = getLineCnt( file,ocFile );                       // 5.7.7.1 (2014/06/13) 出力ファイルを渡します。
265                         setValue( LINECNT ,String.valueOf( cntVals[0] ) );
266                         setValue( LENGTH  ,Long.valueOf(   cntVals[1] ) );
267                 }
268                 else {
269                         setValue( LENGTH  ,Long.valueOf( file.length() ) );
270                 }
271
272                 // 5.7.2.1 (2014/01/17) MD5計算がtrue で、かつ、ファイルの場合、MD5 計算を行います。
273                 if( useMD5 && file.isFile() ) {
274                         // 5.7.7.1 (2014/06/13) omitCmnt を考慮したMD5計算
275                         if( ocFile == null ) {
276 //                              setValue( MD5 ,HybsCryptography.getMD5( file ) );                               // 8.1.2.0 (2022/03/10) Modify
277                                 setValue( MD5 ,HybsCryptography.getHash( "MD5", file ) );
278                         }
279                         else {
280 //                              setValue( MD5 ,HybsCryptography.getMD5( ocFile ) );                             // 8.1.2.0 (2022/03/10) Modify
281                                 setValue( MD5 ,HybsCryptography.getHash( "MD5", ocFile ) );
282                                 // 6.0.2.4 (2014/10/17) RV  java.io.File.delete() の例外的戻り値を無視しています。
283                                 // 6.2.1.0 (2015/03/13) ファイルの削除に失敗するため、削除しない。
284                         }
285                 }
286
287                 // 6.3.1.0 (2015/06/28) FILEPATH,ADDRESS,FILENAME 属性追加
288                 if( useFilePath ) {
289                         // FILEPATH は、正規のパス名文字列 を求めるが、エラー時は、絶対パス名文字列 にする。
290                         try {
291                                 setValue( FILEPATH      , file.getCanonicalPath() );    // 正規のパス名文字列
292                         }
293                         catch( final IOException ex ) {
294                                 setValue( FILEPATH      , file.getAbsolutePath() );             // 絶対パス名文字列
295                         }
296
297                         // ADDRESS は、親の名前なので、直フォルダ名になる。
298                         final File parent = file.getParentFile();
299                         if( parent != null ) {
300                                 setValue( ADDRESS       ,parent.getName() );
301                         }
302
303                         setValue( FILENAME      ,file.getName() );
304                 }
305         }
306
307         /**
308          * コメント削除時の文字数計算で利用するファイルのエンコードをセットします。
309          * 初期値:JISAutoDetect
310          *
311          * @og.rev 5.7.4.0 (2014/03/07) 新規追加
312          *
313          * @param       encode  コメント削除時の文字数計算で利用するファイルのエンコード
314          */
315         public void setEncode( final String encode ) {
316                 this.encode = encode;
317         }
318
319         /**
320          * File属性値をセットします。
321          *
322          * @param       file    ファイルオブジェクト
323          */
324         public void setFile( final File file ) {
325                 setValue( FILE,file );
326         }
327
328         /**
329          * ファイルを取得します。
330          *
331          * @return      ファイル
332          */
333         public File getFile() {
334                 return (File)getValue( FILE );
335         }
336
337         /**
338          * 備考情報属性値をセットします。
339          *
340          * @og.rev 4.2.2.0 (2008/05/10) 行数カウントの使用有無
341          *
342          * @param       biko    備考情報
343          */
344         public void setBiko( final String biko ) {
345                 setValue( BIKO,biko );
346         }
347
348         /**
349          * レベル File属性値を取得します。
350          *
351          * @return      ファイルのディレクトリ階層
352          */
353         public int getLevel() {
354                 return ((Integer)getValue( LEVEL )).intValue();
355         }
356
357         /**
358          * ファイルサイズ File属性値を取得します。
359          *
360          * @return      ファイルサイズ
361          */
362         public long getLength() {
363                 return ((Long)getValue( LENGTH )).longValue();
364         }
365
366         /**
367          * 更新日時(Modify) のフォーマットを、指定します。
368          *
369          * ここで指定しない場合は、"yyyy/MM/dd HH:mm:ss" になります。
370          * Date型で変換できないようなフォームを指定した場合は、実行時に
371          * エラーになりますので、ご注意ください。
372          *
373          * @og.rev 6.3.1.1 (2015/07/10) Modify のフォーマットを、指定可能にします。
374          *
375          * @param       form 更新日時のフォーマット
376          * @see         java.text.SimpleDateFormat
377          */
378         public void setModifyForm( final String form ) {
379                 if( form != null && !form.isEmpty() ) {
380                         modifyForm = form;
381                 }
382         }
383
384         /**
385          * 更新日時 File属性値を取得します。
386          *
387          * @return      更新日時(yyyy/MM/dd HH:mm:ss)
388          */
389         public String getModify() {
390                 return (String)getValue( MODIFY );
391         }
392
393         /**
394          * MD5 File属性値を取得します。
395          * ただし、useMD5 が true でないと値は返しません。
396          *
397          * @og.rev 5.7.2.1 (2014/01/17) 新規追加(MD5対応)
398          *
399          * @return      MD5の値
400          */
401         public String getMD5() {
402                 return (String)getValue( MD5 );
403         }
404
405         /**
406          * 行数と文字数を取得します。
407          * 行数カウントとファイルの文字数カウント(バイト数ではありません)を行います。
408          * ※ useLineCnt=false の場合のLength(文字数)は、File#length() メソッドで求めます。
409          *    一方、useLineCnt=true にすると、行単位に、String#length() を加算するため、
410          *    先のLength(文字数)値とは異なりますのでご注意ください。
411          *
412          * 結果は、long型の配列で返します。[0]が行数で、[1]が文字数です。
413          * omitCmnt 属性を使用した場合は、コメント部分を削除した行数と文字数を求めます。
414          * これは、/* から */ の間、// から改行までです。
415          * ただし、"(二重引用符)で囲まれた文字列は、コメントとみなしません。
416          *
417          * @og.rev 5.7.4.0 (2014/03/07) 行数カウントとファイルの文字数カウントを行う。
418          * @og.rev 5.7.7.1 (2014/06/13) omitCmnt=true(コメント除外する) and useMD5=true(MD5計算する) 場合の処理
419          * @og.rev 6.2.1.0 (2015/03/13) ディレクトリ以外からファイルのみに対象を変更。
420          * @og.rev 6.3.1.0 (2015/06/28) nioを使用すると UTF-8とShuft-JISで、エラーになる。
421          * @og.rev 6.4.0.2 (2015/12/11) CommentLineParser 改造。
422          * @og.rev 6.5.0.1 (2016/10/21) CharacterCodingException は、OgCharacterException に変換する。
423          * @og.rev 8.1.0.4 (2022/01/28) 各行の空行はカウントに含めないことにする。
424          *
425          * @param       file    行数を数えるファイルオブジェクト
426          * @param       ocFile  omitCmnt=trueの場合に、MD5計算する時の、仮出力ファイル(nullの場合は、無視)
427          *
428          * @return  long型の配列([0]が行数で、[1]が文字数)
429          * @og.rtnNotNull
430          */
431         private long[] getLineCnt( final File file,final File ocFile ) {
432                 long lineCnt = 0L;              // 行数
433                 long charCnt = 0L;              // 文字数
434
435                 final BufferedReader reader = FileUtil.getBufferedReader( file,encode );
436
437                 // 5.7.7.1 (2014/06/13) omitCmnt=true(コメント除外する) and useMD5=true(MD5計算する) 場合の処理
438                 PrintWriter writer = null;
439                 if( ocFile != null ) { writer = FileUtil.getPrintWriter( ocFile ,encode ); }
440
441                 // 6.4.0.2 (2015/12/11) CommentLineParser 改造
442                 final CommentLineParser clp = omitCmnt ? new CommentLineParser( FileInfo.getSUFIX( file ) ) : null;
443                 try {
444                         // 6.2.1.0 (2015/03/13) ディレクトリ以外からファイルのみに対象を変更。
445                         if( file.isFile() ) {
446                                 String line ;
447                                 while((line = reader.readLine()) != null) {
448                                         if( omitCmnt ) {
449                                                 line = clp.line( line );
450                                                 // 8.1.0.4 (2022/01/28) 各行の空行はカウントに含めないことにする。
451 //                                              if( line == null ) { continue; }        // 戻り値が null の場合は、行として不成立
452                                                 if( line == null || line.isEmpty() ) { continue; }      // 戻り値が nullか 空行の場合は、含めない
453                                                 if( writer != null ) { writer.println( line ); }        // 5.7.7.1 (2014/06/13)
454                                         }
455
456                                         lineCnt++;
457                                         charCnt += line.length();
458                                 }
459                         }
460                 }
461                 // 6.3.1.0 (2015/06/28) nioを使用すると UTF-8とShuft-JISで、エラーになる。
462                 catch( final CharacterCodingException ex ) {
463                         final String errMsg = "文字のエンコード・エラーが発生しました。" + CR
464                                                                 +       "  ファイルのエンコードが指定のエンコードと異なります。" + CR
465                                                                 +       " [" + file.getPath() + "] , Encode=[" + encode + "]" ;
466                         throw new OgCharacterException( errMsg,ex );    // 6.5.0.1 (2016/10/21)
467                 }
468                 catch( final IOException ex ) {
469                         final String errMsg = "ファイルカウント中に例外が発生しました。" + CR
470                                                                 +       " [" + file.getPath() + "] , Encode=[" + encode + "]" ;
471                         throw new OgRuntimeException( errMsg,ex );
472                 }
473                 finally {
474                         Closer.ioClose( reader ) ;
475                         Closer.ioClose( writer ) ;              // 5.7.7.1 (2014/06/13) ioClose は、引数が null なら無視します。
476                 }
477
478                 return new long[] { lineCnt,charCnt };
479         }
480 }