Java之IO

本文详细介绍了Java IO的基本概念,包括磁盘IO与网络IO的区别,以及java.io包中的核心类如File、RandomAccessFile、InputStream、OutputStream等的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IO分为磁盘IO和网络IO

IO

java.io.*包中主要包含三部分:

  • 流时部分
  • 非流式部分,主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor等类
  • 其他-文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类

File&RandomAccessFile

File是对文件的抽象,提供了获取文件属性,创建、删除文件等操作,目录也是文件。

//构造File对象
public File(String pathname);
public File(File parent, String child);
public File(String parent, String child);
public File(URI uri);

//获取文件属性
public String getName();
public long length();
public boolean canExecute();
public int hashCode();
public boolean isDirectory();
public boolean exists();
.......

//文件操作
public boolean createNewFile() throws IOException;
public boolean mkdir();
public boolean delete();
public void deleteOnExit();
public boolean renameTo(File dest);

RandomAccessFile提供了随机读写文件的接口,即可用定位文件位置,然后进行读取或写入数据。

public class RandomAccessFile implements DataOutput, DataInput, Closeable {
    public RandomAccessFile(String name, String mode);

    public native void seek(long pos) throws IOException;

    public int read() throws IOException;

    public void write(byte b[]) throws IOException;
}

流是对数据源和数据目的地的抽象,提供数据传输操作的接口。

数据源:

  • 键盘
  • 内存
  • 文件
  • 网络
  • 管道

数据目的地:

  • 显示器
  • 内存
  • 文件
  • 网络
  • 管道

Java中将输入数据源抽象为输入流,输出数据目的地抽象为输出流,数据源/目的地直接作为流对象构造函数参数传入。

输入流

根据流里数据类型分为字符流和字节流,Java中字符是Unicode字符,且是UTF-16编码,字符内部也是字节,字符流一次读取多个字节然后根据Unicode码表映射成字符,因此,处理文本数据时使用字符流,其他数据则用字节流。

字节输入流InputStream

public abstract class InputStream implements Closeable {

    // MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to
    // use when skipping.
    private static final int MAX_SKIP_BUFFER_SIZE = 2048;

     // 返回读入的字节,范围0-255,无数据返回-1
    public abstract int read() throws IOException;

    //返回读入的字节个数,无数据返回-1代表流结束
    public int read(byte b[]) throws IOException {
        return read(b, 0, b.length);
    }
    //读取数据倒缓冲区
    public int read(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int c = read();
        if (c == -1) {
            return -1;
        }
        b[off] = (byte)c;

        int i = 1;
        try {
            for (; i < len ; i++) {
                c = read();
                if (c == -1) {
                    break;
                }
                b[off + i] = (byte)c;
            }
        } catch (IOException ee) {
        }
        return i;
    }

    public long skip(long n) throws IOException {

        long remaining = n;
        int nr;

        if (n <= 0) {
            return 0;
        }

        int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
        byte[] skipBuffer = new byte[size];
        while (remaining > 0) {
            nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
            if (nr < 0) {
                break;
            }
            remaining -= nr;
        }

        return n - remaining;
    }

    public int available() throws IOException {
        return 0;
    }

    public void close() throws IOException {}

    public synchronized void mark(int readlimit) {}

    public synchronized void reset() throws IOException {
        throw new IOException("mark/reset not supported");
    }

    public boolean markSupported() {
        return false;
    }
}

InputStream主要提供read()方法一次读取一个字节,以及read(byte buf[])读取多个字符到缓冲区,此外还提供了skip/mark/reset接口进行标记重复读取数据。

字符输入流Reader

public abstract class Reader implements Readable, Closeable {
    public int read() throws IOException;
    public int read(char cbuf[]);
    abstract public int read(char cbuf[], int off, int len) throws IOException;
    public long skip(long n);
    public boolean markSupported();
    public void reset() throws IOException;
    ........
}

与InputStream提供的接口类似,只是read方法读取的是字符。

键盘

键盘抽象为字节流InputStream, java.lang.System.in常量抽象为标准输入,一般对应键盘

内存

字节输入流

字节输入流ByteArrayInputStream,继承InputStream,读取byte[]类型数据,支持skip/mark/reset操作:

public ByteArrayInputStream(byte buf[]);
public ByteArrayInputStream(byte buf[], int offset, int length);

此外Object本身也是由一连串byte组成,其成员是基本类型或Object, 因此抽象出可以从字节流中反序列化对象的ObjectInputStream,一般输入源是序列化对象时使用字节输出流ObjectOutputStream输出的数据,反序列化时再形成输入字节流作为ObjectInputStream的数据源。

public class ObjectInputStream
extends InputStream implements ObjectInput, ObjectStreamConstants {

    public ObjectInputStream(InputStream in) throws IOException;

    public Object readObject() throws ClassNotFoundException, IOException;

    ........
}

ObjectInputStream继承自ObjectInput,除了提供readObject方法外,还实现了读取Primitive类型的DataInput接口

public interface ObjectInput extends DataInput, AutoCloseable {
    public Object readObject() throws ClassNotFoundException, IOException;
    public int read() throws IOException;
    public int read(byte b[]) throws IOException;
    public int read(byte b[], int off, int len) throws IOException;
    public long skip(long n) throws IOException;
    public int available() throws IOException;
    public void close() throws IOException;
}

public interface DataInput {

    void readFully(byte b[]) throws IOException;

    void readFully(byte b[], int off, int len) throws IOException;

    int skipBytes(int n) throws IOException;

    boolean readBoolean() throws IOException;

    byte readByte() throws IOException;

    int readUnsignedByte() throws IOException;

    short readShort() throws IOException;

    int readUnsignedShort() throws IOException;

    char readChar() throws IOException;

    int readInt() throws IOException;

    long readLong() throws IOException;

    float readFloat() throws IOException;

    double readDouble() throws IOException;

    String readLine() throws IOException;

    String readUTF() throws IOException;
}

DataInput抽象了基本数据类型的读取

字符输入流

字符输入流CharArrayReader,继承Reader,读取char[]数据,支持skip/mark/reset:

CharArrayReader(char[] buf);
public CharArrayReader(char buf[], int offset, int length);

又有String本质也是CharArray, 为方便将String转换为流提供了StringReader:

public StringReader(String s);

文件

文件抽象为File对象,FileInputStream则是把File作为数据源的字节输入流的抽象,FileReader则是字符输入流。

FileInputStream
FileInputStream(File file);
FileInputStream(FileDescriptor fdObj);
public FileInputStream(String name) throws FileNotFoundException;

public FileChannel getChannel();
FileReader

一般读取文本文件使用FileReader,FileReader直接借助FileInputStream实现,将读取的字节流通过码表转换为字符流,InputStreamReader实现了字节到字符的转换。

public class FileReader extends InputStreamReader {

    public FileReader(String fileName) throws FileNotFoundException {
        super(new FileInputStream(fileName));
    }

    public FileReader(File file) throws FileNotFoundException {
        super(new FileInputStream(file));
    }

    public FileReader(FileDescriptor fd) {
        super(new FileInputStream(fd));
    }
}

网络

网络传输的是字节数据,没有直接提供抽象网络流的类,而是绑定到某个Socket,通过网络套接字java.net.Socket直接获取输入/输出字节流。

class public Socket implements java.io.Closeable {
    public InputStream getInputStream() throws IOException;
    public OutputStream getOutputStream() throws IOException
}

管道

PipedInputStream一般连接一个PipeOutputStream, 一个线程通过PipedInputStream从PipedInputStream读取数据,另外一个线程通过PipeOutputStream写数据

public PipedInputStream(PipedOutputStream src);
public PipedInputStream(PipedOutputStream src, int pipeSize);

同样,PipedReader是基于管道的字符输入流

过滤输入流

Java中通过装饰模式为流提供了更丰富的功能,FilterInputStream是一种装饰后的InputStream,因此构造函数中需传入一个InputStream对象,并将此对象保存成成员对象,底层数据传输都是通过此对象完成。

BufferedInputStream & BufferedReader

BufferedInputStream在InputStream基础上增加了缓冲区,读取数据更加高效,默认缓冲大小为8192,因此使用InputStream读取数据时一般包装成BufferedInputStream

同理BufferedReader为Reader增加缓冲区,此外还增加了readLine()方法按行读取文本数据。

    public BufferedReader(Reader in);
    //读取一行,返回null时代表流结束
    String readLine();
DataInputStream

DataInputStream在InputStream基础上实现DataInput接口,提供了从InputStream读取Java Primitive类型数据

输出流

与输入流相反,InputStream对应成OutputStream, Reader对应成Writer

字节输出流OutputStream

OutputStream提供了write(int b)写一个字节或write(byte b[])写多个字节

public abstract class OutputStream implements Closeable, Flushable {

    public abstract void write(int b) throws IOException;

    public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
    }

    public void write(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if ((off < 0) || (off > b.length) || (len < 0) ||
                   ((off + len) > b.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        for (int i = 0 ; i < len ; i++) {
            write(b[off + i]);
        }
    }

    public void flush() throws IOException {
    }

    public void close() throws IOException {
    }

}

字符输出流Writer

Writer则提供了输出一个字符、字符数组和字符串的方法

public abstract class Writer implements Appendable, Closeable, Flushable {

    public void write(int c) throws IOException;
    public void write(char cbuf[]) throws IOException;
    public void write(String str) throws IOException;
    .....
}

显示器

显示器抽象为字节输出流PrintStream, java.lang.System.out/err是标准输出/错误输出对象,对应显示器。

PrintStream在OutputStream基础上增加了print/println/printf方法:

public void print(boolean b);
public void println(float x)
public PrintStream printf(String format, Object ... args);

内存

字节输出流

ByteArrayOutputStream将数据存储到byte[],因此内部维持一个byte[]缓冲区,写入数据时按翻倍的速率动态调整大小,默认大小为32.

//默认大小32
public ByteArrayOutputStream(); 
//指定大小
public ByteArrayOutputStream(int size);
//获取缓冲器数据
public synchronized byte[] toByteArray();

ObjectOutputStream用于将对象输出到OutputStream, 实现了ObjectOutput和DataOutput接口, 输出Object以及Primitive类型数据。

public class ObjectOutputStream
extends OutputStream implements ObjectOutput, ObjectStreamConstants {
    public ObjectOutputStream(OutputStream out) throws IOException;

    public final void writeObject(Object obj) throws IOException;
}

public interface ObjectOutput extends DataOutput, AutoCloseable {

    public void writeObject(Object obj) throws IOException;

    public void write(int b) throws IOException;

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

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

    public void flush() throws IOException;

    public void close() throws IOException;
}


public interface DataOutput {

    void write(int b) throws IOException;

    void write(byte b[]) throws IOException;

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

    void writeBoolean(boolean v) throws IOException;

    void writeByte(int v) throws IOException;

    void writeShort(int v) throws IOException;

    void writeChar(int v) throws IOException;

    void writeInt(int v) throws IOException;

    void writeLong(long v) throws IOException;

    void writeFloat(float v) throws IOException;

    void writeDouble(double v) throws IOException;

    void writeBytes(String s) throws IOException;

    void writeChars(String s) throws IOException;

    void writeUTF(String s) throws IOException;
}

字符输出流

CharArrayWriter将字符流输出到char[]缓冲中,char[]也会动态扩容

public CharArrayWriter();

public CharArrayWriter(int initialSize);

public char[] toCharArray();

StringWriter内部使用StringBuffer保存流输出数据

public StringWriter();

public StringWriter(int initialSize);

public StringBuffer getBuffer();

文件

FileOutputStream

FileOutputStream输出字节数据到File

public FileOutputStream(File file) throws FileNotFoundException;

public FileOutputStream(File file, boolean append);

public FileOutputStream(String name) throws FileNotFoundException;

public FileOutputStream(String name, boolean append);
FileWriter

FileWriter借助FileOutputStream实现,继承自OutputStreamWriter,OutputStreamWriter实现了将字符流转换为字节流,然后输出的功能.

public class FileWriter extends OutputStreamWriter {

    public FileWriter(String fileName) throws IOException {
        super(new FileOutputStream(fileName));
    }

    public FileWriter(String fileName, boolean append) throws IOException {
        super(new FileOutputStream(fileName, append));
    }

    public FileWriter(File file) throws IOException {
        super(new FileOutputStream(file));
    }

    public FileWriter(File file, boolean append) throws IOException {
        super(new FileOutputStream(file, append));
    }

    public FileWriter(FileDescriptor fd) {
        super(new FileOutputStream(fd));
    }
}

网络

数据输出到网络,直接通过java.net.Socket.getOutputStream()获取字节流数据数据倒Socket.

管道

PipeOutputStream一般连接一个PipeInputStream, PipeReader连接一个PipeWriter.

过滤输出流

FilterOutputStream用例装饰OutputStream,构造函数中需传入一个OutputStream对象,并将此对象保存成成员对象。

BufferedOutputStream & BufferedWriter

BufferedOutputStreamm在Outputstream基础上增加了缓冲区,使用Outputstream输出数据时一般包装成BufferedOutputStream

BufferedWriter为Writer增加缓冲区,此外增加了newLine()方法输出换行符。

    public BufferedWriter(Writer out);
    public void newLine() throws IOException;
DataOutputStream

DataOutputStream实现了DataOutput,在底层OutputStream基础上增加了输出输出原生类型的方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值