View Javadoc
1   /*
2    * Copyright 2013 the original author or authors.
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, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.orangesignal.csv;
18  
19  import java.io.Closeable;
20  import java.io.File;
21  import java.io.FileInputStream;
22  import java.io.FileOutputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.InputStreamReader;
26  import java.io.OutputStream;
27  import java.io.OutputStreamWriter;
28  import java.io.Reader;
29  import java.io.Writer;
30  import java.util.ArrayList;
31  import java.util.Enumeration;
32  import java.util.List;
33  import java.util.zip.ZipEntry;
34  import java.util.zip.ZipFile;
35  import java.util.zip.ZipInputStream;
36  import java.util.zip.ZipOutputStream;
37  
38  import com.orangesignal.jlha.LhaFile;
39  import com.orangesignal.jlha.LhaHeader;
40  import com.orangesignal.jlha.LhaInputStream;
41  import com.orangesignal.jlha.LhaOutputStream;
42  
43  /**
44   * 区切り文字形式データの統合アクセスユーティリティを提供します。
45   *
46   * @author Koji Sugisawa
47   */
48  public abstract class Csv {
49  
50  	/**
51  	 * デフォルトコンストラクタです。
52  	 */
53  	protected Csv() {
54  	}
55  
56  	// ------------------------------------------------------------------------
57  	// static load
58  
59  	/**
60  	 * 指定された区切り文字形式入力ストリームを読込み、
61  	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
62  	 *
63  	 * @param reader 区切り文字形式入力ストリーム
64  	 * @param handler 区切り文字形式データアクセスハンドラ
65  	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
66  	 * @throws IOException 入出力エラーが発生した場合
67  	 */
68  	public static <T> T load(final CsvReader reader, final CsvHandler<T> handler) throws IOException {
69  		return handler.load(reader);
70  	}
71  
72  	/**
73  	 * 指定された文字入力ストリームを読込み、
74  	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
75  	 *
76  	 * @param reader 文字入力ストリーム
77  	 * @param cfg 区切り文字形式情報
78  	 * @param handler 区切り文字形式データアクセスハンドラ
79  	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
80  	 * @throws IOException 入出力エラーが発生した場合
81  	 */
82  	public static <T> T load(final Reader reader, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
83  		return load(new CsvReader(reader, cfg), handler);
84  	}
85  
86  	/**
87  	 * 指定された入力ストリームを指定されたエンコーディングで読込み、
88  	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
89  	 *
90  	 * @param in 入力ストリーム
91  	 * @param encoding エンコーディング
92  	 * @param cfg 区切り文字形式情報
93  	 * @param handler 区切り文字形式データアクセスハンドラ
94  	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
95  	 * @throws IOException 入出力エラーが発生した場合
96  	 */
97  	public static <T> T load(final InputStream in, final String encoding, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
98  		return load(new InputStreamReader(in, encoding), cfg, handler);
99  	}
100 
101 	/**
102 	 * 指定された入力ストリームをプラットフォームのデフォルトエンコーディングで読込み、
103 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
104 	 *
105 	 * @param in 入力ストリーム
106 	 * @param cfg 区切り文字形式情報
107 	 * @param handler 区切り文字形式データアクセスハンドラ
108 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
109 	 * @throws IOException 入出力エラーが発生した場合
110 	 */
111 	public static <T> T load(final InputStream in, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
112 		return load(new InputStreamReader(in), cfg, handler);
113 	}
114 
115 	/**
116 	 * 指定されたファイルを指定されたエンコーディングで読込み、
117 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
118 	 *
119 	 * @param file 入力ファイル
120 	 * @param encoding エンコーディング
121 	 * @param cfg 区切り文字形式情報
122 	 * @param handler 区切り文字形式データアクセスハンドラ
123 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
124 	 * @throws IOException 入出力エラーが発生した場合
125 	 */
126 	public static <T> T load(final File file, final String encoding, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
127 		final InputStream in = new FileInputStream(file);
128 		try {
129 			return load(in, encoding, cfg, handler);
130 		} finally {
131 			closeQuietly(in);
132 		}
133 	}
134 
135 	/**
136 	 * 指定されたファイルをプラットフォームのデフォルトエンコーディングで読込み、
137 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
138 	 *
139 	 * @param file 入力ファイル
140 	 * @param cfg 区切り文字形式情報
141 	 * @param handler 区切り文字形式データアクセスハンドラ
142 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
143 	 * @throws IOException 入出力エラーが発生した場合
144 	 */
145 	public static <T> T load(final File file, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
146 		final InputStream in = new FileInputStream(file);
147 		try {
148 			return load(in, cfg, handler);
149 		} finally {
150 			closeQuietly(in);
151 		}
152 	}
153 
154 	// ------------------------------------------------------------------------
155 	// static load (compress support)
156 
157 	/**
158 	 * 指定された LHA 入力ストリームから指定されたフィルタの基準を満たす LHA エントリを指定されたエンコーディングで読込み、
159 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
160 	 *
161 	 * @param in LHA 入力ストリーム
162 	 * @param encoding エンコーディング
163 	 * @param cfg 区切り文字形式情報
164 	 * @param handler 区切り文字形式データアクセスハンドラ
165 	 * @param filter LHA エントリフィルタ
166 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
167 	 * @throws IOException 入出力エラーが発生した場合
168 	 * @since 1.2.1
169 	 */
170 	public static <T> List<T> load(final LhaInputStream in, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler, final LhaEntryFilter filter) throws IOException {
171 		final List<T> list = new ArrayList<T>();
172 		LhaHeader entry;
173 		while ((entry = in.getNextEntry()) != null) {
174 			try {
175 				if (filter != null && !filter.accept(entry)) {
176 					continue;
177 				}
178 				list.addAll(handler.load(new CsvReader(new InputStreamReader(in, encoding), cfg), true));
179 			} finally {
180 				in.closeEntry();
181 			}
182 		}
183 		return handler.processScalar(list);
184 	}
185 
186 	/**
187 	 * 指定された LHA 入力ストリームからすべての LHA エントリを指定されたエンコーディングで読込み、
188 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
189 	 *
190 	 * @param in LHA 入力ストリーム
191 	 * @param encoding エンコーディング
192 	 * @param cfg 区切り文字形式情報
193 	 * @param handler 区切り文字形式データアクセスハンドラ
194 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
195 	 * @throws IOException 入出力エラーが発生した場合
196 	 * @since 1.2.1
197 	 */
198 	public static <T> List<T> load(final LhaInputStream in, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler) throws IOException {
199 		return load(in, encoding, cfg, handler, null);
200 	}
201 
202 	/**
203 	 * 指定された LHA 入力ストリームから指定されたフィルタの基準を満たす LHA エントリをプラットフォームのデフォルトエンコーディングで読込み、
204 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
205 	 *
206 	 * @param in LHA 入力ストリーム
207 	 * @param cfg 区切り文字形式情報
208 	 * @param handler 区切り文字形式データアクセスハンドラ
209 	 * @param filter LHA エントリフィルタ
210 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
211 	 * @throws IOException 入出力エラーが発生した場合
212 	 */
213 	public static <T> List<T> load(final LhaInputStream in, final CsvConfig cfg, final CsvListHandler<T> handler, final LhaEntryFilter filter) throws IOException {
214 		final List<T> list = new ArrayList<T>();
215 		LhaHeader entry;
216 		while ((entry = in.getNextEntry()) != null) {
217 			try {
218 				if (filter != null && !filter.accept(entry)) {
219 					continue;
220 				}
221 				list.addAll(handler.load(new CsvReader(new InputStreamReader(in), cfg), true));
222 			} finally {
223 				in.closeEntry();
224 			}
225 		}
226 		return handler.processScalar(list);
227 	}
228 
229 	/**
230 	 * 指定された LHA 入力ストリームからすべての LHA エントリをプラットフォームのデフォルトエンコーディングで読込み、
231 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
232 	 *
233 	 * @param in LHA 入力ストリーム
234 	 * @param cfg 区切り文字形式情報
235 	 * @param handler 区切り文字形式データアクセスハンドラ
236 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
237 	 * @throws IOException 入出力エラーが発生した場合
238 	 */
239 	public static <T> List<T> load(final LhaInputStream in, final CsvConfig cfg, final CsvListHandler<T> handler) throws IOException {
240 		return load(in, cfg, handler, null);
241 	}
242 
243 	/**
244 	 * 指定された LHA ファイルから指定されたフィルタの基準を満たす LHA エントリを指定されたエンコーディングで読込み、
245 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
246 	 *
247 	 * @param lhaFile LHA ファイル
248 	 * @param encoding エンコーディング
249 	 * @param cfg 区切り文字形式情報
250 	 * @param handler 区切り文字形式データアクセスハンドラ
251 	 * @param filter LHA エントリフィルタ
252 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
253 	 * @throws IOException 入出力エラーが発生した場合
254 	 * @since 1.2.1
255 	 */
256 	public static <T> List<T> load(final LhaFile lhaFile, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler, final LhaEntryFilter filter) throws IOException {
257 		final List<T> list = new ArrayList<T>();
258 		final LhaHeader[] entries = lhaFile.getEntries();
259 		for (final LhaHeader entry : entries) {
260 			if (filter != null && !filter.accept(entry)) {
261 				continue;
262 			}
263 			list.addAll(handler.load(new CsvReader(new InputStreamReader(lhaFile.getInputStream(entry), encoding), cfg), true));
264 		}
265 		return handler.processScalar(list);
266 	}
267 
268 	/**
269 	 * 指定された LHA ファイルからすべての LHA エントリを指定されたエンコーディングで読込み、
270 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
271 	 *
272 	 * @param lhaFile LHA ファイル
273 	 * @param encoding エンコーディング
274 	 * @param cfg 区切り文字形式情報
275 	 * @param handler 区切り文字形式データアクセスハンドラ
276 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
277 	 * @throws IOException 入出力エラーが発生した場合
278 	 * @since 1.2.1
279 	 */
280 	public static <T> List<T> load(final LhaFile lhaFile, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler) throws IOException {
281 		return load(lhaFile, encoding, cfg, handler, null);
282 	}
283 
284 	/**
285 	 * 指定された LHA ファイルから指定されたフィルタの基準を満たす LHA エントリをプラットフォームのデフォルトエンコーディングで読込み、
286 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
287 	 *
288 	 * @param lhaFile LHA ファイル
289 	 * @param cfg 区切り文字形式情報
290 	 * @param handler 区切り文字形式データアクセスハンドラ
291 	 * @param filter LHA エントリフィルタ
292 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
293 	 * @throws IOException 入出力エラーが発生した場合
294 	 */
295 	public static <T> List<T> load(final LhaFile lhaFile, final CsvConfig cfg, final CsvListHandler<T> handler, final LhaEntryFilter filter) throws IOException {
296 		final List<T> list = new ArrayList<T>();
297 		final LhaHeader[] entries = lhaFile.getEntries();
298 		for (final LhaHeader entry : entries) {
299 			if (filter != null && !filter.accept(entry)) {
300 				continue;
301 			}
302 			list.addAll(handler.load(new CsvReader(new InputStreamReader(lhaFile.getInputStream(entry)), cfg), true));
303 		}
304 		return handler.processScalar(list);
305 	}
306 
307 	/**
308 	 * 指定された LHA ファイルからすべての LHA エントリをプラットフォームのデフォルトエンコーディングで読込み、
309 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
310 	 *
311 	 * @param lhaFile LHA ファイル
312 	 * @param cfg 区切り文字形式情報
313 	 * @param handler 区切り文字形式データアクセスハンドラ
314 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
315 	 * @throws IOException 入出力エラーが発生した場合
316 	 */
317 	public static <T> List<T> load(final LhaFile lhaFile, final CsvConfig cfg, final CsvListHandler<T> handler) throws IOException {
318 		return load(lhaFile, cfg, handler, null);
319 	}
320 
321 	/**
322 	 * 指定された ZIP 入力ストリームから指定されたフィルタの基準を満たす ZIP エントリを指定されたエンコーディングで読込み、
323 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
324 	 *
325 	 * @param in ZIP 入力ストリーム
326 	 * @param encoding エンコーディング
327 	 * @param cfg 区切り文字形式情報
328 	 * @param handler 区切り文字形式データアクセスハンドラ
329 	 * @param filter ZIP エントリフィルタ
330 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
331 	 * @throws IOException 入出力エラーが発生した場合
332 	 * @since 1.2.1
333 	 */
334 	public static <T> List<T> load(final ZipInputStream in, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler, final ZipEntryFilter filter) throws IOException {
335 		final List<T> list = new ArrayList<T>();
336 		ZipEntry entry;
337 		while ((entry = in.getNextEntry()) != null) {
338 			try {
339 				if (filter != null && !filter.accept(entry)) {
340 					continue;
341 				}
342 				list.addAll(handler.load(new CsvReader(new InputStreamReader(in, encoding), cfg), true));
343 			} finally {
344 				in.closeEntry();
345 			}
346 		}
347 		return handler.processScalar(list);
348 	}
349 
350 	/**
351 	 * 指定された ZIP 入力ストリームからすべての ZIP エントリを指定されたエンコーディングで読込み、
352 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
353 	 *
354 	 * @param in ZIP 入力ストリーム
355 	 * @param encoding エンコーディング
356 	 * @param cfg 区切り文字形式情報
357 	 * @param handler 区切り文字形式データアクセスハンドラ
358 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
359 	 * @throws IOException 入出力エラーが発生した場合
360 	 * @since 1.2.1
361 	 */
362 	public static <T> List<T> load(final ZipInputStream in, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler) throws IOException {
363 		return load(in, encoding, cfg, handler, null);
364 	}
365 
366 	/**
367 	 * 指定された ZIP 入力ストリームから指定されたフィルタの基準を満たす ZIP エントリをプラットフォームのデフォルトエンコーディングで読込み、
368 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
369 	 *
370 	 * @param in ZIP 入力ストリーム
371 	 * @param cfg 区切り文字形式情報
372 	 * @param handler 区切り文字形式データアクセスハンドラ
373 	 * @param filter ZIP エントリフィルタ
374 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
375 	 * @throws IOException 入出力エラーが発生した場合
376 	 */
377 	public static <T> List<T> load(final ZipInputStream in, final CsvConfig cfg, final CsvListHandler<T> handler, final ZipEntryFilter filter) throws IOException {
378 		final List<T> list = new ArrayList<T>();
379 		ZipEntry entry;
380 		while ((entry = in.getNextEntry()) != null) {
381 			try {
382 				if (filter != null && !filter.accept(entry)) {
383 					continue;
384 				}
385 				list.addAll(handler.load(new CsvReader(new InputStreamReader(in), cfg), true));
386 			} finally {
387 				in.closeEntry();
388 			}
389 		}
390 		return handler.processScalar(list);
391 	}
392 
393 	/**
394 	 * 指定された ZIP 入力ストリームからすべての ZIP エントリをプラットフォームのデフォルトエンコーディングで読込み、
395 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
396 	 *
397 	 * @param in ZIP 入力ストリーム
398 	 * @param cfg 区切り文字形式情報
399 	 * @param handler 区切り文字形式データアクセスハンドラ
400 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
401 	 * @throws IOException 入出力エラーが発生した場合
402 	 */
403 	public static <T> List<T> load(final ZipInputStream in, final CsvConfig cfg, final CsvListHandler<T> handler) throws IOException {
404 		return load(in, cfg, handler, null);
405 	}
406 
407 	/**
408 	 * 指定された ZIP ファイルから指定されたフィルタの基準を満たす ZIP エントリを指定されたエンコーディングで読込み、
409 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
410 	 *
411 	 * @param zipFile ZIP ファイル
412 	 * @param encoding エンコーディング
413 	 * @param cfg 区切り文字形式情報
414 	 * @param handler 区切り文字形式データアクセスハンドラ
415 	 * @param filter ZIP エントリフィルタ
416 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
417 	 * @throws IOException 入出力エラーが発生した場合
418 	 * @since 1.2.1
419 	 */
420 	public static <T> List<T> load(final ZipFile zipFile, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler, final ZipEntryFilter filter) throws IOException {
421 		final List<T> list = new ArrayList<T>();
422 		final Enumeration<? extends ZipEntry> entries = zipFile.entries();
423 		while (entries.hasMoreElements()) {
424 			final ZipEntry entry = entries.nextElement();
425 			if (filter != null && !filter.accept(entry)) {
426 				continue;
427 			}
428 			final InputStream in = zipFile.getInputStream(entry);
429 			try {
430 				list.addAll(handler.load(new CsvReader(new InputStreamReader(in, encoding), cfg), true));
431 			} finally {
432 				closeQuietly(in);
433 			}
434 		}
435 		return handler.processScalar(list);
436 	}
437 
438 	/**
439 	 * 指定された ZIP ファイルからすべての ZIP エントリを指定されたエンコーディングで読込み、
440 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
441 	 *
442 	 * @param zipFile ZIP ファイル
443 	 * @param encoding エンコーディング
444 	 * @param cfg 区切り文字形式情報
445 	 * @param handler 区切り文字形式データアクセスハンドラ
446 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
447 	 * @throws IOException 入出力エラーが発生した場合
448 	 * @since 1.2.1
449 	 */
450 	public static <T> List<T> load(final ZipFile zipFile, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler) throws IOException {
451 		return load(zipFile, encoding, cfg, handler, null);
452 	}
453 
454 	/**
455 	 * 指定された ZIP ファイルから指定されたフィルタの基準を満たす ZIP エントリをプラットフォームのデフォルトエンコーディングで読込み、
456 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
457 	 *
458 	 * @param zipFile ZIP ファイル
459 	 * @param cfg 区切り文字形式情報
460 	 * @param handler 区切り文字形式データアクセスハンドラ
461 	 * @param filter ZIP エントリフィルタ
462 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
463 	 * @throws IOException 入出力エラーが発生した場合
464 	 */
465 	public static <T> List<T> load(final ZipFile zipFile, final CsvConfig cfg, final CsvListHandler<T> handler, final ZipEntryFilter filter) throws IOException {
466 		final List<T> list = new ArrayList<T>();
467 		final Enumeration<? extends ZipEntry> entries = zipFile.entries();
468 		while (entries.hasMoreElements()) {
469 			final ZipEntry entry = entries.nextElement();
470 			if (filter != null && !filter.accept(entry)) {
471 				continue;
472 			}
473 			final InputStream in = zipFile.getInputStream(entry);
474 			try {
475 				list.addAll(handler.load(new CsvReader(new InputStreamReader(in), cfg), true));
476 			} finally {
477 				closeQuietly(in);
478 			}
479 		}
480 		return handler.processScalar(list);
481 	}
482 
483 	/**
484 	 * 指定された ZIP ファイルからすべての ZIP エントリをプラットフォームのデフォルトエンコーディングで読込み、
485 	 * ハンドラによって変換された区切り文字形式データのインスタンスを返します。
486 	 *
487 	 * @param zipFile ZIP ファイル
488 	 * @param cfg 区切り文字形式情報
489 	 * @param handler 区切り文字形式データアクセスハンドラ
490 	 * @return ハンドラによって変換された区切り文字形式データのインスタンス
491 	 * @throws IOException 入出力エラーが発生した場合
492 	 */
493 	public static <T> List<T> load(final ZipFile zipFile, final CsvConfig cfg, final CsvListHandler<T> handler) throws IOException {
494 		return load(zipFile, cfg, handler, null);
495 	}
496 
497 	// ------------------------------------------------------------------------
498 	// static save
499 
500 	/**
501 	 * 指定された区切り文字形式データのインスタンスを
502 	 * ハンドラによって変換して指定された区切り文字形式出力ストリームへ書込みます。
503 	 *
504 	 * @param obj 区切り文字形式データのインスタンス
505 	 * @param writer 区切り文字形式出力ストリーム
506 	 * @param handler 区切り文字形式データアクセスハンドラ
507 	 * @throws IOException 入出力エラーが発生した場合
508 	 */
509 	public static <T> void save(final T obj, final CsvWriter writer, final CsvHandler<T> handler) throws IOException {
510 		handler.save(obj, writer);
511 		writer.flush();
512 	}
513 
514 	/**
515 	 * 指定された区切り文字形式データのインスタンスを
516 	 * ハンドラによって変換して指定された文字出力ストリームへ書込みます。
517 	 *
518 	 * @param obj 区切り文字形式データのインスタンス
519 	 * @param writer 文字出力ストリーム
520 	 * @param cfg 区切り文字形式情報
521 	 * @param handler 区切り文字形式データアクセスハンドラ
522 	 * @throws IOException 入出力エラーが発生した場合
523 	 */
524 	public static <T> void save(final T obj, final Writer writer, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
525 		save(obj, new CsvWriter(writer, cfg), handler);
526 	}
527 
528 	/**
529 	 * 指定された区切り文字形式データのインスタンスを
530 	 * ハンドラによって変換して指定された出力ストリームへ指定されたエンコーディングで書込みます。
531 	 *
532 	 * @param obj 区切り文字形式データのインスタンス
533 	 * @param out 出力ストリーム
534 	 * @param encoding エンコーディング
535 	 * @param cfg 区切り文字形式情報
536 	 * @param handler 区切り文字形式データアクセスハンドラ
537 	 * @throws IOException 入出力エラーが発生した場合
538 	 */
539 	public static <T> void save(final T obj, final OutputStream out, final String encoding, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
540 		save(obj, new OutputStreamWriter(out, encoding), cfg, handler);
541 	}
542 
543 	/**
544 	 * 指定された区切り文字形式データのインスタンスを
545 	 * ハンドラによって変換して指定された出力ストリームへプラットフォームのデフォルトエンコーディングで書込みます。
546 	 *
547 	 * @param obj 区切り文字形式データのインスタンス
548 	 * @param out 出力ストリーム
549 	 * @param cfg 区切り文字形式情報
550 	 * @param handler 区切り文字形式データアクセスハンドラ
551 	 * @throws IOException 入出力エラーが発生した場合
552 	 */
553 	public static <T> void save(final T obj, final OutputStream out, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
554 		save(obj, new OutputStreamWriter(out), cfg, handler);
555 	}
556 
557 	/**
558 	 * 指定された区切り文字形式データのインスタンスを
559 	 * ハンドラによって変換して指定されたファイルへ指定されたエンコーディングで書込みます。
560 	 *
561 	 * @param obj 区切り文字形式データのインスタンス
562 	 * @param file 出力ファイル
563 	 * @param encoding エンコーディング
564 	 * @param cfg 区切り文字形式情報
565 	 * @param handler 区切り文字形式データアクセスハンドラ
566 	 * @throws IOException 入出力エラーが発生した場合
567 	 */
568 	public static <T> void save(final T obj, final File file, final String encoding, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
569 		final OutputStream out = new FileOutputStream(file);
570 		try {
571 			save(obj, out, encoding, cfg, handler);
572 		} finally {
573 			closeQuietly(out);
574 		}
575 	}
576 
577 	/**
578 	 * 指定された区切り文字形式データのインスタンスを
579 	 * ハンドラによって変換して指定されたファイルへプラットフォームのデフォルトエンコーディングで書込みます。
580 	 *
581 	 * @param obj 区切り文字形式データのインスタンス
582 	 * @param file 出力ファイル
583 	 * @param cfg 区切り文字形式情報
584 	 * @param handler 区切り文字形式データアクセスハンドラ
585 	 * @throws IOException 入出力エラーが発生した場合
586 	 */
587 	public static <T> void save(final T obj, final File file, final CsvConfig cfg, final CsvHandler<T> handler) throws IOException {
588 		final OutputStream out = new FileOutputStream(file);
589 		try {
590 			save(obj, out, cfg, handler);
591 		} finally {
592 			closeQuietly(out);
593 		}
594 	}
595 
596 	// ------------------------------------------------------------------------
597 	// static save (compress support)
598 
599 	/**
600 	 * 指定された区切り文字形式データのインスタンスを
601 	 * ハンドラによって変換して指定された LHA 出力ストリームへ指定されたエンコーディングで指定された LHA エントリを書込みます。
602 	 * 
603 	 * @param obj 区切り文字形式データのインスタンス
604 	 * @param out LHA 出力ストリーム
605 	 * @param encoding エンコーディング
606 	 * @param cfg 区切り文字形式情報
607 	 * @param handler 区切り文字形式データアクセスハンドラ
608 	 * @param entryName 作成する LHA エントリ名
609 	 * @throws IOException 入出力エラーが発生した場合
610 	 * @since 1.2.1
611 	 */
612 	public static <T> void save(final List<T> obj, final LhaOutputStream out, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler, final String entryName) throws IOException {
613 		out.putNextEntry(new LhaHeader(entryName));
614 		try {
615 			save(obj, out, encoding, cfg, handler);
616 		} finally {
617 			out.closeEntry();
618 		}
619 	}
620 
621 	/**
622 	 * 指定された区切り文字形式データのインスタンスを
623 	 * ハンドラによって変換して指定された LHA 出力ストリームへプラットフォームのデフォルトエンコーディングで指定された LHA エントリを書込みます。
624 	 * 
625 	 * @param obj 区切り文字形式データのインスタンス
626 	 * @param out LHA 出力ストリーム
627 	 * @param cfg 区切り文字形式情報
628 	 * @param handler 区切り文字形式データアクセスハンドラ
629 	 * @param entryName 作成する LHA エントリ名
630 	 * @throws IOException 入出力エラーが発生した場合
631 	 */
632 	public static <T> void save(final List<T> obj, final LhaOutputStream out, final CsvConfig cfg, final CsvListHandler<T> handler, final String entryName) throws IOException {
633 		out.putNextEntry(new LhaHeader(entryName));
634 		try {
635 			save(obj, out, cfg, handler);
636 		} finally {
637 			out.closeEntry();
638 		}
639 	}
640 
641 	/**
642 	 * 指定された区切り文字形式データのインスタンスを
643 	 * ハンドラによって変換して指定された ZIP 出力ストリームへ指定されたエンコーディングで指定された ZIP エントリを書込みます。
644 	 * 
645 	 * @param obj 区切り文字形式データのインスタンス
646 	 * @param out ZIP 出力ストリーム
647 	 * @param encoding エンコーディング
648 	 * @param cfg 区切り文字形式情報
649 	 * @param handler 区切り文字形式データアクセスハンドラ
650 	 * @param entryName 作成する ZIP エントリ名
651 	 * @throws IOException 入出力エラーが発生した場合
652 	 * @since 1.2.1
653 	 */
654 	public static <T> void save(final List<T> obj, final ZipOutputStream out, final String encoding, final CsvConfig cfg, final CsvListHandler<T> handler, final String entryName) throws IOException {
655 		out.putNextEntry(new ZipEntry(entryName));
656 		try {
657 			save(obj, out, encoding, cfg, handler);
658 		} finally {
659 			out.closeEntry();
660 		}
661 	}
662 
663 	/**
664 	 * 指定された区切り文字形式データのインスタンスを
665 	 * ハンドラによって変換して指定された ZIP 出力ストリームへプラットフォームのデフォルトエンコーディングで指定された ZIP エントリを書込みます。
666 	 * 
667 	 * @param obj 区切り文字形式データのインスタンス
668 	 * @param out ZIP 出力ストリーム
669 	 * @param cfg 区切り文字形式情報
670 	 * @param handler 区切り文字形式データアクセスハンドラ
671 	 * @param entryName 作成する ZIP エントリ名
672 	 * @throws IOException 入出力エラーが発生した場合
673 	 */
674 	public static <T> void save(final List<T> obj, final ZipOutputStream out, final CsvConfig cfg, final CsvListHandler<T> handler, final String entryName) throws IOException {
675 		out.putNextEntry(new ZipEntry(entryName));
676 		try {
677 			save(obj, out, cfg, handler);
678 		} finally {
679 			out.closeEntry();
680 		}
681 	}
682 
683 	// ------------------------------------------------------------------------
684 	// closeQuietly
685 
686 	/**
687 	 * 無条件に、<code>Closeable</code> を閉じます。
688 	 *
689 	 * @param closeable Closeable オブジェクト
690 	 */
691 	protected static void closeQuietly(final Closeable closeable) {
692 		try {
693 			if (closeable != null) {
694 				closeable.close();
695 			}
696 		} catch (final IOException e) {
697 			// 無視する
698 		}
699 	}
700 
701 }