基础
在Java API中,称可以写字节序列的对象为输出流,可以读字节序列的对象称为输入流。
字节序列的来源或去向通常是文件,但也可以是网络连接或者内存块。
抽象类InputStream
和 OutputStream
构成输入输出流的基础。
面向字节的流在处理Unicode编码的信息时很不方便。(Unicode编码使用多字节编码)所以就有另一系列的类去专门处理,他们的抽象类是Reader
和Writer
。这些类有基于双字节Unicode编码的读和写的方法。
abstract int read()
返回读取的字节,如果返回-1表明到达输入流的结束。
abstract void write(int b)
写一个字节到输出流。
这两个方法都是阻塞的,也就是说线程会挂起直至字节确实读入或写出。对比NIO:
NIO
NIO是在JDK 1.4加入的,可以看做NEW IO,亦可以看做 Non-blocking IO
。即非阻塞式IO,与旧的阻塞式IO区别是,当等待输入时,如调用 abstract int read()方法时,使用NIO,线程不会挂起,而是返回一个值。这有什么优势呢?我们应该都用Java写过聊天室。为了提高效率,在服务端,会对每一个客户端创建一个线程去处理(创建新的线程处理socket)。这样在人数小的时候的确好用,但当成千上万人的时候,这么多线程的消耗就很大了(很多线程挂起了,要保存其状态,虽然不耗费CPU资源,但耗费内存)。而使用NIO则不用每个客户端创建一个线程,而是使用单线程处理,把请求(如连接、读、写)都放到某个类,单线程不断对那个类的实例进行处理(取出等待完IO的请求)。就是不会去等待IO,而是不时去看下IO是否完成。
分类
读写文本文件内容
try(PrintWriter printWriter=new PrintWriter("d:/a.txt","GBK")){
printWriter.print("写东西");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
try(BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(new FileInputStream("d:/a.txt"),"GBK"))){
String line;
while((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
对象流和对象序列化
类要实现Serializable接口(没有方法的functional interface),表明这个类可以序列化
class Person implements Serializable{
public String name="";
public boolean sex=false;
}
Person p=new Person();
p.name="温睿诚";
p.sex=true;
try ( ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream("d:/a.txt"))){
out.writeObject(p);
} catch (IOException e) {
e.printStackTrace();
}
try(ObjectInputStream in=new ObjectInputStream(new FileInputStream("d:/a.txt"))) {
p= (Person) in.readObject();
System.out.println(p.name);
System.out.println(p.sex==true?"男":"女");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}