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 jdk.internal.access.SharedSecrets;
30 import jdk.internal.access.JavaIOFileDescriptorAccess;
31 import jdk.internal.misc.Blocker;
32 import sun.nio.ch.FileChannelImpl;
33
34
35 /**
36 * A file output stream is an output stream for writing data to a
37 * {@code File} or to a {@code FileDescriptor}. Whether or not
38 * a file is available or may be created depends upon the underlying
39 * platform. Some platforms, in particular, allow a file to be opened
40 * for writing by only one {@code FileOutputStream} (or other
41 * file-writing object) at a time. In such situations the constructors in
42 * this class will fail if the file involved is already open.
43 *
44 * <p>{@code FileOutputStream} is meant for writing streams of raw bytes
45 * such as image data. For writing streams of characters, consider using
46 * {@code FileWriter}.
47 *
48 * @apiNote
49 * The {@link #close} method should be called to release resources used by this
50 * stream, either directly, or with the {@code try}-with-resources statement.
51 *
269 this.path = null;
270
271 fd.attach(this);
272 }
273
274 /**
275 * Opens a file, with the specified name, for overwriting or appending.
276 * @param name name of file to be opened
277 * @param append whether the file is to be opened in append mode
278 */
279 private native void open0(String name, boolean append)
280 throws FileNotFoundException;
281
282 // wrap native call to allow instrumentation
283 /**
284 * Opens a file, with the specified name, for overwriting or appending.
285 * @param name name of file to be opened
286 * @param append whether the file is to be opened in append mode
287 */
288 private void open(String name, boolean append) throws FileNotFoundException {
289 long comp = Blocker.begin();
290 try {
291 open0(name, append);
292 } finally {
293 Blocker.end(comp);
294 }
295 }
296
297 /**
298 * Writes the specified byte to this file output stream.
299 *
300 * @param b the byte to be written.
301 * @param append {@code true} if the write operation first
302 * advances the position to the end of file
303 */
304 private native void write(int b, boolean append) throws IOException;
305
306 /**
307 * Writes the specified byte to this file output stream. Implements
308 * the {@code write} method of {@code OutputStream}.
309 *
310 * @param b the byte to be written.
311 * @throws IOException if an I/O error occurs.
312 */
313 @Override
314 public void write(int b) throws IOException {
315 boolean append = FD_ACCESS.getAppend(fd);
316 long comp = Blocker.begin();
317 try {
318 write(b, append);
319 } finally {
320 Blocker.end(comp);
321 }
322 }
323
324 /**
325 * Writes a sub array as a sequence of bytes.
326 * @param b the data to be written
327 * @param off the start offset in the data
328 * @param len the number of bytes that are written
329 * @param append {@code true} to first advance the position to the
330 * end of file
331 * @throws IOException If an I/O error has occurred.
332 */
333 private native void writeBytes(byte[] b, int off, int len, boolean append)
334 throws IOException;
335
336 /**
337 * Writes {@code b.length} bytes from the specified byte array
338 * to this file output stream.
339 *
340 * @param b {@inheritDoc}
341 * @throws IOException {@inheritDoc}
342 */
343 @Override
344 public void write(byte[] b) throws IOException {
345 boolean append = FD_ACCESS.getAppend(fd);
346 long comp = Blocker.begin();
347 try {
348 writeBytes(b, 0, b.length, append);
349 } finally {
350 Blocker.end(comp);
351 }
352 }
353
354 /**
355 * Writes {@code len} bytes from the specified byte array
356 * starting at offset {@code off} to this file output stream.
357 *
358 * @param b {@inheritDoc}
359 * @param off {@inheritDoc}
360 * @param len {@inheritDoc}
361 * @throws IOException if an I/O error occurs.
362 * @throws IndexOutOfBoundsException {@inheritDoc}
363 */
364 @Override
365 public void write(byte[] b, int off, int len) throws IOException {
366 boolean append = FD_ACCESS.getAppend(fd);
367 long comp = Blocker.begin();
368 try {
369 writeBytes(b, off, len, append);
370 } finally {
371 Blocker.end(comp);
372 }
373 }
374
375 /**
376 * Closes this file output stream and releases any system resources
377 * associated with this stream. This file output stream may no longer
378 * be used for writing bytes.
379 *
380 * <p> If this stream has an associated channel then the channel is closed
381 * as well.
382 *
383 * @apiNote
384 * Overriding {@link #close} to perform cleanup actions is reliable
385 * only when called directly or when called by try-with-resources.
386 *
387 * @implSpec
388 * Subclasses requiring that resource cleanup take place after a stream becomes
389 * unreachable should use the {@link java.lang.ref.Cleaner} mechanism.
390 *
391 * <p>
392 * If this stream has an associated channel then this method will close the
443 * object associated with this file output stream.
444 *
445 * <p> The initial {@link java.nio.channels.FileChannel#position()
446 * position} of the returned channel will be equal to the
447 * number of bytes written to the file so far unless this stream is in
448 * append mode, in which case it will be equal to the size of the file.
449 * Writing bytes to this stream will increment the channel's position
450 * accordingly. Changing the channel's position, either explicitly or by
451 * writing, will change this stream's file position.
452 *
453 * @return the file channel associated with this file output stream
454 *
455 * @since 1.4
456 */
457 public FileChannel getChannel() {
458 FileChannel fc = this.channel;
459 if (fc == null) {
460 synchronized (this) {
461 fc = this.channel;
462 if (fc == null) {
463 this.channel = fc = FileChannelImpl.open(fd, path, false,
464 true, false, this);
465 if (closed) {
466 try {
467 // possible race with close(), benign since
468 // FileChannel.close is final and idempotent
469 fc.close();
470 } catch (IOException ioe) {
471 throw new InternalError(ioe); // should not happen
472 }
473 }
474 }
475 }
476 }
477 return fc;
478 }
479
480 private static native void initIDs();
481
482 static {
483 initIDs();
484 }
|
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 jdk.internal.access.SharedSecrets;
30 import jdk.internal.access.JavaIOFileDescriptorAccess;
31 import sun.nio.ch.FileChannelImpl;
32
33
34 /**
35 * A file output stream is an output stream for writing data to a
36 * {@code File} or to a {@code FileDescriptor}. Whether or not
37 * a file is available or may be created depends upon the underlying
38 * platform. Some platforms, in particular, allow a file to be opened
39 * for writing by only one {@code FileOutputStream} (or other
40 * file-writing object) at a time. In such situations the constructors in
41 * this class will fail if the file involved is already open.
42 *
43 * <p>{@code FileOutputStream} is meant for writing streams of raw bytes
44 * such as image data. For writing streams of characters, consider using
45 * {@code FileWriter}.
46 *
47 * @apiNote
48 * The {@link #close} method should be called to release resources used by this
49 * stream, either directly, or with the {@code try}-with-resources statement.
50 *
268 this.path = null;
269
270 fd.attach(this);
271 }
272
273 /**
274 * Opens a file, with the specified name, for overwriting or appending.
275 * @param name name of file to be opened
276 * @param append whether the file is to be opened in append mode
277 */
278 private native void open0(String name, boolean append)
279 throws FileNotFoundException;
280
281 // wrap native call to allow instrumentation
282 /**
283 * Opens a file, with the specified name, for overwriting or appending.
284 * @param name name of file to be opened
285 * @param append whether the file is to be opened in append mode
286 */
287 private void open(String name, boolean append) throws FileNotFoundException {
288 open0(name, append);
289 }
290
291 /**
292 * Writes the specified byte to this file output stream.
293 *
294 * @param b the byte to be written.
295 * @param append {@code true} if the write operation first
296 * advances the position to the end of file
297 */
298 private native void write(int b, boolean append) throws IOException;
299
300 /**
301 * Writes the specified byte to this file output stream. Implements
302 * the {@code write} method of {@code OutputStream}.
303 *
304 * @param b the byte to be written.
305 * @throws IOException if an I/O error occurs.
306 */
307 @Override
308 public void write(int b) throws IOException {
309 boolean append = FD_ACCESS.getAppend(fd);
310 write(b, append);
311 }
312
313 /**
314 * Writes a sub array as a sequence of bytes.
315 * @param b the data to be written
316 * @param off the start offset in the data
317 * @param len the number of bytes that are written
318 * @param append {@code true} to first advance the position to the
319 * end of file
320 * @throws IOException If an I/O error has occurred.
321 */
322 private native void writeBytes(byte[] b, int off, int len, boolean append)
323 throws IOException;
324
325 /**
326 * Writes {@code b.length} bytes from the specified byte array
327 * to this file output stream.
328 *
329 * @param b {@inheritDoc}
330 * @throws IOException {@inheritDoc}
331 */
332 @Override
333 public void write(byte[] b) throws IOException {
334 boolean append = FD_ACCESS.getAppend(fd);
335 writeBytes(b, 0, b.length, append);
336 }
337
338 /**
339 * Writes {@code len} bytes from the specified byte array
340 * starting at offset {@code off} to this file output stream.
341 *
342 * @param b {@inheritDoc}
343 * @param off {@inheritDoc}
344 * @param len {@inheritDoc}
345 * @throws IOException if an I/O error occurs.
346 * @throws IndexOutOfBoundsException {@inheritDoc}
347 */
348 @Override
349 public void write(byte[] b, int off, int len) throws IOException {
350 boolean append = FD_ACCESS.getAppend(fd);
351 writeBytes(b, off, len, append);
352 }
353
354 /**
355 * Closes this file output stream and releases any system resources
356 * associated with this stream. This file output stream may no longer
357 * be used for writing bytes.
358 *
359 * <p> If this stream has an associated channel then the channel is closed
360 * as well.
361 *
362 * @apiNote
363 * Overriding {@link #close} to perform cleanup actions is reliable
364 * only when called directly or when called by try-with-resources.
365 *
366 * @implSpec
367 * Subclasses requiring that resource cleanup take place after a stream becomes
368 * unreachable should use the {@link java.lang.ref.Cleaner} mechanism.
369 *
370 * <p>
371 * If this stream has an associated channel then this method will close the
422 * object associated with this file output stream.
423 *
424 * <p> The initial {@link java.nio.channels.FileChannel#position()
425 * position} of the returned channel will be equal to the
426 * number of bytes written to the file so far unless this stream is in
427 * append mode, in which case it will be equal to the size of the file.
428 * Writing bytes to this stream will increment the channel's position
429 * accordingly. Changing the channel's position, either explicitly or by
430 * writing, will change this stream's file position.
431 *
432 * @return the file channel associated with this file output stream
433 *
434 * @since 1.4
435 */
436 public FileChannel getChannel() {
437 FileChannel fc = this.channel;
438 if (fc == null) {
439 synchronized (this) {
440 fc = this.channel;
441 if (fc == null) {
442 fc = FileChannelImpl.open(fd, path, false, true, false, false, this);
443 this.channel = fc;
444 if (closed) {
445 try {
446 // possible race with close(), benign since
447 // FileChannel.close is final and idempotent
448 fc.close();
449 } catch (IOException ioe) {
450 throw new InternalError(ioe); // should not happen
451 }
452 }
453 }
454 }
455 }
456 return fc;
457 }
458
459 private static native void initIDs();
460
461 static {
462 initIDs();
463 }
|