Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/java/io/FileOutputStream.java
41152 views
1
/*
2
* Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
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 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
* To release resources used by this stream {@link #close} should be called
49
* directly or by try-with-resources. Subclasses are responsible for the cleanup
50
* of resources acquired by the subclass.
51
* Subclasses that override {@link #finalize} in order to perform cleanup
52
* should be modified to use alternative cleanup mechanisms such as
53
* {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
54
*
55
* @implSpec
56
* If this FileOutputStream has been subclassed and the {@link #close}
57
* method has been overridden, the {@link #close} method will be
58
* called when the FileInputStream is unreachable.
59
* Otherwise, it is implementation specific how the resource cleanup described in
60
* {@link #close} is performed.
61
*
62
* @author Arthur van Hoff
63
* @see java.io.File
64
* @see java.io.FileDescriptor
65
* @see java.io.FileInputStream
66
* @see java.nio.file.Files#newOutputStream
67
* @since 1.0
68
*/
69
public class FileOutputStream extends OutputStream
70
{
71
/**
72
* Access to FileDescriptor internals.
73
*/
74
private static final JavaIOFileDescriptorAccess fdAccess =
75
SharedSecrets.getJavaIOFileDescriptorAccess();
76
77
/**
78
* The system dependent file descriptor.
79
*/
80
private final FileDescriptor fd;
81
82
/**
83
* The associated channel, initialized lazily.
84
*/
85
private volatile FileChannel channel;
86
87
/**
88
* The path of the referenced file
89
* (null if the stream is created with a file descriptor)
90
*/
91
private final String path;
92
93
private final Object closeLock = new Object();
94
95
private volatile boolean closed;
96
97
/**
98
* Creates a file output stream to write to the file with the
99
* specified name. A new {@code FileDescriptor} object is
100
* created to represent this file connection.
101
* <p>
102
* First, if there is a security manager, its {@code checkWrite}
103
* method is called with {@code name} as its argument.
104
* <p>
105
* If the file exists but is a directory rather than a regular file, does
106
* not exist but cannot be created, or cannot be opened for any other
107
* reason then a {@code FileNotFoundException} is thrown.
108
*
109
* @implSpec Invoking this constructor with the parameter {@code name} is
110
* equivalent to invoking {@link #FileOutputStream(String,boolean)
111
* new FileOutputStream(name, false)}.
112
*
113
* @param name the system-dependent filename
114
* @throws FileNotFoundException if the file exists but is a directory
115
* rather than a regular file, does not exist but cannot
116
* be created, or cannot be opened for any other reason
117
* @throws SecurityException if a security manager exists and its
118
* {@code checkWrite} method denies write access
119
* to the file.
120
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
121
*/
122
public FileOutputStream(String name) throws FileNotFoundException {
123
this(name != null ? new File(name) : null, false);
124
}
125
126
/**
127
* Creates a file output stream to write to the file with the specified
128
* name. If the second argument is {@code true}, then
129
* bytes will be written to the end of the file rather than the beginning.
130
* A new {@code FileDescriptor} object is created to represent this
131
* file connection.
132
* <p>
133
* First, if there is a security manager, its {@code checkWrite}
134
* method is called with {@code name} as its argument.
135
* <p>
136
* If the file exists but is a directory rather than a regular file, does
137
* not exist but cannot be created, or cannot be opened for any other
138
* reason then a {@code FileNotFoundException} is thrown.
139
*
140
* @param name the system-dependent file name
141
* @param append if {@code true}, then bytes will be written
142
* to the end of the file rather than the beginning
143
* @throws FileNotFoundException if the file exists but is a directory
144
* rather than a regular file, does not exist but cannot
145
* be created, or cannot be opened for any other reason.
146
* @throws SecurityException if a security manager exists and its
147
* {@code checkWrite} method denies write access
148
* to the file.
149
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
150
* @since 1.1
151
*/
152
public FileOutputStream(String name, boolean append)
153
throws FileNotFoundException
154
{
155
this(name != null ? new File(name) : null, append);
156
}
157
158
/**
159
* Creates a file output stream to write to the file represented by
160
* the specified {@code File} object. A new
161
* {@code FileDescriptor} object is created to represent this
162
* file connection.
163
* <p>
164
* First, if there is a security manager, its {@code checkWrite}
165
* method is called with the path represented by the {@code file}
166
* argument as its argument.
167
* <p>
168
* If the file exists but is a directory rather than a regular file, does
169
* not exist but cannot be created, or cannot be opened for any other
170
* reason then a {@code FileNotFoundException} is thrown.
171
*
172
* @param file the file to be opened for writing.
173
* @throws FileNotFoundException if the file exists but is a directory
174
* rather than a regular file, does not exist but cannot
175
* be created, or cannot be opened for any other reason
176
* @throws SecurityException if a security manager exists and its
177
* {@code checkWrite} method denies write access
178
* to the file.
179
* @see java.io.File#getPath()
180
* @see java.lang.SecurityException
181
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
182
*/
183
public FileOutputStream(File file) throws FileNotFoundException {
184
this(file, false);
185
}
186
187
/**
188
* Creates a file output stream to write to the file represented by
189
* the specified {@code File} object. If the second argument is
190
* {@code true}, then bytes will be written to the end of the file
191
* rather than the beginning. A new {@code FileDescriptor} object is
192
* created to represent this file connection.
193
* <p>
194
* First, if there is a security manager, its {@code checkWrite}
195
* method is called with the path represented by the {@code file}
196
* argument as its argument.
197
* <p>
198
* If the file exists but is a directory rather than a regular file, does
199
* not exist but cannot be created, or cannot be opened for any other
200
* reason then a {@code FileNotFoundException} is thrown.
201
*
202
* @param file the file to be opened for writing.
203
* @param append if {@code true}, then bytes will be written
204
* to the end of the file rather than the beginning
205
* @throws FileNotFoundException if the file exists but is a directory
206
* rather than a regular file, does not exist but cannot
207
* be created, or cannot be opened for any other reason
208
* @throws SecurityException if a security manager exists and its
209
* {@code checkWrite} method denies write access
210
* to the file.
211
* @see java.io.File#getPath()
212
* @see java.lang.SecurityException
213
* @see java.lang.SecurityManager#checkWrite(java.lang.String)
214
* @since 1.4
215
*/
216
public FileOutputStream(File file, boolean append)
217
throws FileNotFoundException
218
{
219
String name = (file != null ? file.getPath() : null);
220
@SuppressWarnings("removal")
221
SecurityManager security = System.getSecurityManager();
222
if (security != null) {
223
security.checkWrite(name);
224
}
225
if (name == null) {
226
throw new NullPointerException();
227
}
228
if (file.isInvalid()) {
229
throw new FileNotFoundException("Invalid file path");
230
}
231
this.fd = new FileDescriptor();
232
fd.attach(this);
233
this.path = name;
234
235
open(name, append);
236
FileCleanable.register(fd); // open sets the fd, register the cleanup
237
}
238
239
/**
240
* Creates a file output stream to write to the specified file
241
* descriptor, which represents an existing connection to an actual
242
* file in the file system.
243
* <p>
244
* First, if there is a security manager, its {@code checkWrite}
245
* method is called with the file descriptor {@code fdObj}
246
* argument as its argument.
247
* <p>
248
* If {@code fdObj} is null then a {@code NullPointerException}
249
* is thrown.
250
* <p>
251
* This constructor does not throw an exception if {@code fdObj}
252
* is {@link java.io.FileDescriptor#valid() invalid}.
253
* However, if the methods are invoked on the resulting stream to attempt
254
* I/O on the stream, an {@code IOException} is thrown.
255
*
256
* @param fdObj the file descriptor to be opened for writing
257
* @throws SecurityException if a security manager exists and its
258
* {@code checkWrite} method denies
259
* write access to the file descriptor
260
* @see java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)
261
*/
262
public FileOutputStream(FileDescriptor fdObj) {
263
@SuppressWarnings("removal")
264
SecurityManager security = System.getSecurityManager();
265
if (fdObj == null) {
266
throw new NullPointerException();
267
}
268
if (security != null) {
269
security.checkWrite(fdObj);
270
}
271
this.fd = fdObj;
272
this.path = null;
273
274
fd.attach(this);
275
}
276
277
/**
278
* Opens a file, with the specified name, for overwriting or appending.
279
* @param name name of file to be opened
280
* @param append whether the file is to be opened in append mode
281
*/
282
private native void open0(String name, boolean append)
283
throws FileNotFoundException;
284
285
// wrap native call to allow instrumentation
286
/**
287
* Opens a file, with the specified name, for overwriting or appending.
288
* @param name name of file to be opened
289
* @param append whether the file is to be opened in append mode
290
*/
291
private void open(String name, boolean append)
292
throws FileNotFoundException {
293
open0(name, append);
294
}
295
296
/**
297
* Writes the specified byte to this file output stream.
298
*
299
* @param b the byte to be written.
300
* @param append {@code true} if the write operation first
301
* advances the position to the end of file
302
*/
303
private native void write(int b, boolean append) throws IOException;
304
305
/**
306
* Writes the specified byte to this file output stream. Implements
307
* the {@code write} method of {@code OutputStream}.
308
*
309
* @param b the byte to be written.
310
* @throws IOException if an I/O error occurs.
311
*/
312
public void write(int b) throws IOException {
313
write(b, fdAccess.getAppend(fd));
314
}
315
316
/**
317
* Writes a sub array as a sequence of bytes.
318
* @param b the data to be written
319
* @param off the start offset in the data
320
* @param len the number of bytes that are written
321
* @param append {@code true} to first advance the position to the
322
* end of file
323
* @throws IOException If an I/O error has occurred.
324
*/
325
private native void writeBytes(byte b[], int off, int len, boolean append)
326
throws IOException;
327
328
/**
329
* Writes {@code b.length} bytes from the specified byte array
330
* to this file output stream.
331
*
332
* @param b the data.
333
* @throws IOException if an I/O error occurs.
334
*/
335
public void write(byte b[]) throws IOException {
336
writeBytes(b, 0, b.length, fdAccess.getAppend(fd));
337
}
338
339
/**
340
* Writes {@code len} bytes from the specified byte array
341
* starting at offset {@code off} to this file output stream.
342
*
343
* @param b the data.
344
* @param off the start offset in the data.
345
* @param len the number of bytes to write.
346
* @throws IOException if an I/O error occurs.
347
*/
348
public void write(byte b[], int off, int len) throws IOException {
349
writeBytes(b, off, len, fdAccess.getAppend(fd));
350
}
351
352
/**
353
* Closes this file output stream and releases any system resources
354
* associated with this stream. This file output stream may no longer
355
* be used for writing bytes.
356
*
357
* <p> If this stream has an associated channel then the channel is closed
358
* as well.
359
*
360
* @apiNote
361
* Overriding {@link #close} to perform cleanup actions is reliable
362
* only when called directly or when called by try-with-resources.
363
* Do not depend on finalization to invoke {@code close};
364
* finalization is not reliable and is deprecated.
365
* If cleanup of native resources is needed, other mechanisms such as
366
* {@linkplain java.lang.ref.Cleaner} should be used.
367
*
368
* @throws IOException if an I/O error occurs.
369
*
370
* @revised 1.4
371
*/
372
public void close() throws IOException {
373
if (closed) {
374
return;
375
}
376
synchronized (closeLock) {
377
if (closed) {
378
return;
379
}
380
closed = true;
381
}
382
383
FileChannel fc = channel;
384
if (fc != null) {
385
// possible race with getChannel(), benign since
386
// FileChannel.close is final and idempotent
387
fc.close();
388
}
389
390
fd.closeAll(new Closeable() {
391
public void close() throws IOException {
392
fd.close();
393
}
394
});
395
}
396
397
/**
398
* Returns the file descriptor associated with this stream.
399
*
400
* @return the {@code FileDescriptor} object that represents
401
* the connection to the file in the file system being used
402
* by this {@code FileOutputStream} object.
403
*
404
* @throws IOException if an I/O error occurs.
405
* @see java.io.FileDescriptor
406
*/
407
public final FileDescriptor getFD() throws IOException {
408
if (fd != null) {
409
return fd;
410
}
411
throw new IOException();
412
}
413
414
/**
415
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
416
* object associated with this file output stream.
417
*
418
* <p> The initial {@link java.nio.channels.FileChannel#position()
419
* position} of the returned channel will be equal to the
420
* number of bytes written to the file so far unless this stream is in
421
* append mode, in which case it will be equal to the size of the file.
422
* Writing bytes to this stream will increment the channel's position
423
* accordingly. Changing the channel's position, either explicitly or by
424
* writing, will change this stream's file position.
425
*
426
* @return the file channel associated with this file output stream
427
*
428
* @since 1.4
429
*/
430
public FileChannel getChannel() {
431
FileChannel fc = this.channel;
432
if (fc == null) {
433
synchronized (this) {
434
fc = this.channel;
435
if (fc == null) {
436
this.channel = fc = FileChannelImpl.open(fd, path, false,
437
true, false, this);
438
if (closed) {
439
try {
440
// possible race with close(), benign since
441
// FileChannel.close is final and idempotent
442
fc.close();
443
} catch (IOException ioe) {
444
throw new InternalError(ioe); // should not happen
445
}
446
}
447
}
448
}
449
}
450
return fc;
451
}
452
453
private static native void initIDs();
454
455
static {
456
initIDs();
457
}
458
}
459
460