OSDN Git Service

予約ダイアログに裏番組情報のグラフィカル表示を追加
[tainavi/TinyBannavi.git] / TinyBannavi / src / tainavi / CommonUtils.java
1 \r
2 package tainavi;\r
3 \r
4 import java.awt.Color;\r
5 import java.awt.Desktop;\r
6 import java.beans.XMLDecoder;\r
7 import java.beans.XMLEncoder;\r
8 import java.io.BufferedInputStream;\r
9 import java.io.BufferedOutputStream;\r
10 import java.io.BufferedReader;\r
11 import java.io.BufferedWriter;\r
12 import java.io.File;\r
13 import java.io.FileInputStream;\r
14 import java.io.FileNotFoundException;\r
15 import java.io.FileOutputStream;\r
16 import java.io.FileReader;\r
17 import java.io.FileWriter;\r
18 import java.io.IOException;\r
19 import java.io.InputStream;\r
20 import java.io.InputStreamReader;\r
21 import java.io.OutputStream;\r
22 import java.io.OutputStreamWriter;\r
23 import java.io.Reader;\r
24 import java.io.Writer;\r
25 import java.net.HttpURLConnection;\r
26 import java.net.Socket;\r
27 import java.nio.channels.FileChannel;\r
28 import java.nio.channels.FileLock;\r
29 import java.text.SimpleDateFormat;\r
30 import java.util.ArrayList;\r
31 import java.util.Calendar;\r
32 import java.util.GregorianCalendar;\r
33 import java.util.HashMap;\r
34 import java.util.Map.Entry;\r
35 import java.util.regex.Matcher;\r
36 import java.util.regex.Pattern;\r
37 import java.util.zip.ZipEntry;\r
38 import java.util.zip.ZipFile;\r
39 import java.util.zip.ZipOutputStream;\r
40 \r
41 /**\r
42  * <P>頻繁に使用する雑多なメソッドをstaticで提供します。\r
43  * <P>パッケージを小分けにしておけばよかった…\r
44  */\r
45 public class CommonUtils {\r
46 \r
47         /*******************************************************************************\r
48          * CommonUtilsの動作設定\r
49          ******************************************************************************/\r
50 \r
51         /**\r
52          * デバッグログ出力するかどうか\r
53          */\r
54         public static void setDebug(boolean b) { debug = b; }\r
55         private static boolean debug = false;\r
56         \r
57         /**\r
58          *  深夜の帯予約補正に対応するかどうか\r
59          */\r
60         public static void setAdjLateNight(boolean b) { adjLateNight = b; }\r
61         private static boolean adjLateNight = false;\r
62         \r
63         /**\r
64          * Web番組表の8日分取得に対応するかどうか\r
65          */\r
66         public static void setExpandTo8(boolean b) { dogDays = ((b)?(8):(7)); }\r
67         private static int dogDays = 7;\r
68         \r
69         /**\r
70          * 過去予約の表示に対応するかどうか\r
71          */\r
72         public static void setDisplayPassedReserve(boolean b) { displayPassedReserve = b; }\r
73         private static boolean displayPassedReserve = false;\r
74         \r
75         /**\r
76          * Windows環境下で、アプリケーションに関連付けられたファイルを開くのにrundll32.exeを利用するかどうか\r
77          */\r
78         public static void setUseRundll32(boolean b) { useRundll32 = b; }\r
79         private static boolean useRundll32 = false;\r
80         \r
81         \r
82         /*******************************************************************************\r
83          * 日付時刻関連\r
84          ******************************************************************************/\r
85         \r
86         public static final String[] WDTPTN = {"日","月","火","水","木","金","土"};\r
87         \r
88         /**\r
89          * 曜日→wday\r
90          */\r
91         public static int getWday(String s) {\r
92                 if ( s == null || s.length() == 0 ) {\r
93                         return 0;\r
94                 }\r
95                 \r
96                 String x = s.substring(0,1);\r
97                 for ( int i=0; i<WDTPTN.length; i++ ) {\r
98                         if ( WDTPTN[i].equals(x) ) {\r
99                                 return i+1;\r
100                         }\r
101                 }\r
102                 return 0;\r
103         }\r
104         \r
105         /**\r
106          * 月日に年を補完\r
107          */\r
108         public static String getDateByMD(int m, int d, int wday, boolean addwstr) {\r
109                 return getDate(getCalendarByMD(m,d,wday),addwstr);\r
110         }\r
111         \r
112         /**\r
113          * 月日に年を補完\r
114          */\r
115         public static GregorianCalendar getCalendarByMD(int m, int d, int wday) {\r
116                 GregorianCalendar c = new GregorianCalendar(\r
117                                 Calendar.getInstance().get(Calendar.YEAR),\r
118                                 m-1,\r
119                                 d\r
120                                 );\r
121                 \r
122                 if ( c.get(Calendar.DAY_OF_WEEK) == wday ) {\r
123                         // 当年\r
124                         return c;\r
125                 }\r
126                 \r
127                 c.add(Calendar.YEAR, 1);\r
128                 if ( c.get(Calendar.DAY_OF_WEEK) == wday ) {\r
129                         // 翌年\r
130                         return c;\r
131                 }\r
132                 \r
133                 return null;\r
134         }\r
135 \r
136         \r
137         /**\r
138          * 深夜帯(24:00~28:59)かどうか判定する\r
139          */\r
140         public static boolean isLateNight(GregorianCalendar A) {\r
141                 return isLateNight(A.get(Calendar.HOUR_OF_DAY));\r
142         }\r
143         \r
144         /**\r
145          * 深夜帯(24:00~28:59)かどうか判定する\r
146          */\r
147         public static boolean isLateNight(String Ahh) {\r
148                 return ("00".compareTo(Ahh) <= 0 && "05".compareTo(Ahh) > 0);\r
149         }\r
150         \r
151         /**\r
152          * 深夜帯(24:00~28:59)かどうか判定する\r
153          */\r
154         public static boolean isLateNight(int Ahh) {\r
155                 return (Ahh >= 0 && Ahh < 5);\r
156         }\r
157         \r
158         /**\r
159          *  開始・終了時刻から長さを算出する。引数の前後関係は意識しなくて良い。\r
160          */\r
161         public static String getRecMin(GregorianCalendar ca, GregorianCalendar cz) {\r
162                 return String.valueOf(getRecMinVal(ca, cz));\r
163         }\r
164         \r
165         /**\r
166          *  開始・終了時刻から長さを算出する。引数の前後関係は意識しなくて良い。\r
167          */\r
168         public static String getRecMin(String start, String end) {\r
169                 return String.valueOf(getRecMinVal(start,end));\r
170         }\r
171 \r
172         public static String getRecMin(String ahhStr,String ammStr,String zhhStr,String zmmStr) {\r
173                 return String.valueOf(getRecMinVal(ahhStr,ammStr,zhhStr,zmmStr));\r
174         }\r
175 \r
176         /**\r
177          *  開始・終了時刻から長さを算出する。引数の前後関係は意識しなくて良い。\r
178          */\r
179         public static long getRecMinVal(GregorianCalendar ca, GregorianCalendar cz)     {\r
180                 return getDiffDateTime(ca, cz)/60000L;\r
181         }\r
182         \r
183         /**\r
184          * 開始・終了時刻から長さを算出する。引数の前後関係は意識しなくて良い。\r
185          * @param start hh:mm\r
186          * @param end hh:mm\r
187          */\r
188         public static int getRecMinVal(String start, String end) {\r
189                 Matcher ma = Pattern.compile("(\\d\\d):(\\d\\d)").matcher(start);\r
190                 Matcher mb = Pattern.compile("(\\d\\d):(\\d\\d)").matcher(end);\r
191                 if ( ! ma.find() || ! mb.find()) {\r
192                         return 0;\r
193                 }\r
194                 return getRecMinVal(ma.group(1),ma.group(2),mb.group(1),mb.group(2));\r
195         }\r
196         \r
197         /**\r
198          *  開始・終了時刻から長さを算出する。引数の前後関係は意識しなくて良い。\r
199          */\r
200         public static int getRecMinVal(String ahhStr,String ammStr,String zhhStr,String zmmStr) {\r
201                 try {\r
202                         return getRecMinVal(Integer.valueOf(ahhStr), Integer.valueOf(ammStr), Integer.valueOf(zhhStr), Integer.valueOf(zmmStr));\r
203                 }\r
204                 catch ( NumberFormatException e ) {\r
205                         System.err.println("[ERROR] at getRecMin(): "+ahhStr+","+ammStr+","+zhhStr+","+zmmStr);\r
206                         e.printStackTrace();\r
207                 }\r
208                 return 0;\r
209         }\r
210         \r
211         /**\r
212          *  開始・終了時刻から長さを算出する。引数の前後関係は意識しなくて良い。\r
213          */\r
214         public static int getRecMinVal(int ahh, int amm, int zhh, int zmm) {\r
215                 int min = (zhh*60+zmm) - (ahh*60+amm);\r
216                 if (min < 0) min += 24*60;\r
217                 return min;\r
218         }\r
219         \r
220         /**\r
221          *  1440分中の何分目か返す\r
222          */\r
223         public static int getMinOfDate(String ahh, String amm) {\r
224                 try {\r
225                         return getMinOfDate(Integer.valueOf(ahh),Integer.valueOf(amm));\r
226                 }\r
227                 catch (NumberFormatException e) {\r
228                         return -1;\r
229                 }\r
230         }\r
231         \r
232         /**\r
233          *  1440分中の何分目か返す\r
234          */\r
235         public static int getMinOfDate(int ahh, int amm) {\r
236                 return ahh*60+amm;\r
237         }\r
238         \r
239         /**\r
240          * @see #getCritDateTime(int)\r
241          */\r
242         public static String getCritDateTime() {\r
243                 return getCritDateTime(0);\r
244         }\r
245         /**\r
246          * <P>ここより前は「前日」分であり過去情報であると判断するための基準日時を生成する。\r
247          * <P>要するに、「当日」の "YYYY/MM/DD 05:00" (「当日」なので、日付は {@link #getDate529} の値)\r
248          * @param n : n日先の基準日時か。当日の場合は0 \r
249          */\r
250         public static String getCritDateTime(int n) {\r
251                 return getDate529(n*86400,false)+" 05:00";\r
252         }\r
253         /**\r
254          * \r
255          * @param showpassed true:{@link #getCritDateTime()}と等価、false:{@link #getDateTime(int)}と等価\r
256          * @return\r
257          */\r
258         public static String getCritDateTime(boolean showpassed) {\r
259                 if (showpassed) {\r
260                         return getCritDateTime(0);\r
261                 }\r
262                 else {\r
263                         return getDateTime(0);\r
264                 }\r
265         }\r
266         /**\r
267          * \r
268          */\r
269         public static GregorianCalendar getCritCalendar(String date) {\r
270                 GregorianCalendar ca = getCalendar(date);\r
271                 int hh = ca.get(Calendar.HOUR_OF_DAY);\r
272                 int mm = ca.get(Calendar.MINUTE);\r
273                 int ss = ca.get(Calendar.SECOND);\r
274                 ca.add(Calendar.HOUR_OF_DAY,-hh+5);\r
275                 ca.add(Calendar.MINUTE,-mm);\r
276                 ca.add(Calendar.SECOND,-ss);\r
277                 return ca;\r
278         }\r
279         \r
280         /**\r
281          * 次回実行予定日を取得する\r
282          * @see #getStartEndList(ArrayList, ArrayList, ReserveList)\r
283          */\r
284         public static String getNextDate(ReserveList r) {\r
285                 \r
286                 ArrayList<String> starts = new ArrayList<String>();\r
287                 ArrayList<String> ends = new ArrayList<String>();\r
288                 CommonUtils.getStartEndList(starts, ends, r);\r
289                 if (starts.size() > 0) {\r
290                         GregorianCalendar c = getCalendar(starts.get(0));\r
291                         if (c != null) {\r
292                                 return(getDate(c));\r
293                         }\r
294                 }\r
295                 \r
296                 // エラーの場合は1970/01/01を返す\r
297                 return(getDate(new GregorianCalendar(1970,0,1)));\r
298         }\r
299         \r
300         /**\r
301          * 開始・終了日時のリストを作成する\r
302          * @see #getNextDate(ReserveList)\r
303          */\r
304         public static void getStartEndList(ArrayList<String> starts, ArrayList<String> ends, ReserveList r) {\r
305                 \r
306                 int ptnid = r.getRec_pattern_id();\r
307                 \r
308                 //boolean isOverDay = (r.getAhh().compareTo(r.getZhh()) > 0);           // 日付をまたいだ\r
309                 //boolean isLateNight = (adjLateNight == false && ( ptnid >= 7 && ptnid <= 10 ) && isLateNight(r.getAhh()));    // 深夜帯(毎日&帯予約のみ利用)\r
310                 \r
311                 int len = Integer.valueOf(getRecMin(r.getAhh(), r.getAmm(), r.getZhh(), r.getZmm()));\r
312                 \r
313                 // 予約パターンによりけり対象となる日付は増えたり増えたり\r
314                 if (ptnid == 11) {\r
315                         // 単日\r
316                         GregorianCalendar d = getCalendar(r.getRec_pattern()+" "+r.getAhh()+":"+r.getAmm());\r
317                         if (d != null) {\r
318                                 starts.add(getDateTime(d));\r
319                                 d.add(Calendar.MINUTE,len);\r
320                                 ends.add(getDateTime(d));\r
321                         }\r
322                 }\r
323                 else {\r
324                         \r
325                         // 基準日時\r
326                         GregorianCalendar cur = getCalendar(0);\r
327                         GregorianCalendar cri = getCalendar(getCritDateTime());\r
328                         \r
329                         // 切り捨て条件の選択\r
330                         GregorianCalendar cond;\r
331                         if ( displayPassedReserve ) {\r
332                                 cond = (GregorianCalendar) cri.clone(); // 過去予約表示\r
333                         }\r
334                         else {\r
335                                 cond = (GregorianCalendar) cur.clone(); // 現在日時以上\r
336                         }\r
337                         \r
338                         // ループ終了位置\r
339                         GregorianCalendar cz = (GregorianCalendar) cur.clone();\r
340                         cz.add(Calendar.DATE, dogDays);\r
341                         \r
342                         // ループ開始位置\r
343                         GregorianCalendar ca = (GregorianCalendar) cri.clone();\r
344                         if ( isLateNight(r.getAhh()) ) {\r
345                                 ca.add(Calendar.DATE, 1);\r
346                         }\r
347                         ca.set(Calendar.HOUR_OF_DAY, Integer.valueOf(r.getAhh()));\r
348                         ca.set(Calendar.MINUTE, Integer.valueOf(r.getAmm()));\r
349                         GregorianCalendar cb = (GregorianCalendar) ca.clone();\r
350                         cb.set(Calendar.HOUR_OF_DAY, Integer.valueOf(r.getZhh()));\r
351                         cb.set(Calendar.MINUTE, Integer.valueOf(r.getZmm()));\r
352                         if ( cb.compareTo(ca) < 0 ) {\r
353                                 cb.add(Calendar.DATE, 1);       // 終了日時より開始日時が大きいならば\r
354                         }\r
355                         \r
356                         // 深夜かな?\r
357                         boolean islatenight = isLateNight(r.getAhh());\r
358                         \r
359                         while (ca.compareTo(cz) < 0)\r
360                         {\r
361                                 if ( cond.compareTo(cb) > 0 ) {\r
362                                         // 過去情報だにゅ\r
363                                         ca.add(Calendar.DATE, 1);\r
364                                         cb.add(Calendar.DATE, 1);\r
365                                         continue;\r
366                                 }\r
367                                 \r
368                                 boolean isReserved = false;     // 過去の予約=false\r
369 \r
370                                 if (ptnid == 10) {\r
371                                         // 毎日\r
372                                         isReserved = true;\r
373                                 }\r
374                                 else if (9 >= ptnid && ptnid >= 7) {\r
375                                         // 帯\r
376                                         int wd = ca.get(Calendar.DAY_OF_WEEK);\r
377                                         if ( islatenight ) {\r
378                                                 if ( adjLateNight ) {\r
379                                                         // RDなどの深夜時間帯(月~土)\r
380                                                         if ( Calendar.MONDAY <= wd && wd <= (r.getRec_pattern_id()-2) ) {\r
381                                                                 isReserved = true;\r
382                                                         }\r
383                                                 }\r
384                                                 else {\r
385                                                         // 通常の深夜時間帯(火~日)\r
386                                                         if ( Calendar.TUESDAY <= wd && wd <= (r.getRec_pattern_id()-1) ) {\r
387                                                                 isReserved = true;\r
388                                                         }\r
389                                                         else if ( ptnid == 9 && wd == Calendar.SUNDAY ) {\r
390                                                                 isReserved = true;\r
391                                                         }\r
392                                                 }\r
393                                         }\r
394                                         else {\r
395                                                 // 平常時間帯\r
396                                                 if ( Calendar.MONDAY <= wd && wd <= (r.getRec_pattern_id()-2) ) {\r
397                                                         isReserved = true;\r
398                                                 }\r
399                                         }\r
400                                 }\r
401                                 else if (ptnid < 7) {\r
402                                         // 週次\r
403                                         if ( ptnid == (ca.get(Calendar.DAY_OF_WEEK)-1) ) {\r
404                                                 isReserved = true;\r
405                                         }\r
406                                 }\r
407                                 \r
408                                 if (isReserved) {\r
409                                         GregorianCalendar ct = (GregorianCalendar) ca.clone();\r
410                                         ct.add(Calendar.MINUTE,len);\r
411                                         starts.add(getDateTime(ca));\r
412                                         ends.add(getDateTime(ct));\r
413                                 }\r
414                                 \r
415                                 ca.add(Calendar.DATE, 1);\r
416                                 cb.add(Calendar.DATE, 1);\r
417                         }\r
418                 }\r
419         }\r
420         \r
421         /**\r
422          * <P>aとbの差をミリ秒で返す(正/負)\r
423          * <P>秒に直すなら 1000、分に直すなら 60000で割る。\r
424          * @see #getDiffDateTime\r
425          */\r
426         public static long getCompareDateTime(String a, String b) {\r
427                 GregorianCalendar d = getCalendar(a);\r
428                 GregorianCalendar e = getCalendar(b);\r
429                 if ( d == null || e == null ) {\r
430                         return -1;\r
431                 }\r
432                 return getCompareDateTime(d.getTimeInMillis(), e.getTimeInMillis());\r
433         }\r
434 \r
435         /**\r
436          * <P>aとbの差をミリ秒で返す(正/負)\r
437          * <P>秒に直すなら 1000、分に直すなら 60000で割る。\r
438          * @see #getDiffDateTime\r
439          */\r
440         public static long getCompareDateTime(GregorianCalendar a, GregorianCalendar b) {\r
441                 return getCompareDateTime(a.getTimeInMillis(), b.getTimeInMillis());\r
442         }\r
443 \r
444         private static long getCompareDateTime(long x, long y) {\r
445                 return x-y;\r
446         }\r
447         \r
448         /**\r
449          * <P>aとbの差をミリ秒で返す(絶対値)\r
450          * <P>秒に直すなら 1000、分に直すなら 60000で割る。\r
451          * @see #getCompareDateTime\r
452          */\r
453         public static long getDiffDateTime(String a, String b) {\r
454                 GregorianCalendar d = getCalendar(a);\r
455                 GregorianCalendar e = getCalendar(b);\r
456                 if ( d == null || e == null ) {\r
457                         return -1;\r
458                 }\r
459                 return getDiffDateTime(d.getTimeInMillis(), e.getTimeInMillis());\r
460         }\r
461         \r
462         /**\r
463          * <P>aとbの差をミリ秒で返す\r
464          * <P>秒に直すなら 1000、分に直すなら 60000で割る。\r
465          */\r
466         public static long getDiffDateTime(GregorianCalendar a, GregorianCalendar b) {\r
467                 return getDiffDateTime(a.getTimeInMillis(), b.getTimeInMillis());\r
468         }\r
469         \r
470         private static long getDiffDateTime(long x, long y) {\r
471                 return ((x>y)?(x-y):(y-x));\r
472         }\r
473         \r
474 \r
475         /**\r
476          * 現在時刻+n秒のCalendarを返す\r
477          */\r
478         public static GregorianCalendar getCalendar(int n) {\r
479                 GregorianCalendar c = new GregorianCalendar();\r
480                 //c.setTime(new Date());\r
481                 c.add(Calendar.SECOND, n);\r
482                 return c;\r
483         }\r
484         /**\r
485          *  日付時刻文字列をCalendarに変換\r
486          *  @param date YYYY/MM/DD[(.)][ hh:mm[:ss]] or YYYY-MM-DD[Thh:mm[:ss]] or YYYYMMDD[hhmm[ss]]\r
487          */\r
488         public static GregorianCalendar getCalendar(String date) {\r
489                 Matcher ma = Pattern.compile("^(\\d\\d\\d\\d)[/-](\\d{1,2})[/-](\\d{1,2})(\\(.\\))?([ T](\\d{1,2}):(\\d{1,2})(:\\d{1,2})?)?$").matcher(date);\r
490                 if ( ! ma.find()) {\r
491                         ma = Pattern.compile("^(\\d\\d\\d\\d)(\\d\\d)(\\d\\d)()?((\\d\\d)(\\d\\d)(\\d\\d)?)?$").matcher(date);\r
492                         if ( ! ma.find()) {\r
493                                 return null;\r
494                         }\r
495                 }\r
496                 \r
497                 GregorianCalendar c = null;\r
498                 if ( ma.group(5) == null ) {\r
499                         c = new GregorianCalendar(\r
500                                         Integer.valueOf(ma.group(1)),\r
501                                         Integer.valueOf(ma.group(2))-1,\r
502                                         Integer.valueOf(ma.group(3)),\r
503                                         0,\r
504                                         0,\r
505                                         0);\r
506                 }\r
507                 else {\r
508                         c = new GregorianCalendar(\r
509                                         Integer.valueOf(ma.group(1)),\r
510                                         Integer.valueOf(ma.group(2))-1,\r
511                                         Integer.valueOf(ma.group(3)),\r
512                                         Integer.valueOf(ma.group(6)),\r
513                                         Integer.valueOf(ma.group(7)),\r
514                                         0);\r
515                 }\r
516                 return c;\r
517         }\r
518         \r
519         /**\r
520          *  現在日時+n秒を日付時刻形式に変換。\r
521          *  @param n : 負の値を許可する\r
522          *  @return YYYY/MM/DD hh:mm\r
523          */\r
524         public static String getDateTime(int n) {\r
525                 GregorianCalendar c = new GregorianCalendar();\r
526                 //c.setTime(new Date());\r
527                 c.add(Calendar.SECOND, n);\r
528                 return getDateTime(c);\r
529         }\r
530         \r
531         /**\r
532          *  日時を日付時刻形式に変換。曜日文字がつかない。\r
533          *  @see #getDateTimeW(GregorianCalendar)\r
534          *  @see #getIsoDateTime(GregorianCalendar)\r
535          *  @see #getDateTimeYMD(GregorianCalendar)\r
536          *  @return YYYY/MM/DD hh:mm\r
537          */\r
538         public static String getDateTime(GregorianCalendar c) {\r
539                 return new SimpleDateFormat("yyyy/MM/dd HH:mm").format(c.getTime());\r
540         }\r
541         \r
542         /**\r
543          *  現在日時+n秒を日付時刻形式に変換。曜日文字がつく。\r
544          *  @param n : 負の値を許可する\r
545          *  @return YYYY/MM/DD hh:mm\r
546          */\r
547         public static String getDateTimeW(int n) {\r
548                 GregorianCalendar c = new GregorianCalendar();\r
549                 //c.setTime(new Date());\r
550                 c.add(Calendar.SECOND, n);\r
551                 return getDateTimeW(c);\r
552         }\r
553         \r
554         /**\r
555          *  日時を日付時刻形式に変換。曜日文字がつく。\r
556          *  @see #getDateTime(GregorianCalendar)\r
557          *  @return YYYY/MM/DD(WD) hh:mm\r
558          */\r
559         public static String getDateTimeW(GregorianCalendar c) {\r
560                 return new SimpleDateFormat("yyyy/MM/dd('"+WDTPTN[c.get(Calendar.DAY_OF_WEEK)-1]+"') HH:mm").format(c.getTime());\r
561         }\r
562         \r
563         /**\r
564          *  日時を日付時刻形式に変換。ISO形式。秒まで返却。\r
565          *  @see #getDateTime(GregorianCalendar)\r
566          *  @return YYYY-MM-DDThh:mm:ss\r
567          */\r
568         public static String getIsoDateTime(GregorianCalendar c) {\r
569                 return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").format(c.getTime());\r
570         }\r
571 \r
572         /**\r
573          *  現在日時+n秒を日付時刻形式に変換。\r
574          *  @see #getDateTime(GregorianCalendar)\r
575          *  @param n : 負の値を許可する\r
576          *  @return YYYYMMDDhhmmss\r
577          */\r
578         public static String getDateTimeYMD(int n) {\r
579                 GregorianCalendar c = new GregorianCalendar();\r
580                 //c.setTime(new Date());\r
581                 if (n != 0) c.add(Calendar.SECOND, n);\r
582                 return getDateTimeYMD(c);\r
583         }\r
584         \r
585         /**\r
586          *  日時を日付時刻形式に変換。YMD形式。秒まで返却。\r
587          *  @see #getDateTime(GregorianCalendar)\r
588          *  @return YYYYMMDDhhmmss\r
589          */\r
590         public static String getDateTimeYMD(GregorianCalendar c) {\r
591                 return new SimpleDateFormat("yyyyMMddHHmmss").format(c.getTime());\r
592         }\r
593 \r
594         /**\r
595          *  日時を日付時刻形式に変換。YMD形式。ミリ秒まで返却。\r
596          *  @see #getDateTime(GregorianCalendar)\r
597          *  @return YYYYMMDDhhmmssSSS\r
598          */\r
599         public static String getDateTimeYMDx(GregorianCalendar c) {\r
600                 return new SimpleDateFormat("yyyyMMddHHmmssSSS").format(c.getTime());\r
601         }\r
602 \r
603         /**\r
604          * <P>「当日」の日付文字列を返します。\r
605          * <P>ただし、05時~29時を当日として判断するので、<B>24時~29時に実行した場合は前日の日付が返ります</B>。\r
606          * @param n : 現在日時に対して n秒 加えた日時を返します。負の値も許可されます。\r
607          * @param addwdstr : trueの場合、日付に曜日文字[これ->(日)]を加えます。\r
608          * @return YYYY/MM/DD[(WD)] hh:mm:ss\r
609          */\r
610         public static String getDate529(int n, boolean addwdstr) {\r
611                 GregorianCalendar c = getCalendar(0);\r
612                 c.add(Calendar.SECOND, n);\r
613                 return getDate529(c, addwdstr);\r
614         }\r
615         /**\r
616          * @see #getDate529(int, boolean)\r
617          */\r
618         public static String getDate529(String s, boolean addwdstr) {\r
619                 GregorianCalendar c = getCalendar(s);\r
620                 return getDate529(c, addwdstr);\r
621         }\r
622         /**\r
623          * @see #getDate529(int, boolean)\r
624          */\r
625         public static String getDate529(GregorianCalendar c, boolean addwdstr) {\r
626                 // 今日の範囲は05:00~04:59まで\r
627                 if ( isLateNight(c.get(Calendar.HOUR_OF_DAY)) ) {\r
628                         c.add(Calendar.DAY_OF_MONTH, -1);\r
629                 }\r
630                 return getDate(c, addwdstr);\r
631         }\r
632         \r
633         /**\r
634          * 日付を日付形式に変換。\r
635          * @return YYYY/MM/DD(WD)\r
636          */ \r
637         public static String getDate(GregorianCalendar c) {\r
638                 return getDate(c, true);\r
639         }\r
640         \r
641         /**\r
642          * 日付を日付形式に変換。\r
643          * @param addwdstr : trueの場合、日付に曜日文字[これ->(日)]を加えます。\r
644          * @return YYYY/MM/DD[(WD)]\r
645          */ \r
646         public static String getDate(GregorianCalendar c, boolean addwdstr) {\r
647                 if ( addwdstr ) {\r
648                         return new SimpleDateFormat("yyyy/MM/dd('"+WDTPTN[c.get(Calendar.DAY_OF_WEEK)-1]+"')").format(c.getTime());\r
649                 }\r
650                 else {\r
651                         return new SimpleDateFormat("yyyy/MM/dd").format(c.getTime());\r
652                 }\r
653         }\r
654         \r
655         /**\r
656          * 日付を日付形式に変換。\r
657          * @return YYYY/MM/DD(WD)\r
658          */ \r
659         public static String getDate() {\r
660                 return getDate(getCalendar(0), true);\r
661         }\r
662         /**\r
663          * <P>「当日」の日付文字列を返します。\r
664          * <P>ただし、05時~29時を当日として判断するので、<B>24時~29時に実行した場合は前日の日付が返ります</B>。\r
665          * @param n : 現在日時に対して n秒 加えた日時を返します。負の値も許可されます。\r
666          * @return YYYYMMDD\r
667          */\r
668         public static String getDateYMD529(int n) {\r
669                 GregorianCalendar c = new GregorianCalendar();\r
670                 //c.setTime(new Date());\r
671                 c.add(Calendar.SECOND, n);\r
672                 \r
673                 // 今日の範囲は05:00~04:59まで\r
674                 if (c.get(Calendar.HOUR_OF_DAY) < 5) {\r
675                         c.add(Calendar.DAY_OF_MONTH, -1);\r
676                 }\r
677                 \r
678                 return getDateYMD(c);\r
679         }\r
680         \r
681         /**\r
682          * 現在日付を日付形式に変換。\r
683          * @param n : 負の値を許可する。\r
684          * @return YYYYMMDD\r
685          */\r
686         public static String getDateYMD(int n) {\r
687                 GregorianCalendar ca = CommonUtils.getCalendar(n);\r
688                 return getDateYMD(ca);\r
689         }\r
690         \r
691         /**\r
692          * 現在日付を日付形式に変換。\r
693          * @return YYYYMMDD\r
694          */\r
695         public static String getDateYMD(GregorianCalendar c) {\r
696                 return new SimpleDateFormat("yyyyMMdd").format(c.getTime());\r
697         }\r
698         \r
699         /**\r
700          *  日時を時刻形式に変換\r
701          * @return hh:mm\r
702          */\r
703         public static String getTime(int n) {\r
704                 return getTime(getCalendar(n));\r
705         }\r
706         \r
707         /**\r
708          *  日時を時刻形式に変換\r
709          * @return hh:mm\r
710          */\r
711         public static String getTime(GregorianCalendar c) {\r
712                 return getTime(c.get(Calendar.HOUR_OF_DAY),c.get(Calendar.MINUTE));\r
713         }\r
714         \r
715         /**\r
716          *  日時を時刻形式に変換\r
717          * @see #getTimeHM(GregorianCalendar)\r
718          * @return hh:mm\r
719          */\r
720         public static String getTime(int hh, int mm) {\r
721                 return String.format("%02d:%02d",hh,mm);\r
722         }\r
723         \r
724         /**\r
725          *  日時を時刻形式に変換\r
726          *  @see #getTime(GregorianCalendar)\r
727          * @return hhmm\r
728          */\r
729         public static String getTimeHM(int n) {\r
730                 return getTimeHM(getCalendar(n));\r
731         }\r
732         \r
733         /**\r
734          *  日時を時刻形式に変換\r
735          *  @see #getTime(GregorianCalendar)\r
736          * @return hhmm\r
737          */\r
738         public static String getTimeHM(GregorianCalendar c) {\r
739                 return getTimeHM(c.get(Calendar.HOUR_OF_DAY),c.get(Calendar.MINUTE));\r
740         }\r
741         \r
742         /**\r
743          *  日時を時刻形式に変換\r
744          *  @see #getTime(GregorianCalendar)\r
745          * @return hhmm\r
746          */\r
747         public static String getTimeHM(int hh, int mm) {\r
748                 return String.format("%02d%02d",hh,mm);\r
749         }\r
750         \r
751         /**\r
752          * 時間帯の重複があるかどうかを判定します。\r
753          * @param adjnotrep : falseの場合、終了時刻と開始時刻が重なるものを重複として扱います。\r
754          */\r
755         public static boolean isOverlap(String start1, String end1, String start2, String end2, boolean adjnotrep) {\r
756                 if ( adjnotrep ) {\r
757                         return( ! (end1.compareTo(start2) <= 0 || end2.compareTo(start1) <= 0));\r
758                 }\r
759                 else {\r
760                         return( ! (end1.compareTo(start2) < 0 || end2.compareTo(start1) < 0));\r
761                 }\r
762         }\r
763         \r
764         \r
765         /*******************************************************************************\r
766          * Color関連\r
767          ******************************************************************************/\r
768         \r
769         /**\r
770          * 文字列を色化します。\r
771          * @param s : 色化する文字列 "#xxxxxx;" (R、G、B 各16進2ケタ)\r
772          * @return {@link Color}\r
773          * @see #color2str(Color c)\r
774          */\r
775         public static Color str2color(String s) {\r
776                 try {\r
777                         Matcher ma = Pattern.compile("#(..)(..)(..)").matcher(s);\r
778                         if ( ma.find() ) {\r
779                                 int r = Integer.decode("0x"+ma.group(1));\r
780                                 int g = Integer.decode("0x"+ma.group(2));\r
781                                 int b = Integer.decode("0x"+ma.group(3));\r
782                                 return(new Color(r,g,b));\r
783                         }\r
784                         return new Color(0,0,0);\r
785                 }\r
786                 catch (NumberFormatException e) {\r
787                         e.printStackTrace();\r
788                 }\r
789                 return null;\r
790         }\r
791         \r
792         /**\r
793          * 色を文字列化します。\r
794          * @param c : 文字列化する色({@link Color})\r
795          * @return "#xxxxxx;" (R、G、B 各16進2ケタ)\r
796          * @see #str2color(String) \r
797          */\r
798         public static String color2str(Color c) {\r
799                 return String.format("#%02x%02x%02x", c.getRed(), c.getGreen(), c.getBlue());\r
800         }\r
801         \r
802         \r
803         /*******************************************************************************\r
804          * 文字列操作関連\r
805          ******************************************************************************/\r
806          \r
807         public static String joinPath(String... path) {\r
808                 return joinStr(File.separator, path);\r
809         }\r
810 \r
811         public static String joinStr(String s, ArrayList<String> a) {\r
812                 return joinStr(s,a.toArray(new String[0]));\r
813         }\r
814         \r
815         public static String joinStr(String s, String... a) {\r
816                 if (a.length <= 0) {\r
817                         return "";\r
818                 }\r
819                 StringBuffer sb = new StringBuffer();\r
820                 for (int i=0; i<a.length-1; i++) {\r
821                         sb.append(a[i]);\r
822                         sb.append(s);\r
823                 }\r
824                 sb.append(a[a.length-1]);\r
825                 return(sb.toString());\r
826         }\r
827         \r
828         /**\r
829          * 文字数ではなく、バイト数でのsubstringを行います。\r
830          * @param s\r
831          * @param length\r
832          * @return\r
833          */\r
834         public static String substringrb(String s, int length) {\r
835                 StringBuilder sb = new StringBuilder();\r
836                 int len = 0;\r
837                 for ( Character c : s.toCharArray() ) {\r
838                         len += (c<256)?(1):(2);\r
839                         if (len > length) {\r
840                                 break;\r
841                         }\r
842                         sb.append(c.toString());\r
843                 }\r
844                 return(sb.toString());\r
845         }\r
846         \r
847         private static final char[] NGCharList = "\\/:*?\"<>|".toCharArray();\r
848         \r
849         /**\r
850          * ファイル名に使用できない文字の一覧を返します。\r
851          */\r
852         public static String getNGCharList() {\r
853                 return new String(NGCharList);\r
854         }\r
855         \r
856         /**\r
857          * ファイル名に使用できない文字が含まれているかどうか判定します。\r
858          */\r
859         public static boolean isNGChar(String s) {\r
860                 for (int i=0; i<NGCharList.length; i++) {\r
861                         if (s.indexOf(NGCharList[i]) >= 0) {\r
862                                 return(true);\r
863                         }\r
864                 }\r
865                 return(false);\r
866         }\r
867         \r
868         /**\r
869          * ファイル名に使用できない文字をHTMLエスケープ(&#ddd;)します。\r
870          * @see #unEscape(String)\r
871          */\r
872         public static String escapeFilename(String src) {\r
873                 for (int i=0; i<NGCharList.length; i++) {\r
874                         src = src.replaceAll(String.format("\\%s",String.valueOf(NGCharList[i])), String.format("&#%03d;", (int)NGCharList[i]));\r
875                 }\r
876                 return src;\r
877         }\r
878 \r
879         /**\r
880          * HTMLエスケープをデコードします。\r
881          */\r
882         public static String unEscape(String src) {\r
883                 String dst = src.replaceAll("&quot;", "\"");\r
884                 dst = dst.replaceAll("&lt;", "<");\r
885                 dst = dst.replaceAll("&gt;", ">");\r
886                 dst = dst.replaceAll("&amp;", "&");\r
887                 dst = dst.replaceAll("&nbsp;", " ");\r
888                 dst = dst.replaceAll("〜", "~");\r
889                 dst = dst.replaceAll("−", "-");\r
890                 HashMap<String, String> ek = new HashMap<String, String>();\r
891                 Matcher ma = Pattern.compile("(&#(\\d+);)").matcher(src);\r
892                 while (ma.find()) {\r
893                         ek.put(ma.group(1), Character.valueOf((char)(int)Integer.valueOf(ma.group(2))).toString());\r
894                 }\r
895                 for (Entry<String, String> kv : ek.entrySet()) {\r
896                         dst = dst.replaceAll(kv.getKey(), kv.getValue());\r
897                 }\r
898                 return dst;\r
899         }\r
900         \r
901         public static String enEscape(String src) {\r
902                 StringBuilder sb = new StringBuilder();\r
903                 for ( int index=0; index<src.length(); index++ ) {\r
904                         char c = src.charAt(index);\r
905                         if ( c == '<' ) {\r
906                                 sb.append("&lt;");\r
907                         }\r
908                         else if ( c == '>' ) {\r
909                                 sb.append("&gt;");\r
910                         }\r
911                         else if ( c == '&' ) {\r
912                                 sb.append("&amp;");\r
913                         }\r
914                         else {\r
915                                 sb.append(c);\r
916                         }\r
917                 }\r
918                 return sb.toString();\r
919         }\r
920         \r
921         \r
922         /**\r
923          *  Unicodeエスケープをデコードします。\r
924          */\r
925         public static String unUniEscape(String src) {\r
926                 Matcher ma = Pattern.compile("\\\\u[0-9a-f]{4}").matcher(src);\r
927                 StringBuffer sb = new StringBuffer(src.length());\r
928                 while (ma.find()) {\r
929                         char[] chars = ma.group().substring(2, 6).toCharArray();\r
930                         int hex = 0;\r
931                         for (char c : chars) {\r
932                                 hex = hex << 4;\r
933                                 if ('a' <= c && c <= 'f') {\r
934                                         hex += c - 'a' + 10;\r
935                                 }\r
936                                 else {\r
937                                         hex += c - '0';\r
938                                 }\r
939                         }\r
940                         ma.appendReplacement(sb, ""+(char)hex);\r
941                 }\r
942                 ma.appendTail(sb);\r
943                 return sb.toString();\r
944         }\r
945         \r
946         \r
947         /**\r
948          * 文字列中の全角数字を半角数字に置き換えます\r
949          */\r
950         public static String toHANUM(String numTmp) {\r
951                 if (numTmp == null) return null;\r
952                 \r
953                 StringBuilder sb = new StringBuilder();\r
954                 for ( int i=0; i<numTmp.length(); i++ ) {\r
955                         char c = numTmp.charAt(i);\r
956                         if ( '0' <= c && c <= '9' ) {\r
957                                 c = (char)(c -  '0' + '0' );\r
958                         }\r
959                         sb.append(c);\r
960                 }\r
961                 return sb.toString();\r
962         }\r
963         \r
964         public static String toHANALNUM(String alnumTmp) {\r
965                 if (alnumTmp == null) return null;\r
966                 \r
967                 StringBuilder sb = new StringBuilder();\r
968                 for ( int i=0; i<alnumTmp.length(); i++ ) {\r
969                         char c = alnumTmp.charAt(i);\r
970                         if ( 'a' <= c && c <= 'z' ) {\r
971                                 c = (char)(c - 'a' + 'a' );\r
972                         }\r
973                         else if ( 'A' <= c && c <= 'Z' ) {\r
974                                 c = (char)(c -  'A' + 'A' );\r
975                         }\r
976                         else if ( '0' <= c && c <= '9' ) {\r
977                                 c = (char)(c -  '0' + '0' );\r
978                         }\r
979                         else if ( c == '(' ) {\r
980                                 c = '(';\r
981                         }\r
982                         else if ( c == ')' ) {\r
983                                 c = ')';\r
984                         }\r
985                         else if ( c == '-' ) {\r
986                                 c = '-';\r
987                         }\r
988                         else if ( c == ' ' ) {\r
989                                 c = ' ';\r
990                         }\r
991                         sb.append(c);\r
992                 }\r
993                 return sb.toString();\r
994         }\r
995 \r
996         \r
997         public static String getVerticalSplittedHTML(String text) {\r
998                 if ( text == null ) {\r
999                         return null;\r
1000                 }\r
1001                 \r
1002                 String html = "<HTML>";\r
1003                 for ( String s : text.split("") ) {\r
1004                         html += s+"<BR>";\r
1005                 }\r
1006                 html += "</HTML>";\r
1007                 \r
1008                 return html;\r
1009         }\r
1010         \r
1011         \r
1012         /*******************************************************************************\r
1013          * オブジェクト操作関連\r
1014          ******************************************************************************/\r
1015 \r
1016         /*******************************************************************************\r
1017          * JavaVM関連\r
1018          ******************************************************************************/\r
1019 \r
1020         /**\r
1021          * デバッグ用にスタックトレースをとりたいなー\r
1022          */\r
1023         public static void printStackTrace() {\r
1024                 if ( ! debug) return;\r
1025                 \r
1026                 new Throwable().printStackTrace();\r
1027         }\r
1028         \r
1029         /*******************************************************************************\r
1030          * OS操作関連\r
1031          ******************************************************************************/\r
1032 \r
1033         // なぜJavaなのに機種別のコードをかかなければならないのか…\r
1034         public static boolean isMac() { return ismac; }\r
1035         public static boolean isLinux() { return islinux; }\r
1036         public static boolean isWindows() { return iswindows; }\r
1037         public static boolean isWindowsXP() { return iswindowsxp; }\r
1038         \r
1039         private static final boolean ismac              = ((String)System.getProperty("os.name")).toLowerCase().replaceAll(" ", "").startsWith("macosx");\r
1040         private static final boolean islinux    = ((String)System.getProperty("os.name")).toLowerCase().replaceAll(" ", "").startsWith("linux");\r
1041         private static final boolean iswindows  = ((String)System.getProperty("os.name")).toLowerCase().replaceAll(" ", "").startsWith("windows");\r
1042         private static final boolean iswindowsxp= ((String)System.getProperty("os.name")).toLowerCase().replaceAll(" ", "").startsWith("windowsxp");\r
1043         \r
1044         // ミリ秒単位でsleep\r
1045         public static void milSleep(int i) {\r
1046                 try {\r
1047                         Thread.sleep(i);\r
1048                 }\r
1049                 catch (InterruptedException e) {\r
1050                         System.err.println("[スリープ] なんかあったのか");\r
1051                         e.printStackTrace();\r
1052                 }\r
1053         }\r
1054         \r
1055         /**\r
1056          * コマンドを実行する\r
1057          * @see #getCommandResult()\r
1058          * @param run : コマンドの指定\r
1059          * @return -1 : 失敗、-1以外 : コマンドのexit値\r
1060          */\r
1061         public static int executeCommand(String run)    {\r
1062                 \r
1063                 commandResult = null;\r
1064                 \r
1065                 ArrayList<String> list = new ArrayList<String>();\r
1066                 Matcher ma = Pattern.compile("((\"([^\"]*?)\"|([^\"]+?))(\\s+|$))").matcher(run);\r
1067                 while (ma.find()) {\r
1068                         if (ma.group(3) != null) {\r
1069                                 list.add(ma.group(3));\r
1070                         }\r
1071                         else {\r
1072                                 list.add(ma.group(4));\r
1073                         }\r
1074                 }\r
1075                 if ( list.size() == 0 ) {\r
1076                         System.err.println("[外部コマンド] 実行できません: "+run);\r
1077                         return -1;\r
1078                 }\r
1079                 else {\r
1080                         ProcessBuilder pb = null;\r
1081                         Process p = null;\r
1082                         \r
1083                         InputStream is = null;\r
1084                         InputStreamReader isr = null;\r
1085                         BufferedReader br =  null;\r
1086         \r
1087                         try {\r
1088                                 pb = new ProcessBuilder(list);\r
1089                                 pb.redirectErrorStream(true);\r
1090                                 \r
1091                                 p = pb.start();\r
1092                                 p.getOutputStream().close();    // 入力はしない\r
1093                                 \r
1094                                 String encoding = (isWindows())?("MS932"):("UTF-8");\r
1095                                 \r
1096                                 StringBuilder sb = new StringBuilder();\r
1097                                 is = p.getInputStream();\r
1098                                 isr = new InputStreamReader(is,encoding);\r
1099                                 br =  new BufferedReader(isr);\r
1100                                 String s;\r
1101                                 while ((s=br.readLine()) != null) {\r
1102                                         sb.append(s);\r
1103                                         sb.append("\n");\r
1104                                 }\r
1105                                 commandResult = sb.toString();\r
1106                                 \r
1107                                 System.out.println("--- 外部コマンドを実行します ---");\r
1108                                 System.out.println(commandResult);\r
1109                                 System.out.println("--- 外部コマンドを実行しました ---");\r
1110                                 \r
1111                                 p.waitFor();    // is.read()で判定できるので不要\r
1112                                 \r
1113                                 int retval = p.exitValue();\r
1114                                 \r
1115                                 return retval;\r
1116                         }\r
1117                         catch ( IOException e ) {\r
1118                                 System.err.println("[外部コマンド] 失敗しました: "+run);\r
1119                                 e.printStackTrace();\r
1120                         }\r
1121                         catch ( InterruptedException e ) {\r
1122                                 System.err.println("[外部コマンド] 失敗しました: "+run);\r
1123                                 e.printStackTrace();\r
1124                         }\r
1125                         finally {\r
1126                                 closing(br);\r
1127                                 closing(isr);\r
1128                                 closing(is);\r
1129                                 \r
1130                                 if ( p != null ) {\r
1131                                         closing(p.getInputStream());\r
1132                                         closing(p.getErrorStream());\r
1133                                         p.destroy();\r
1134                                 }\r
1135                         }\r
1136                 }\r
1137                 \r
1138                 return -1;\r
1139         }\r
1140         \r
1141         public static String getCommandResult() { return commandResult; }\r
1142         \r
1143         private static String commandResult;\r
1144 \r
1145         /**\r
1146          * 登録されたアプリケーションでファイルを開く\r
1147          */\r
1148         public static String openFile(String file)      {\r
1149                 String errmsg = null;\r
1150                 try {\r
1151                         if ( useRundll32 && isWindows() ) {\r
1152                                 Runtime runtime = Runtime.getRuntime(); \r
1153                                 runtime.exec("rundll32 url.dll,FileProtocolHandler "+new File(file).getAbsolutePath());\r
1154                         }\r
1155                         else {\r
1156                                 Desktop desktop = Desktop.getDesktop();\r
1157                                 desktop.open(new File(file));\r
1158                         }\r
1159                 }\r
1160                 catch (UnsupportedOperationException e) {\r
1161                         System.err.println("[アプリケーションでファイルを開く] 失敗しました: "+file);\r
1162                         e.printStackTrace();\r
1163                         errmsg = e.toString();\r
1164                 }\r
1165                 catch (IOException e) {\r
1166                         System.err.println("[アプリケーションでファイルを開く] 失敗しました: "+file);\r
1167                         e.printStackTrace();\r
1168                         errmsg = e.toString();\r
1169                 }\r
1170                 return errmsg;\r
1171         }\r
1172         \r
1173         \r
1174         /*******************************************************************************\r
1175          * ファイルI/O関連\r
1176          ******************************************************************************/\r
1177         \r
1178         // 古くないかどうか\r
1179         public static boolean isFileAvailable(File f, int days) {\r
1180                 // 存在するか\r
1181                 if ( ! f.exists() ) {\r
1182                         return false;\r
1183                 }\r
1184                 \r
1185                 // 最近更新されているか\r
1186                 long lm = f.lastModified();\r
1187                 GregorianCalendar cal = new GregorianCalendar();\r
1188                 cal.setTimeInMillis(lm);\r
1189                 if ( getCompareDateTime(cal, getCalendar(-days*86400)) < 0 ) {\r
1190                         return false;\r
1191                 }\r
1192                         \r
1193                 return true;\r
1194         }\r
1195         \r
1196         // ディレクトリをまるっと削除\r
1197         public static boolean rmdir(File f) {\r
1198                 if( ! f.exists()) {\r
1199                         return false;\r
1200                 }\r
1201                 \r
1202                 if (f.isFile()){\r
1203                         return f.delete();\r
1204                 }\r
1205                 else if (f.isDirectory()) {\r
1206                         File[] files = f.listFiles();\r
1207                         for (File file : files){\r
1208                                 if ( ! rmdir(file)) {\r
1209                                         return false;\r
1210                                 }\r
1211                         }\r
1212                         return f.delete();\r
1213                 }\r
1214                 \r
1215                 return false;   // ここには来ないはず\r
1216         }\r
1217         \r
1218         // カウンタの記録\r
1219         public static boolean saveCnt(int cnt, String filename) {\r
1220                 if ( ! write2file(filename, String.valueOf(cnt)) ) {\r
1221                         System.out.println("[カウンタファイル] 書き込めませんでした: "+filename);\r
1222                         return false;\r
1223                 }\r
1224                 return true;\r
1225         }\r
1226         public static int loadCnt(String filename) {\r
1227                 if ( ! new File(filename).exists() ) {\r
1228                         return -1;\r
1229                 }\r
1230                 \r
1231                 try {\r
1232                         String str = read4file(filename, true);\r
1233                         if ( str != null ) {\r
1234                                 return Integer.valueOf(str);\r
1235                         }\r
1236                 }\r
1237                 catch ( NumberFormatException e ) {\r
1238                         System.err.println("[カウンタファイル] 内容が不正です: "+filename);\r
1239                 }\r
1240                 \r
1241                 System.err.println("[カウンタファイル] 読み込めませんでした: "+filename);\r
1242                 return -1;\r
1243         }\r
1244         \r
1245         // ロック・アンロック\r
1246         \r
1247         /**\r
1248          *  ロック\r
1249          */\r
1250         public static boolean getLock() {\r
1251                 FileOutputStream fos = null;\r
1252                 FileChannel fc = null;\r
1253                 try {\r
1254                         fos = new FileOutputStream(new File("_lock_"));\r
1255                         fc = fos.getChannel();\r
1256                         lock = fc.tryLock();\r
1257                         if ( lock == null ) {\r
1258                                 System.err.println("[多重起動禁止] ロックされています.");\r
1259                                 return false;\r
1260                         }\r
1261                         else {\r
1262                                 return true;\r
1263                         }\r
1264                 }\r
1265                 catch (FileNotFoundException e) {\r
1266                         System.err.println("[多重起動禁止] ロックの取得に失敗しました.");\r
1267                         e.printStackTrace();\r
1268                 }\r
1269                 catch (IOException e) {\r
1270                         System.err.println("[多重起動禁止] ロックの取得に失敗しました.");\r
1271                         e.printStackTrace();\r
1272                 }\r
1273                 finally {\r
1274                         //closing(fos);\r
1275                         //closing(fc);\r
1276                 }\r
1277                 return false;\r
1278         }\r
1279         \r
1280         /**\r
1281          *  アンロック\r
1282          */\r
1283         public static void getUnlock() {\r
1284                 try {\r
1285                         if ( lock != null ) {\r
1286                                 lock.release();\r
1287                         }\r
1288                 } catch (IOException e) {\r
1289                         System.err.println("[多重起動禁止] ロックの解放に失敗しました.");\r
1290                         e.printStackTrace();\r
1291                 }\r
1292         }\r
1293 \r
1294         private static FileLock lock = null;\r
1295 \r
1296         /**\r
1297          *  テキストをファイルに書き出す(エンコードはデフォルト)\r
1298          */\r
1299         public static boolean write2file(String fname, String dat) {\r
1300                 return write2file(fname, dat, null);\r
1301         }\r
1302         \r
1303         /**\r
1304          *  テキストをファイルに書き出す(エンコードは指定による)\r
1305          */\r
1306         public static boolean write2file(String fname, String dat, String encoding) {\r
1307                 if ( fname.matches(".*\\.zip$") ) {\r
1308                         return _write2zip(fname, dat, encoding);\r
1309                 }\r
1310                 else {\r
1311                         return _write2file(fname, dat, encoding);\r
1312                 }\r
1313         }\r
1314         private static boolean _write2zip(String fname, String dat, String encoding) {\r
1315                 {\r
1316                         FileOutputStream os = null;\r
1317                         BufferedOutputStream bos = null;\r
1318                         ZipOutputStream zos = null;\r
1319                         try {\r
1320                                 // 一時ファイルに書き出し\\r
1321                                 os = new FileOutputStream(fname+".tmp");\r
1322                                 bos = new BufferedOutputStream(os);\r
1323                                 zos = new ZipOutputStream(bos);\r
1324                                 \r
1325                                 byte[] buf = null;\r
1326                                 if ( encoding == null ) {\r
1327                                         // デフォルトエンコーディングで\r
1328                                         buf = dat.getBytes();\r
1329                                 }\r
1330                                 else {\r
1331                                         // 指定エンコーディングで\r
1332                                         buf = dat.getBytes(encoding);\r
1333                                 }\r
1334                                 \r
1335                                 ZipEntry ze = new ZipEntry(ZIPENTRY);\r
1336                                 ze.setSize(buf.length);\r
1337                                 \r
1338                                 zos.putNextEntry(ze);\r
1339                                 zos.write(buf);\r
1340                                 \r
1341                         // 処理が続くので閉じないとアカン!\r
1342                                 zos.closeEntry();\r
1343                             zos.close(); zos = null;\r
1344                         if (bos!=null) { bos.close(); bos = null; }\r
1345                         if (os!=null) { os.close(); os = null; }\r
1346                                 \r
1347                                 // キャッシュファイルに変換\r
1348                             File o = new File(fname);\r
1349                             if ( o.exists() && ! o.delete() ) {\r
1350                                 System.err.println("削除できないよ: "+fname);\r
1351                             }\r
1352                             File n = new File(fname+".tmp");\r
1353                             if ( ! n.renameTo(o) ) {\r
1354                                 System.err.println("リネームできないよ: "+fname);\r
1355                             }\r
1356                         }\r
1357                         catch (Exception e) {\r
1358                                 // 例外\r
1359                                 System.out.println("書けないよ: "+e.toString());\r
1360                                 return false;\r
1361                         }\r
1362                         finally {\r
1363                                 closing(zos);\r
1364                                 closing(bos);\r
1365                                 closing(os);\r
1366                         }\r
1367                 }\r
1368                 return true;\r
1369         }\r
1370         private static boolean _write2file(String fname, String dat, String encoding) {\r
1371                 {\r
1372                         Writer wr = null;\r
1373                         BufferedWriter bw = null;\r
1374                         FileOutputStream os = null;\r
1375                         try {\r
1376                                 // 一時ファイルに書き出し\r
1377                                 if ( encoding == null ) {\r
1378                                         // デフォルトエンコーディングで\r
1379                                         wr = new FileWriter(fname+".tmp");\r
1380                                 }\r
1381                                 else {\r
1382                                         // 指定エンコーディングで\r
1383                                         os = new FileOutputStream(new File(fname+".tmp"));\r
1384                                         wr = new OutputStreamWriter(os, encoding); \r
1385                                 }\r
1386                                 bw = new BufferedWriter(wr);\r
1387                         bw.write(dat);\r
1388                         \r
1389                         // 処理が続くので閉じないとアカン!\r
1390                             bw.close(); bw = null;\r
1391                         wr.close(); wr = null;\r
1392                         if (os!=null) { os.close(); os = null; }\r
1393                                 \r
1394                                 // キャッシュファイルに変換\r
1395                             File o = new File(fname);\r
1396                             if ( o.exists() && ! o.delete() ) {\r
1397                                 System.err.println("削除できないよ: "+fname);\r
1398                             }\r
1399                             File n = new File(fname+".tmp");\r
1400                             if ( ! n.renameTo(o) ) {\r
1401                                 System.err.println("リネームできないよ: "+fname);\r
1402                             }\r
1403                         }\r
1404                         catch (Exception e) {\r
1405                                 // 例外\r
1406                                 System.out.println("書けないよ: "+e.toString());\r
1407                                 return false;\r
1408                         }\r
1409                         finally {\r
1410                                 closing(bw);\r
1411                                 closing(wr);\r
1412                                 closing(os);\r
1413                         }\r
1414                 }\r
1415                 return true;\r
1416         }\r
1417         \r
1418         private static final String ZIPENTRY = "compressed.dat";\r
1419         \r
1420         /**\r
1421          *  テキストをファイルを読み出す(エンコードはデフォルト)\r
1422          */\r
1423         public static String read4file(String fname, boolean nocr) {\r
1424                 return read4file(fname, nocr, null);\r
1425         }\r
1426 \r
1427         /**\r
1428          *  テキストをファイルを読み出す(エンコードは指定による)\r
1429          */\r
1430         public static String read4file(String fname, boolean nocr, String encoding) {\r
1431                 if ( fname.matches(".*\\.zip$") ) {\r
1432                         return _read4zip(fname, nocr, null);\r
1433                 }\r
1434                 else {\r
1435                         return _read4file(fname, nocr, null);\r
1436                 }\r
1437         }\r
1438         private static String _read4zip(String fname, boolean nocr, String encoding) {\r
1439                 String response = null;\r
1440                 {\r
1441                         ZipFile zf = null;\r
1442                         Reader rd = null;\r
1443                         InputStream is = null;\r
1444                         BufferedReader br = null;\r
1445                         try {\r
1446                                 // ファイルから読み出し\r
1447                                 zf = new ZipFile(fname);\r
1448                                 ZipEntry ze = zf.getEntry(ZIPENTRY);\r
1449                                 if ( ze == null ) {\r
1450                                         System.out.println("ZIPファイルがおかしい");\r
1451                                         return null;\r
1452                                 }\r
1453                                 \r
1454                                 is = zf.getInputStream(ze);\r
1455                                 \r
1456                                 // ファイルから読み出し\r
1457                                 if ( encoding == null ) {\r
1458                                         // デフォルトエンコーディングで\r
1459                                         rd = new InputStreamReader(is); \r
1460                                 }\r
1461                                 else {\r
1462                                         // 指定エンコーディングで\r
1463                                         rd = new InputStreamReader(is, encoding); \r
1464                                 }\r
1465                                 br = new BufferedReader(rd);\r
1466                                 \r
1467                                 String str;\r
1468                                 StringBuilder sb = new StringBuilder();\r
1469                                 while ((str = br.readLine()) != null) {\r
1470                                         sb.append(str);\r
1471                                         if ( ! nocr ) sb.append("\n");\r
1472                                 }\r
1473                                 \r
1474                                 response = sb.toString();\r
1475                         }\r
1476                         catch (Exception e) {\r
1477                                 // 例外\r
1478                                 System.out.println("読めないよ: "+e.toString());\r
1479                                 return null;\r
1480                         }\r
1481                         finally {\r
1482                                 closing(is);\r
1483                                 closing(br);\r
1484                                 closing(rd);\r
1485                                 closing(zf);\r
1486                         }\r
1487                 }\r
1488                 return response;\r
1489         }\r
1490         private static String _read4file(String fname, boolean nocr, String encoding) {\r
1491                 String response = null;\r
1492                 {\r
1493                         Reader rd = null;\r
1494                         BufferedReader br = null;\r
1495                         FileInputStream is = null;\r
1496                         try {\r
1497                                 // ファイルから読み出し\r
1498                                 if ( encoding == null ) {\r
1499                                         // デフォルトエンコーディングで\r
1500                                         rd = new FileReader(fname);\r
1501                                 }\r
1502                                 else {\r
1503                                         // 指定エンコーディングで\r
1504                                         is = new FileInputStream(new File(fname));\r
1505                                         rd = new InputStreamReader(is, encoding); \r
1506                                 }\r
1507                                 br = new BufferedReader(rd);\r
1508                                 \r
1509                                 String str;\r
1510                                 StringBuilder sb = new StringBuilder();\r
1511                                 while ((str = br.readLine()) != null) {\r
1512                                         sb.append(str);\r
1513                                         if ( ! nocr ) sb.append("\n");\r
1514                                 }\r
1515                                 \r
1516                                 response = sb.toString();\r
1517                         }\r
1518                         catch (Exception e) {\r
1519                                 // 例外\r
1520                                 System.out.println("読めないよ: "+e.toString());\r
1521                                 return null;\r
1522                         }\r
1523                         finally {\r
1524                                 closing(br);\r
1525                                 closing(rd);\r
1526                                 closing(is);\r
1527                         }\r
1528                 }\r
1529                 return response;\r
1530         }\r
1531 \r
1532         /**\r
1533          *  XMLEncoderでシリアライズしてファイルに出力する\r
1534          */\r
1535         public static boolean writeXML(String fname, Object obj) {\r
1536                 boolean done = true;\r
1537                 {\r
1538                         FileOutputStream fos = null;\r
1539                         BufferedOutputStream bos = null;\r
1540                         XMLEncoder enc = null;\r
1541                         try {\r
1542                                 fos = new FileOutputStream(fname+".tmp");\r
1543                                 bos = new BufferedOutputStream(fos);\r
1544                                 enc = new XMLEncoder(bos);\r
1545                                 enc.writeObject(obj);\r
1546                                 \r
1547                         // 処理が続くので閉じないとアカン!\r
1548                                 enc.close(); enc = null;\r
1549                                 bos.close(); bos = null;\r
1550                                 fos.close(); fos = null;\r
1551                                 \r
1552                                 // キャッシュファイルに変換\r
1553                             File o = new File(fname);\r
1554                             if ( o.exists() && ! o.delete() ) {\r
1555                                 System.err.println("削除できないよ: "+fname);\r
1556                             }\r
1557                             File n = new File(fname+".tmp");\r
1558                             if ( ! n.renameTo(o) ) {\r
1559                                 System.err.println("リネームできないよ: "+fname);\r
1560                             }\r
1561                         }\r
1562                         catch (Exception e) {\r
1563                                 // 例外\r
1564                                 done = false;\r
1565                                 System.err.println(e.toString());\r
1566                         }\r
1567                         finally {\r
1568                                 closing(enc);\r
1569                                 closing(fos);\r
1570                                 closing(bos);\r
1571                         }\r
1572                 }\r
1573                 return done;\r
1574         }\r
1575         \r
1576         /**\r
1577          * XMLDecorderでシリアライズしたファイルを読みだす(オブジェクトを返す場合)\r
1578          */\r
1579         public static Object readXML(String fname) {\r
1580                 {\r
1581                         XMLDecoder dec = null;\r
1582                         FileInputStream fis = null;\r
1583                         BufferedInputStream bis = null;\r
1584                         try {\r
1585                                 fis = new FileInputStream(fname);\r
1586                                 bis = new BufferedInputStream(fis);\r
1587                                 dec = new XMLDecoder(bis);\r
1588                                 return dec.readObject();\r
1589                         }\r
1590                         catch (Exception e) {\r
1591                                 // 例外\r
1592                                 System.err.println(e.toString());\r
1593                         }\r
1594                         finally {\r
1595                                 closing(dec);\r
1596                                 closing(bis);\r
1597                                 closing(fis);\r
1598                         }\r
1599                 }\r
1600                 return null;\r
1601         }\r
1602         \r
1603         /**\r
1604          * XMLDecorderでシリアライズしたファイルを読みだす(既存のオブジェクトに値を入れて返す場合)\r
1605          */\r
1606         public static boolean readXML(String fname, Object obj) {\r
1607                 \r
1608                 Object tmp = readXML(fname);\r
1609                 if ( tmp == null ) {\r
1610                         return false;\r
1611                 }\r
1612                 \r
1613                 return FieldUtils.deepCopy(obj, tmp);\r
1614         }\r
1615 \r
1616         /*\r
1617          * finallyブロックで書き間違えそうなので\r
1618          */\r
1619         public static void closing(Reader r) {\r
1620                 if ( r != null ) try { r.close(); } catch (Exception e) {}\r
1621         }\r
1622         public static void closing(InputStream r) {\r
1623                 if ( r != null ) try { r.close(); } catch (Exception e) {}\r
1624         }\r
1625         public static void closing(ZipFile r) {\r
1626                 if ( r != null ) try { r.close(); } catch (Exception e) {}\r
1627         }\r
1628         public static void closing(XMLDecoder r) {\r
1629                 if ( r != null ) r.close();\r
1630         }\r
1631         \r
1632         public static void closing(Writer w) {\r
1633                 if ( w != null ) try { w.close(); } catch (Exception e) {}\r
1634         }\r
1635         public static void closing(OutputStream w) {\r
1636                 if ( w != null ) try { w.close(); } catch (Exception e) {}\r
1637         }\r
1638         public static void closing(XMLEncoder w) {\r
1639                 if ( w != null ) w.close();\r
1640         }\r
1641         \r
1642         public static void closing(FileChannel fc) {\r
1643                 if ( fc != null ) try { fc.close(); } catch (Exception e) {}\r
1644         }\r
1645         \r
1646         public static void closing(Socket sock) {\r
1647                 if ( sock != null ) try { sock.close(); } catch (Exception e) {}\r
1648         }\r
1649         public static void closing(HttpURLConnection ucon) {\r
1650                 if ( ucon != null ) ucon.disconnect();\r
1651         }\r
1652 }\r