java|java io

永远看不懂的Java IO 有一件非常蛋疼的事情,每次准备面试去看Java IO的时候,心里总是无数只草泥马跑过- -
最近心血来潮在看Java编程思想,我简直越看越。
姑且把自己的理解先记下来,有空慢慢补。
基本结构

众所周知,两种:基于字节和基于字符。

字节流:通过8位字节来实现输入输出,处理的是字节(byte)和字节数组。适用于音频文件,图片,歌曲等。
所有的字节流类都继承自InputStream和OutputStream。
字符流:处理的单元为两个字节的Unicode字符,分别操作字符(char),字符数组或者字符串(String)。(字符流由Java虚拟机将字节转化为2个字节地Unicode字符而成,所以对文本的支持比较好)。
所有的字符流都继承自Reader和Writer。
注意:所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列。

在两者之间还会有一些转换,这时候可以用InputStreamReader(从InputStream字节流转换为Reader的字符流)。这时候需要制定字符编码,否则会默认采用系统的编码,出现乱码。
字节流 InputStream
java|java io
文章图片
java inputstream.png 其中用的比较多的FileInputStream和BufferedInputStream
  • FileInputStream: 以字节方式读取file.
三种构造函数
// construct by file name FileInputStream in = new FileInputStream("/Users/lulei/Desktop/test.txt"); File file = new File("/Users/lulei/Desktop/test.txt"); // construct by file in = new FileInputStream(file); // construct by file descriptor FileInputStream in2 = new FileInputStream(in.getFD());

使用方式
byte[] bytes = new byte[1024]; int temp, len = 0; while ((temp = in.read())!= -1) { bytes[len] = (byte) temp; len++; } fs.close(); System.out.println(new String(bytes, 0, len));

  • ByteArrayInputStream 流的来源是一串字节数组
    构造函数
ByteArrayInputStream(byte[] buf); ByteArrayInputStream(byte[] buf, int offset, int len);

  • ObjectInputStream 读取对象类型的数据,将一个序列化的对象通过底层字节输入流读取到程序中
    可以把inputstream包装到ObjectInputStream中,这样就可以直接读取对象了(这个对象必须要是serializable的)
ObjectInputStream input = new ObjectInputStream(new FileInputStream("object.data")); MyClass object = (MyClass) input.readObject(); //etc.input.close();

  • DataInputStream 继承自FilterInputStream,算是一个装饰类。可以返回一些基本类型,而不一定要是byte。
FileInputStream fs = new FileInputStream(file); DataInputStream dataInputStream = new DataInputStream(fs); dataInputStream.readInt();

  • BufferedInputStream 继承自FilterInputStream, 也是装饰类,可以起到一个缓冲的作用,防止每次都真正执行操作。
BufferedInputStream bis = new BufferedInputStream(fs); bis.read();

OutputStream
OutputStream的结构与InputStream基本类似
java|java io
文章图片
OutputStream.png 字符流 Reader
java|java io
文章图片
Reader.png 【java|java io】Reader与InputStream的结构相似,但却有些不同。
比如,BufferedReader并未继承FilterReader。
一些典型的使用方法
  1. 缓冲输入文件 (BufferedReader)
public class BufferedInputFile { public static String read(String fileName) throws IOException { // reading input by lines BufferedReader in = new BufferedReader(new FileReader(fileName)); StringBuilder sb = new StringBuilder(); String s; while( ( s = in.readLine()) != null) { sb.append(s); } in.close(); return sb.toString(); } }

  1. 从内存输入 (StringReader)
    下面的例子读取内存中的String,并且调用read(),每次读取一个字符
public class MemoryInput { public static void main(String[] args) { StringReader in = new StringReader(BufferedInputFile.read("test.txt")); int c; While ((c = in.read()) != -1) { System.out.print((char)c); } } }

  1. 格式化的内存输入
    要读取格式化数据,可以使用DataInputStream, 它是一个面向字节的IO类
public class FormattedMemoryInput{ public static void main(String[] args) { DataInputStream in = new DataInputStream(new ByteInputStream(BufferedInputFile.read("test.txt").getBytes()); in.readByte(); // 返回的就是Byte in.readInt(); // 返回的就是int } }

    推荐阅读