blob: 135afab3733e80747bb1f5d854358471b746ea2b [file] [log] [blame]
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -07001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070018package javax.imageio.stream;
19
20import java.io.IOException;
21import java.io.File;
22import java.io.OutputStream;
23import java.io.RandomAccessFile;
24
25/**
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080026 * The FileCacheImageOutputStream class is an implementation of
27 * ImageOutputStream that writes to its OutputStream using a temporary file as a
28 * cache.
29 *
30 * @since Android 1.0
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070031 */
32public class FileCacheImageOutputStream extends ImageOutputStreamImpl {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080033
34 /**
35 * The Constant IIO_TEMP_FILE_PREFIX.
36 */
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070037 static final String IIO_TEMP_FILE_PREFIX = "iioCache";
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080038
39 /**
40 * The Constant MAX_BUFFER_LEN.
41 */
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070042 static final int MAX_BUFFER_LEN = 1048575; // 1 MB - is it not too much?
43
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080044 /**
45 * The os.
46 */
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070047 private OutputStream os;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080048
49 /**
50 * The file.
51 */
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070052 private File file;
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080053
54 /**
55 * The raf.
56 */
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070057 private RandomAccessFile raf;
58
59 /**
60 * Instantiates a FileCacheImageOutputStream.
61 *
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -080062 * @param stream
63 * the OutputStream for writing.
64 * @param cacheDir
65 * the cache directory where the cache file will be created.
66 * @throws IOException
67 * if an I/O exception has occurred.
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -070068 */
69 public FileCacheImageOutputStream(OutputStream stream, File cacheDir) throws IOException {
70 if (stream == null) {
71 throw new IllegalArgumentException("stream == null!");
72 }
73 os = stream;
74
75 if (cacheDir == null || cacheDir.isDirectory()) {
76 file = File.createTempFile(IIO_TEMP_FILE_PREFIX, null, cacheDir);
77 file.deleteOnExit();
78 } else {
79 throw new IllegalArgumentException("Not a directory!");
80 }
81
82 raf = new RandomAccessFile(file, "rw");
83 }
84
85 @Override
86 public void close() throws IOException {
87 flushBefore(raf.length());
88 super.close();
89 raf.close();
90 file.delete();
91 }
92
93 @Override
94 public boolean isCached() {
95 return true;
96 }
97
98 @Override
99 public boolean isCachedFile() {
100 return true;
101 }
102
103 @Override
104 public boolean isCachedMemory() {
105 return false;
106 }
107
108 @Override
109 public void write(int b) throws IOException {
110 flushBits(); // See the flushBits method description
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800111
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700112 raf.write(b);
113 streamPos++;
114 }
115
116 @Override
117 public void write(byte[] b, int off, int len) throws IOException {
118 flushBits(); // See the flushBits method description
119
120 raf.write(b, off, len);
121 streamPos += len;
122 }
123
124 @Override
125 public int read() throws IOException {
126 bitOffset = 0; // Should reset
127
128 int res = raf.read();
129 if (res >= 0) {
130 streamPos++;
131 }
132
133 return res;
134 }
135
136 @Override
137 public int read(byte[] b, int off, int len) throws IOException {
138 bitOffset = 0;
139
140 int numRead = raf.read(b, off, len);
141 if (numRead > 0) {
142 streamPos += numRead;
143 }
144
145 return numRead;
146 }
147
148 @Override
149 public void flushBefore(long pos) throws IOException {
150 long readFromPos = flushedPos;
151 super.flushBefore(pos);
152
153 long bytesToRead = pos - readFromPos;
154 raf.seek(readFromPos);
155
156 if (bytesToRead < MAX_BUFFER_LEN) {
157 byte buffer[] = new byte[(int)bytesToRead];
158 raf.readFully(buffer);
159 os.write(buffer);
160 } else {
161 byte buffer[] = new byte[MAX_BUFFER_LEN];
162 while (bytesToRead > 0) {
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800163 int count = (int)Math.min(MAX_BUFFER_LEN, bytesToRead);
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700164 raf.readFully(buffer, 0, count);
165 os.write(buffer, 0, count);
166 bytesToRead -= count;
167 }
168 }
169
170 os.flush();
171
172 if (pos != streamPos) {
173 raf.seek(streamPos); // Reset the position
174 }
175 }
176
177 @Override
178 public void seek(long pos) throws IOException {
179 if (pos < flushedPos) {
180 throw new IndexOutOfBoundsException();
181 }
182
183 raf.seek(pos);
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800184 streamPos = raf.getFilePointer();
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700185 bitOffset = 0;
186 }
187
188 @Override
189 public long length() {
190 try {
191 return raf.length();
The Android Open Source Projecte09fd9e2008-12-17 18:05:43 -0800192 } catch (IOException e) {
The Android Open Source Project7c1b96a2008-10-21 07:00:00 -0700193 return -1L;
194 }
195 }
196}