java filestream 包_Java io包 FileInputStream&FileOutStream

分析FileInputStream,其中finalize()被覆写,优先使用finalize(),close()方法可能内存泄漏,或者手动colse()之前做好检查

package java.io;

import java.nio.channels.FileChannel;

import sun.nio.ch.FileChannelImpl;

/**

* A FileInputStream obtains input bytes

* from a file in a file system. What files

* are  available depends on the host environment.

*

*

FileInputStream is meant for reading streams of raw bytes

* such as image data. For reading streams of characters, consider using

* FileReader.

*

* @author  Arthur van Hoff

* @see     java.io.File

* @see     java.io.FileDescriptor

* @see     java.io.FileOutputStream

* @see     java.nio.file.Files#newInputStream

* @since   JDK1.0

*/

public

class FileInputStream extends InputStream

{

/* File Descriptor - handle to the open file */

private final FileDescriptor fd;

/**

* 文件路径

*(如果传入FileDescriptor实例化输入流则其为null)

*/

private final String path;

/**

* 读、写、操作文件的通道

*/

private FileChannel channel = null;

/**

* 锁,给close()加锁

*/

private final Object closeLock = new Object();

/**

* 锁的条件值

*/

private volatile boolean closed = false;

/**

* 检查name是否为null,不是调用另外一个构造函数,传入 new File(name)

* @param name

* @throws FileNotFoundException

*/

public FileInputStream(String name) throws FileNotFoundException {

this(name != null ? new File(name) : null);

}

/**

* 1、为name赋值

* 2、安全检查

* 3、判断文件是否存在

* 4、创建一个文件描述类

* 5、绑定其到this

* 6、打开文件(native方法)

* @param file

* @throws FileNotFoundException

*/

public FileInputStream(File file) throws FileNotFoundException {

String name = (file != null ? file.getPath() : null);

SecurityManager security = System.getSecurityManager();

if (security != null) {

security.checkRead(name);

}

if (name == null) {

throw new NullPointerException();

}

if (file.isInvalid()) {

throw new FileNotFoundException("Invalid file path");

}

fd = new FileDescriptor();

fd.attach(this);

path = name;

open(name);

}

/**

* 不推荐采用该构造方法

* 引用自jdk:文件描述符类的实例用作表示打开文件,开放套接字或其他字节源或信宿的底层机器特定结构的不透明句柄。 文件描述符的主要实际用途是创建一个FileInputStream或FileOutputStream来包含它。 应用程序不应创建自己的文件描述符。

* @param fdObj

*/

public FileInputStream(FileDescriptor fdObj) {

SecurityManager security = System.getSecurityManager();

if (fdObj == null) {

throw new NullPointerException();

}

if (security != null) {

security.checkRead(fdObj);

}

fd = fdObj;

path = null;

/*

* FileDescriptor is being shared by streams.

* Register this stream with FileDescriptor tracker.

*/

fd.attach(this);

}

/**

* native方法,打开文件

* @param name

* @throws FileNotFoundException

*/

private native void open0(String name) throws FileNotFoundException;

/**

* 打开文件

* @param name

* @throws FileNotFoundException

*/

private void open(String name) throws FileNotFoundException {

open0(name);

}

/**

* 读取字节

* @return

* @throws IOException

*/

public int read() throws IOException {

return read0();

}

/**

* native方法、读取字节

* @return

* @throws IOException

*/

private native int read0() throws IOException;

/**

* native方法,读取字节数组

* @param b

* @param off

* @param len

* @return

* @throws IOException

*/

private native int readBytes(byte b[], int off, int len) throws IOException;

/**

* 读取字节数组

* @param b

* @return

* @throws IOException

*/

public int read(byte b[]) throws IOException {

return readBytes(b, 0, b.length);

}

/**

* 读取字节

* @param b

* @param off

* @param len

* @return

* @throws IOException

*/

public int read(byte b[], int off, int len) throws IOException {

return readBytes(b, off, len);

}

/**

* 跳过n个字节

* @param n

* @return

* @throws IOException

*/

public long skip(long n) throws IOException {

return skip0(n);

}

private native long skip0(long n) throws IOException;

/**

* 可读取最大字节数

* @return

* @throws IOException

*/

public int available() throws IOException {

return available0();

}

private native int available0() throws IOException;

/**

* 关闭输入流

* @throws IOException

*/

public void close() throws IOException {

synchronized (closeLock) {

if (closed) {

return;

}

closed = true;

}

if (channel != null) {

channel.close();

}

fd.closeAll(new Closeable() {

public void close() throws IOException {

close0();

}

});

}

/**

* 获取文件描述类

* @return

* @throws IOException

*/

public final FileDescriptor getFD() throws IOException {

if (fd != null) {

return fd;

}

throw new IOException();

}

/**

* 获取文件描述通道

* @return

*/

public FileChannel getChannel() {

synchronized (this) {

if (channel == null) {

channel = FileChannelImpl.open(fd, path, true, false, this);

}

return channel;

}

}

private static native void initIDs();

private native void close0() throws IOException;

static {

initIDs();

}

/**

*确保输入流不持有其他对象的引用,再关闭输入流

* @throws IOException

*/

protected void finalize() throws IOException {

if ((fd != null) &&  (fd != FileDescriptor.in)) {

/* if fd is shared, the references in FileDescriptor

* will ensure that finalizer is only called when

* safe to do so. All references using the fd have

* become unreachable. We can call close()

*/

close();

}

}

}

分析FileOutputStream,和FileInputStream类似,多了一个append属性,表示追加和覆写两种模式

package java.io;

import java.nio.channels.FileChannel;

import sun.nio.ch.FileChannelImpl;

/**

* A file output stream is an output stream for writing data to a

* File or to a FileDescriptor. Whether or not

* a file is available or may be created depends upon the underlying

* platform.  Some platforms, in particular, allow a file to be opened

* for writing by only one FileOutputStream (or other

* file-writing object) at a time.  In such situations the constructors in

* this class will fail if the file involved is already open.

*

*

FileOutputStream is meant for writing streams of raw bytes

* such as image data. For writing streams of characters, consider using

* FileWriter.

*

* @author  Arthur van Hoff

* @see     java.io.File

* @see     java.io.FileDescriptor

* @see     java.io.FileInputStream

* @see     java.nio.file.Files#newOutputStream

* @since   JDK1.0

*/

public

class FileOutputStream extends OutputStream

{

/**

* The system dependent file descriptor.

*/

private final FileDescriptor fd;

/**

* True if the file is opened for append.

*/

private final boolean append;

/**

* The associated channel, initialized lazily.

*/

private FileChannel channel;

/**

* The path of the referenced file

* (null if the stream is created with a file descriptor)

*/

private final String path;

private final Object closeLock = new Object();

private volatile boolean closed = false;

/**

* Creates a file output stream to write to the file with the

* specified name. A new FileDescriptor object is

* created to represent this file connection.

*

* First, if there is a security manager, its checkWrite

* method is called with name as its argument.

*

* If the file exists but is a directory rather than a regular file, does

* not exist but cannot be created, or cannot be opened for any other

* reason then a FileNotFoundException is thrown.

*

* @param      name   the system-dependent filename

* @exception  FileNotFoundException  if the file exists but is a directory

*                   rather than a regular file, does not exist but cannot

*                   be created, or cannot be opened for any other reason

* @exception  SecurityException  if a security manager exists and its

*               checkWrite method denies write access

*               to the file.

* @see        java.lang.SecurityManager#checkWrite(java.lang.String)

*/

public FileOutputStream(String name) throws FileNotFoundException {

this(name != null ? new File(name) : null, false);

}

/**

* Creates a file output stream to write to the file with the specified

* name.  If the second argument is true, then

* bytes will be written to the end of the file rather than the beginning.

* A new FileDescriptor object is created to represent this

* file connection.

*

* First, if there is a security manager, its checkWrite

* method is called with name as its argument.

*

* If the file exists but is a directory rather than a regular file, does

* not exist but cannot be created, or cannot be opened for any other

* reason then a FileNotFoundException is thrown.

*

* @param     name        the system-dependent file name

* @param     append      if true, then bytes will be written

*                   to the end of the file rather than the beginning

* @exception  FileNotFoundException  if the file exists but is a directory

*                   rather than a regular file, does not exist but cannot

*                   be created, or cannot be opened for any other reason.

* @exception  SecurityException  if a security manager exists and its

*               checkWrite method denies write access

*               to the file.

* @see        java.lang.SecurityManager#checkWrite(java.lang.String)

* @since     JDK1.1

*/

public FileOutputStream(String name, boolean append)

throws FileNotFoundException

{

this(name != null ? new File(name) : null, append);

}

/**

* Creates a file output stream to write to the file represented by

* the specified File object. A new

* FileDescriptor object is created to represent this

* file connection.

*

* First, if there is a security manager, its checkWrite

* method is called with the path represented by the file

* argument as its argument.

*

* If the file exists but is a directory rather than a regular file, does

* not exist but cannot be created, or cannot be opened for any other

* reason then a FileNotFoundException is thrown.

*

* @param      file               the file to be opened for writing.

* @exception  FileNotFoundException  if the file exists but is a directory

*                   rather than a regular file, does not exist but cannot

*                   be created, or cannot be opened for any other reason

* @exception  SecurityException  if a security manager exists and its

*               checkWrite method denies write access

*               to the file.

* @see        java.io.File#getPath()

* @see        java.lang.SecurityException

* @see        java.lang.SecurityManager#checkWrite(java.lang.String)

*/

public FileOutputStream(File file) throws FileNotFoundException {

this(file, false);

}

/**

* Creates a file output stream to write to the file represented by

* the specified File object. If the second argument is

* true, then bytes will be written to the end of the file

* rather than the beginning. A new FileDescriptor object is

* created to represent this file connection.

*

* First, if there is a security manager, its checkWrite

* method is called with the path represented by the file

* argument as its argument.

*

* If the file exists but is a directory rather than a regular file, does

* not exist but cannot be created, or cannot be opened for any other

* reason then a FileNotFoundException is thrown.

*

* @param      file               the file to be opened for writing.

* @param     append      if true, then bytes will be written

*                   to the end of the file rather than the beginning

* @exception  FileNotFoundException  if the file exists but is a directory

*                   rather than a regular file, does not exist but cannot

*                   be created, or cannot be opened for any other reason

* @exception  SecurityException  if a security manager exists and its

*               checkWrite method denies write access

*               to the file.

* @see        java.io.File#getPath()

* @see        java.lang.SecurityException

* @see        java.lang.SecurityManager#checkWrite(java.lang.String)

* @since 1.4

*/

public FileOutputStream(File file, boolean append)

throws FileNotFoundException

{

String name = (file != null ? file.getPath() : null);

SecurityManager security = System.getSecurityManager();

if (security != null) {

security.checkWrite(name);

}

if (name == null) {

throw new NullPointerException();

}

if (file.isInvalid()) {

throw new FileNotFoundException("Invalid file path");

}

this.fd = new FileDescriptor();

fd.attach(this);

this.append = append;

this.path = name;

open(name, append);

}

/**

* Creates a file output stream to write to the specified file

* descriptor, which represents an existing connection to an actual

* file in the file system.

*

* First, if there is a security manager, its checkWrite

* method is called with the file descriptor fdObj

* argument as its argument.

*

* If fdObj is null then a NullPointerException

* is thrown.

*

* This constructor does not throw an exception if fdObj

* is {@link java.io.FileDescriptor#valid() invalid}.

* However, if the methods are invoked on the resulting stream to attempt

* I/O on the stream, an IOException is thrown.

*

* @param      fdObj   the file descriptor to be opened for writing

* @exception  SecurityException  if a security manager exists and its

*               checkWrite method denies

*               write access to the file descriptor

* @see        java.lang.SecurityManager#checkWrite(java.io.FileDescriptor)

*/

public FileOutputStream(FileDescriptor fdObj) {

SecurityManager security = System.getSecurityManager();

if (fdObj == null) {

throw new NullPointerException();

}

if (security != null) {

security.checkWrite(fdObj);

}

this.fd = fdObj;

this.append = false;

this.path = null;

fd.attach(this);

}

/**

* Opens a file, with the specified name, for overwriting or appending.

* @param name name of file to be opened

* @param append whether the file is to be opened in append mode

*/

private native void open0(String name, boolean append)

throws FileNotFoundException;

// wrap native call to allow instrumentation

/**

* Opens a file, with the specified name, for overwriting or appending.

* @param name name of file to be opened

* @param append whether the file is to be opened in append mode

*/

private void open(String name, boolean append)

throws FileNotFoundException {

open0(name, append);

}

/**

* Writes the specified byte to this file output stream.

*

* @param   b   the byte to be written.

* @param   append   {@code true} if the write operation first

*     advances the position to the end of file

*/

private native void write(int b, boolean append) throws IOException;

/**

* Writes the specified byte to this file output stream. Implements

* the write method of OutputStream.

*

* @param      b   the byte to be written.

* @exception  IOException  if an I/O error occurs.

*/

public void write(int b) throws IOException {

write(b, append);

}

/**

* Writes a sub array as a sequence of bytes.

* @param b the data to be written

* @param off the start offset in the data

* @param len the number of bytes that are written

* @param append {@code true} to first advance the position to the

*     end of file

* @exception IOException If an I/O error has occurred.

*/

private native void writeBytes(byte b[], int off, int len, boolean append)

throws IOException;

/**

* Writes b.length bytes from the specified byte array

* to this file output stream.

*

* @param      b   the data.

* @exception  IOException  if an I/O error occurs.

*/

public void write(byte b[]) throws IOException {

writeBytes(b, 0, b.length, append);

}

/**

* Writes len bytes from the specified byte array

* starting at offset off to this file output stream.

*

* @param      b     the data.

* @param      off   the start offset in the data.

* @param      len   the number of bytes to write.

* @exception  IOException  if an I/O error occurs.

*/

public void write(byte b[], int off, int len) throws IOException {

writeBytes(b, off, len, append);

}

/**

* Closes this file output stream and releases any system resources

* associated with this stream. This file output stream may no longer

* be used for writing bytes.

*

*

If this stream has an associated channel then the channel is closed

* as well.

*

* @exception  IOException  if an I/O error occurs.

*

* @revised 1.4

* @spec JSR-51

*/

public void close() throws IOException {

synchronized (closeLock) {

if (closed) {

return;

}

closed = true;

}

if (channel != null) {

channel.close();

}

fd.closeAll(new Closeable() {

public void close() throws IOException {

close0();

}

});

}

/**

* Returns the file descriptor associated with this stream.

*

* @return  the FileDescriptor object that represents

*          the connection to the file in the file system being used

*          by this FileOutputStream object.

*

* @exception  IOException  if an I/O error occurs.

* @see        java.io.FileDescriptor

*/

public final FileDescriptor getFD()  throws IOException {

if (fd != null) {

return fd;

}

throw new IOException();

}

/**

* Returns the unique {@link java.nio.channels.FileChannel FileChannel}

* object associated with this file output stream.

*

*

The initial {@link java.nio.channels.FileChannel#position()

* position} of the returned channel will be equal to the

* number of bytes written to the file so far unless this stream is in

* append mode, in which case it will be equal to the size of the file.

* Writing bytes to this stream will increment the channel's position

* accordingly.  Changing the channel's position, either explicitly or by

* writing, will change this stream's file position.

*

* @return  the file channel associated with this file output stream

*

* @since 1.4

* @spec JSR-51

*/

public FileChannel getChannel() {

synchronized (this) {

if (channel == null) {

channel = FileChannelImpl.open(fd, path, false, true, append, this);

}

return channel;

}

}

/**

* Cleans up the connection to the file, and ensures that the

* close method of this file output stream is

* called when there are no more references to this stream.

*

* @exception  IOException  if an I/O error occurs.

* @see        java.io.FileInputStream#close()

*/

protected void finalize() throws IOException {

if (fd != null) {

if (fd == FileDescriptor.out || fd == FileDescriptor.err) {

flush();

} else {

/* if fd is shared, the references in FileDescriptor

* will ensure that finalizer is only called when

* safe to do so. All references using the fd have

* become unreachable. We can call close()

*/

close();

}

}

}

private native void close0() throws IOException;

private static native void initIDs();

static {

initIDs();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值