10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.io;
27
28 import java.nio.channels.FileChannel;
29 import sun.nio.ch.FileChannelImpl;
30
31
32 /**
33 * A file output stream is an output stream for writing data to a
34 * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
35 * a file is available or may be created depends upon the underlying
36 * platform. Some platforms, in particular, allow a file to be opened
37 * for writing by only one <tt>FileOutputStream</tt> (or other
38 * file-writing object) at a time. In such situations the constructors in
39 * this class will fail if the file involved is already open.
40 *
41 * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
42 * such as image data. For writing streams of characters, consider using
43 * <code>FileWriter</code>.
44 *
45 * @author Arthur van Hoff
46 * @see java.io.File
47 * @see java.io.FileDescriptor
48 * @see java.io.FileInputStream
49 * @see java.nio.file.Files#newOutputStream
50 * @since JDK1.0
51 */
52 public
53 class FileOutputStream extends OutputStream
54 {
55 /**
56 * The system dependent file descriptor.
57 */
58 private final FileDescriptor fd;
59
60 /**
61 * True if the file is opened for append.
62 */
63 private final boolean append;
64
65 /**
66 * The associated channel, initalized lazily.
67 */
68 private FileChannel channel;
69
70 private final Object closeLock = new Object();
71 private volatile boolean closed = false;
72 private static final ThreadLocal<Boolean> runningFinalize =
73 new ThreadLocal<>();
74
75 private static boolean isRunningFinalize() {
76 Boolean val;
77 if ((val = runningFinalize.get()) != null)
78 return val.booleanValue();
79 return false;
80 }
190 * <code>checkWrite</code> method denies write access
191 * to the file.
192 * @see java.io.File#getPath()
193 * @see java.lang.SecurityException
194 * @see java.lang.SecurityManager#checkWrite(java.lang.String)
195 * @since 1.4
196 */
197 public FileOutputStream(File file, boolean append)
198 throws FileNotFoundException
199 {
200 String name = (file != null ? file.getPath() : null);
201 SecurityManager security = System.getSecurityManager();
202 if (security != null) {
203 security.checkWrite(name);
204 }
205 if (name == null) {
206 throw new NullPointerException();
207 }
208 this.fd = new FileDescriptor();
209 this.append = append;
210
211 fd.incrementAndGetUseCount();
212 open(name, append);
213 }
214
215 /**
216 * Creates a file output stream to write to the specified file
217 * descriptor, which represents an existing connection to an actual
218 * file in the file system.
219 * <p>
220 * First, if there is a security manager, its <code>checkWrite</code>
221 * method is called with the file descriptor <code>fdObj</code>
222 * argument as its argument.
223 * <p>
224 * If <code>fdObj</code> is null then a <code>NullPointerException</code>
225 * is thrown.
226 * <p>
227 * This constructor does not throw an exception if <code>fdObj</code>
228 * is {@link java.io.FileDescriptor#valid() invalid}.
229 * However, if the methods are invoked on the resulting stream to attempt
230 * I/O on the stream, an <code>IOException</code> is thrown.
231 *
232 * @param fdObj the file descriptor to be opened for writing
233 * @exception SecurityException if a security manager exists and its
234 * <code>checkWrite</code> method denies
235 * write access to the file descriptor
236 * @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
237 */
238 public FileOutputStream(FileDescriptor fdObj) {
239 SecurityManager security = System.getSecurityManager();
240 if (fdObj == null) {
241 throw new NullPointerException();
242 }
243 if (security != null) {
244 security.checkWrite(fdObj);
245 }
246 this.fd = fdObj;
247 this.append = false;
248
249 /*
250 * FileDescriptor is being shared by streams.
251 * Ensure that it's GC'ed only when all the streams/channels are done
252 * using it.
253 */
254 fd.incrementAndGetUseCount();
255 }
256
257 /**
258 * Opens a file, with the specified name, for overwriting or appending.
259 * @param name name of file to be opened
260 * @param append whether the file is to be opened in append mode
261 */
262 private native void open(String name, boolean append)
263 throws FileNotFoundException;
264
265 /**
266 * Writes the specified byte to this file output stream.
267 *
268 * @param b the byte to be written.
269 * @param append {@code true} if the write operation first
270 * advances the position to the end of file
271 */
272 private native void write(int b, boolean append) throws IOException;
273
274 /**
275 * Writes the specified byte to this file output stream. Implements
276 * the <code>write</code> method of <code>OutputStream</code>.
277 *
278 * @param b the byte to be written.
279 * @exception IOException if an I/O error occurs.
280 */
281 public void write(int b) throws IOException {
282 write(b, append);
283 }
284
285 /**
286 * Writes a sub array as a sequence of bytes.
287 * @param b the data to be written
288 * @param off the start offset in the data
289 * @param len the number of bytes that are written
290 * @param append {@code true} to first advance the position to the
291 * end of file
292 * @exception IOException If an I/O error has occurred.
293 */
294 private native void writeBytes(byte b[], int off, int len, boolean append)
295 throws IOException;
296
297 /**
298 * Writes <code>b.length</code> bytes from the specified byte array
299 * to this file output stream.
300 *
301 * @param b the data.
302 * @exception IOException if an I/O error occurs.
303 */
304 public void write(byte b[]) throws IOException {
305 writeBytes(b, 0, b.length, append);
306 }
307
308 /**
309 * Writes <code>len</code> bytes from the specified byte array
310 * starting at offset <code>off</code> to this file output stream.
311 *
312 * @param b the data.
313 * @param off the start offset in the data.
314 * @param len the number of bytes to write.
315 * @exception IOException if an I/O error occurs.
316 */
317 public void write(byte b[], int off, int len) throws IOException {
318 writeBytes(b, off, len, append);
319 }
320
321 /**
322 * Closes this file output stream and releases any system resources
323 * associated with this stream. This file output stream may no longer
324 * be used for writing bytes.
325 *
326 * <p> If this stream has an associated channel then the channel is closed
327 * as well.
328 *
329 * @exception IOException if an I/O error occurs.
330 *
331 * @revised 1.4
332 * @spec JSR-51
333 */
334 public void close() throws IOException {
335 synchronized (closeLock) {
336 if (closed) {
337 return;
338 }
381 /**
382 * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
383 * object associated with this file output stream. </p>
384 *
385 * <p> The initial {@link java.nio.channels.FileChannel#position()
386 * </code>position<code>} of the returned channel will be equal to the
387 * number of bytes written to the file so far unless this stream is in
388 * append mode, in which case it will be equal to the size of the file.
389 * Writing bytes to this stream will increment the channel's position
390 * accordingly. Changing the channel's position, either explicitly or by
391 * writing, will change this stream's file position.
392 *
393 * @return the file channel associated with this file output stream
394 *
395 * @since 1.4
396 * @spec JSR-51
397 */
398 public FileChannel getChannel() {
399 synchronized (this) {
400 if (channel == null) {
401 channel = FileChannelImpl.open(fd, false, true, append, this);
402
403 /*
404 * Increment fd's use count. Invoking the channel's close()
405 * method will result in decrementing the use count set for
406 * the channel.
407 */
408 fd.incrementAndGetUseCount();
409 }
410 return channel;
411 }
412 }
413
414 /**
415 * Cleans up the connection to the file, and ensures that the
416 * <code>close</code> method of this file output stream is
417 * called when there are no more references to this stream.
418 *
419 * @exception IOException if an I/O error occurs.
420 * @see java.io.FileInputStream#close()
421 */
|
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.io;
27
28 import java.nio.channels.FileChannel;
29 import sun.nio.ch.FileChannelImpl;
30 import sun.misc.IoTrace;
31
32
33 /**
34 * A file output stream is an output stream for writing data to a
35 * <code>File</code> or to a <code>FileDescriptor</code>. Whether or not
36 * a file is available or may be created depends upon the underlying
37 * platform. Some platforms, in particular, allow a file to be opened
38 * for writing by only one <tt>FileOutputStream</tt> (or other
39 * file-writing object) at a time. In such situations the constructors in
40 * this class will fail if the file involved is already open.
41 *
42 * <p><code>FileOutputStream</code> is meant for writing streams of raw bytes
43 * such as image data. For writing streams of characters, consider using
44 * <code>FileWriter</code>.
45 *
46 * @author Arthur van Hoff
47 * @see java.io.File
48 * @see java.io.FileDescriptor
49 * @see java.io.FileInputStream
50 * @see java.nio.file.Files#newOutputStream
51 * @since JDK1.0
52 */
53 public
54 class FileOutputStream extends OutputStream
55 {
56 /**
57 * The system dependent file descriptor.
58 */
59 private final FileDescriptor fd;
60
61 /**
62 * The path of the referenced file (null if the stream is created with a file descriptor)
63 */
64 private final String path;
65
66 /**
67 * True if the file is opened for append.
68 */
69 private final boolean append;
70
71 /**
72 * The associated channel, initalized lazily.
73 */
74 private FileChannel channel;
75
76 private final Object closeLock = new Object();
77 private volatile boolean closed = false;
78 private static final ThreadLocal<Boolean> runningFinalize =
79 new ThreadLocal<>();
80
81 private static boolean isRunningFinalize() {
82 Boolean val;
83 if ((val = runningFinalize.get()) != null)
84 return val.booleanValue();
85 return false;
86 }
196 * <code>checkWrite</code> method denies write access
197 * to the file.
198 * @see java.io.File#getPath()
199 * @see java.lang.SecurityException
200 * @see java.lang.SecurityManager#checkWrite(java.lang.String)
201 * @since 1.4
202 */
203 public FileOutputStream(File file, boolean append)
204 throws FileNotFoundException
205 {
206 String name = (file != null ? file.getPath() : null);
207 SecurityManager security = System.getSecurityManager();
208 if (security != null) {
209 security.checkWrite(name);
210 }
211 if (name == null) {
212 throw new NullPointerException();
213 }
214 this.fd = new FileDescriptor();
215 this.append = append;
216 this.path = name;
217 fd.incrementAndGetUseCount();
218 open(name, append);
219 }
220
221 /**
222 * Creates a file output stream to write to the specified file
223 * descriptor, which represents an existing connection to an actual
224 * file in the file system.
225 * <p>
226 * First, if there is a security manager, its <code>checkWrite</code>
227 * method is called with the file descriptor <code>fdObj</code>
228 * argument as its argument.
229 * <p>
230 * If <code>fdObj</code> is null then a <code>NullPointerException</code>
231 * is thrown.
232 * <p>
233 * This constructor does not throw an exception if <code>fdObj</code>
234 * is {@link java.io.FileDescriptor#valid() invalid}.
235 * However, if the methods are invoked on the resulting stream to attempt
236 * I/O on the stream, an <code>IOException</code> is thrown.
237 *
238 * @param fdObj the file descriptor to be opened for writing
239 * @exception SecurityException if a security manager exists and its
240 * <code>checkWrite</code> method denies
241 * write access to the file descriptor
242 * @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
243 */
244 public FileOutputStream(FileDescriptor fdObj) {
245 SecurityManager security = System.getSecurityManager();
246 if (fdObj == null) {
247 throw new NullPointerException();
248 }
249 if (security != null) {
250 security.checkWrite(fdObj);
251 }
252 this.fd = fdObj;
253 this.path = null;
254 this.append = false;
255
256 /*
257 * FileDescriptor is being shared by streams.
258 * Ensure that it's GC'ed only when all the streams/channels are done
259 * using it.
260 */
261 fd.incrementAndGetUseCount();
262 }
263
264 /**
265 * Opens a file, with the specified name, for overwriting or appending.
266 * @param name name of file to be opened
267 * @param append whether the file is to be opened in append mode
268 */
269 private native void open(String name, boolean append)
270 throws FileNotFoundException;
271
272 /**
273 * Writes the specified byte to this file output stream.
274 *
275 * @param b the byte to be written.
276 * @param append {@code true} if the write operation first
277 * advances the position to the end of file
278 */
279 private native void write(int b, boolean append) throws IOException;
280
281 /**
282 * Writes the specified byte to this file output stream. Implements
283 * the <code>write</code> method of <code>OutputStream</code>.
284 *
285 * @param b the byte to be written.
286 * @exception IOException if an I/O error occurs.
287 */
288 public void write(int b) throws IOException {
289 Object traceContext = IoTrace.fileWriteBegin(path);
290 int bytesWritten = 0;
291 try {
292 write(b, append);
293 bytesWritten = 1;
294 } finally {
295 IoTrace.fileWriteEnd(traceContext, bytesWritten);
296 }
297 }
298
299 /**
300 * Writes a sub array as a sequence of bytes.
301 * @param b the data to be written
302 * @param off the start offset in the data
303 * @param len the number of bytes that are written
304 * @param append {@code true} to first advance the position to the
305 * end of file
306 * @exception IOException If an I/O error has occurred.
307 */
308 private native void writeBytes(byte b[], int off, int len, boolean append)
309 throws IOException;
310
311 /**
312 * Writes <code>b.length</code> bytes from the specified byte array
313 * to this file output stream.
314 *
315 * @param b the data.
316 * @exception IOException if an I/O error occurs.
317 */
318 public void write(byte b[]) throws IOException {
319 Object traceContext = IoTrace.fileWriteBegin(path);
320 int bytesWritten = 0;
321 try {
322 writeBytes(b, 0, b.length, append);
323 bytesWritten = b.length;
324 } finally {
325 IoTrace.fileWriteEnd(traceContext, bytesWritten);
326 }
327 }
328
329 /**
330 * Writes <code>len</code> bytes from the specified byte array
331 * starting at offset <code>off</code> to this file output stream.
332 *
333 * @param b the data.
334 * @param off the start offset in the data.
335 * @param len the number of bytes to write.
336 * @exception IOException if an I/O error occurs.
337 */
338 public void write(byte b[], int off, int len) throws IOException {
339 Object traceContext = IoTrace.fileWriteBegin(path);
340 int bytesWritten = 0;
341 try {
342 writeBytes(b, off, len, append);
343 bytesWritten = len;
344 } finally {
345 IoTrace.fileWriteEnd(traceContext, bytesWritten);
346 }
347 }
348
349 /**
350 * Closes this file output stream and releases any system resources
351 * associated with this stream. This file output stream may no longer
352 * be used for writing bytes.
353 *
354 * <p> If this stream has an associated channel then the channel is closed
355 * as well.
356 *
357 * @exception IOException if an I/O error occurs.
358 *
359 * @revised 1.4
360 * @spec JSR-51
361 */
362 public void close() throws IOException {
363 synchronized (closeLock) {
364 if (closed) {
365 return;
366 }
409 /**
410 * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
411 * object associated with this file output stream. </p>
412 *
413 * <p> The initial {@link java.nio.channels.FileChannel#position()
414 * </code>position<code>} of the returned channel will be equal to the
415 * number of bytes written to the file so far unless this stream is in
416 * append mode, in which case it will be equal to the size of the file.
417 * Writing bytes to this stream will increment the channel's position
418 * accordingly. Changing the channel's position, either explicitly or by
419 * writing, will change this stream's file position.
420 *
421 * @return the file channel associated with this file output stream
422 *
423 * @since 1.4
424 * @spec JSR-51
425 */
426 public FileChannel getChannel() {
427 synchronized (this) {
428 if (channel == null) {
429 channel = FileChannelImpl.open(fd, path, false, true, append, this);
430
431 /*
432 * Increment fd's use count. Invoking the channel's close()
433 * method will result in decrementing the use count set for
434 * the channel.
435 */
436 fd.incrementAndGetUseCount();
437 }
438 return channel;
439 }
440 }
441
442 /**
443 * Cleans up the connection to the file, and ensures that the
444 * <code>close</code> method of this file output stream is
445 * called when there are no more references to this stream.
446 *
447 * @exception IOException if an I/O error occurs.
448 * @see java.io.FileInputStream#close()
449 */
|