1 package charactermanaj.model.io;
\r
4 import java.io.IOException;
\r
5 import java.io.OutputStream;
\r
6 import java.io.UnsupportedEncodingException;
\r
7 import java.nio.charset.Charset;
\r
8 import java.nio.charset.CharsetEncoder;
\r
9 import java.nio.charset.CodingErrorAction;
\r
11 import org.apache.tools.zip.ZipEntry;
\r
12 import org.apache.tools.zip.ZipOutputStream;
\r
14 import charactermanaj.model.AppConfig;
\r
17 public class CharacterDataZipFileWriter extends AbstractCharacterDataArchivedFileWriter {
\r
22 protected ZipOutputStream zipOutStm;
\r
27 protected CharsetEncoder enc;
\r
32 protected String rootPrefix = "";
\r
35 public CharacterDataZipFileWriter(File outFile) throws IOException {
\r
38 AppConfig appConfig = AppConfig.getInstance();
\r
39 String zipNameEncoding = appConfig.getZipNameEncoding();
\r
41 // コンストラクタにストリームではなくファイル名を指定することで、
\r
42 // 内部でランダムアクセスファイルを使うようになるためヘッダのCRCチェックの書き込み等で有利
\r
43 this.zipOutStm = new ZipOutputStream(tmpFile);
\r
45 // ファイル名の文字コードを設定する.
\r
46 // (JDKの標準のZipOutputStreamはUTF-8になるが、一般的にはMS932が多いため、Apache Antのものを借用し指定する.)
\r
47 this.enc = Charset.forName(zipNameEncoding).newEncoder();
\r
48 zipOutStm.setEncoding(zipNameEncoding);
\r
49 enc.onUnmappableCharacter(CodingErrorAction.REPORT);
\r
51 // zipの場合、根本に1つフォルダをたてておく.
\r
52 // 一般的なフォルダ圧縮したものと体裁をそろえるため.
\r
53 String fname = outFile.getName();
\r
54 int extpos = fname.lastIndexOf('.');
\r
55 if (extpos > 0) { // ドットで始まる名前の場合は無視
\r
56 fname = fname.substring(0, extpos);
\r
58 setRootPrefix(fname);
\r
61 public void setRootPrefix(String rootPrefix) {
\r
62 if (rootPrefix == null || rootPrefix.trim().equals("/")) {
\r
65 if (rootPrefix.length() > 0 && !rootPrefix.endsWith("/")) {
\r
68 this.rootPrefix = rootPrefix.trim();
\r
71 public String getRootPrefix() {
\r
76 protected void closeEntry() throws IOException {
\r
77 zipOutStm.closeEntry();
\r
81 protected OutputStream getOutputStream() throws IOException {
\r
86 protected void putNextEntry(String name, long lastModified)
\r
87 throws IOException {
\r
89 // ルートプレフィックスをすべてのエントリの登録時に付与する.
\r
90 String fname = rootPrefix + name;
\r
92 // ファイル名がキャラクターセットに合致するか?
\r
96 ZipEntry entry = new ZipEntry(fname);
\r
97 if (lastModified > 0) {
\r
98 entry.setTime(lastModified);
\r
100 zipOutStm.putNextEntry(entry);
\r
103 protected void internalClose() throws IOException {
\r
108 * ファイル名がエンコーディング可能であるかチェックする.<br>
\r
109 * @param name チェックする名前
\r
110 * @throws IOException ファイル名が不正である場合
\r
111 * @throws UnsupportedEncodingException ファイル名がエンコーディングできない場合
\r
113 protected void checkName(String name) throws UnsupportedEncodingException, IOException {
\r
114 if (name == null || name.length() == 0) {
\r
115 throw new IOException("missing entry name");
\r
117 if (!enc.canEncode(name)) {
\r
118 throw new UnsupportedEncodingException("file name encoding error.: " + name);
\r