天天看点

IO流的详解!超详细! IO流

IO流

Java的IO通过java.io包下的类和接口来支持,在java.io包下主要包括输入、输出两种IO流,每种输入、输出流又可以分为字节流和字符流两大类。其中字节流是以字节为单位来处理输入输出的操作,而字符流则是以字符来处理输入输出的操作。除此之外,JavaIO使用了一种装饰器设计模式,又可以将IO流分为底层的节点流和上层的处理流。

 流的分类:

1:输入流和输出流  

   输入流:只能从中读取数据,不能写入数据。

    输出流:只能写入数据,而不能读取数据。

   Java中的输入流主要是右InputStream和Reader作为基类,而输出流主要是由OutputStream和Writer作为基类。他们都是抽象类,无法创建实例。

2:字节流和字符流

字节流:的操作数据单元是8位字节。

字符流:的操作数据是16位字符。

字节流中 InputStream与OutputStream为字节流的基类,Reader和Writer为字符流的基类。

3:节点流和处理流

节点流:可以向/从 一个特定的IO设备读写数据的流,  节点流连接着数据源和程序。互相关联。

处理流:用于对已经存在的一个流进行连接和封装,通过封装后的流来实现数据的读写功能。程序使用处理流之后并不会直接连接到数据源,使用处理流的好处是,只要使用相同的处理流,程序就可以采用完全相同的输入输出代码访问不同的数据源,随着处理流封装的节点流的变化,程序实际访问的数据源也发生了变化。

流的概念模型

字节流和字符流处理的方式非常的相似,只是输入输出的单位不同而已,输入流使用隐式指针来记录从哪个位置开去读取,每当InputStream或者Reader里取出一个数据后,记录的指针自动向后移一位,除此之外,InputStream和Reader都提供了一些二方法来记录了指针的移动。输出流也一样。

处理流可以嫁接在任何一个已经存在的流的基础之上,这就允许了Java采用了相同的代码,透明的方式来访问不同的输入/输出设备的数据流,通过使用处理流,Java程序不需要在意输入输出的节点是什么,程序只要把这些节点包装成处理流,就可以使用相同的处理流的代码来进行读写。

字节流和字符流

    1:输入流

InputStream和Reader是输入流的抽象基类,本身不能创建实例来进行输入,但是他们是所有输入流的模板。

它们的操作方式基本一样,只是inputStream操作的是字节,而Reader操作的是字符。

InputStream(字节输入流)方法:

int read():从输入流中读取单个字节,返回读取字节的数据。

int read(byte[ ]b):从输入流中读取最多b.length个字节的数据。并把读取出来的数据存取在b数组中,返回实际读取的字节数。

int read(byte[ ]b,int off,int len):从输入流最多读取len个字节的数据,放入数组b中,从off的位置开始存放,返回实际读取的字节数。

Reader(字节输出流的方法大致相同,字节输入流只不过存取读取的数据用byte类型的数组来进行存,但是reader使用char类型的数组进行存取,因为它是字符输入流)

那么我们如何判断读取的数据到了结尾呢?根据指针的指引,每次读取一个数据,指针向后指引,当指针为-1的时候,便说明了读取完毕。就到达了输入流的结束点。

由于inputStream和OutputStream都是抽象类,本身不能创建实例,但是他们都有一个读取文件的输入流:FileInputStream和FileReader。他们本身都是节点流————直接和文件相关联

package fileinput;

import java.io.FileInputStream;
import java.io.FileNotFoundException;

public class FileInput {
    public static void main(String[] args) throws Exception {
        FileInputStream fileInputStream=new FileInputStream("G:\\a.txt");
        //向使用b数组来存取G盘文件的内容
        //因为程序创建了长度为1024的数组来进行读取,但是长度却达不到1024,所以说只要执行一次read
        //就能读取所有的文本数据
        byte[]b=new byte[1024];
        //length定义一个记录存取长度的变量
        int len=0;
        while ((len=fileInputStream.read(b))!=-1){
            System.out.println(new String(b,0,len));

        }
        fileInputStream.close();

    }
}
           
IO流的详解!超详细! IO流

使用FileReader来读取文件:

package fileinput;

import java.io.FileReader;
import java.io.IOException;

public class FileReaderTest {
    public static void main(String[] args) throws IOException{
        FileReader fileReader=new FileReader("G:\\b.txt");
        char[]c=new char[1024];
        int len=0;
        while ((len=fileReader.read(c))!=-1){
            System.out.println(new String(c,0,len));
        }
        fileReader.close();
    }
}
           
IO流的详解!超详细! IO流

    2:输出流(字节输出流和字符输出流)

OutputStream和Writer也非常相似

OutputStream输出流的三种方法:

 1:void write(int c) 将指定的字节字符输出到输出流中,其中c既可以代表字节,也可以代表字符。

2:void write(byte【】/char【】buf):将指定的字节数组或者字符数组输出到输出流中

3:void write(byte[ ]/char [ ]buf,int off,int len)将字节数组或者字符数组从off的位置开始,长度为len的字节或者字符输出到输出流当中。

writer的方法也相似,只不过字节输出流输出的是字节或者字符,而writer输出的是字符串String

下面使用FileInputStream来进行输入,FileOutputStream来进行输出,实现文字的复制:

package fileinput2;


import fileinput.FileInput;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyTest {
    public static void main(String[] args) throws IOException{
        //读取a的文件内容
        FileInputStream fileInputStream=new FileInputStream("G:\\a.txt");
        byte[]b=new byte[1024];
        int len=0;
        len=fileInputStream.read(b);
        fileInputStream.close();
        //将读取内容写入b
        FileOutputStream fileOutputStream=new FileOutputStream("G:\\b.txt");
        fileOutputStream.write(b,0,len);
        fileOutputStream.close();
        //将B中文件进行输出
        FileInputStream fileInputStream1=new FileInputStream("G:\\b.txt");
        while ((len=fileInputStream1.read(b))!=-1){
            System.out.println(new String(b,0,len));
        }
        fileInputStream1.close();


    }
}
           

通过字符流实现文字拷贝:

package fileinput2;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyString {
    public static void main(String[] args) throws IOException{
        FileReader fileReader=new FileReader("G:\\a.txt");
        char[]c=new char[1024];
        int len=0;
        len=fileReader.read(c);
        fileReader.close();
        //读取
        FileWriter fileWriter=new FileWriter("G:\\b.txt");
        fileWriter.write(c,0,len);
        fileWriter.close();
        //打印b
        FileReader fileReader1=new FileReader("G:\\b.txt");
        while((len=fileReader1.read(c))!=-1){
            System.out.println(new String(c,0,len));
        }
        fileReader1.close();

    }
}
           

我们使用了输出输出流的4个抽象的基类,并且使用了4中方法来对文件输入输出等访问,

字节流 基类:FileInputStream  FileOutputStream  字符流基类:FileReader  FileWriter

输入流:FileInputStream   FileReader                     输出流:FileOutputStream   FileWriter

发现使用起来比较繁琐,所以我们需要一种办法来简化操作,这时我们需要认识一下处理流了。

处理流:

我们尝试用PrintStream来对FileOutputStream进行处理输出

package chuliStream;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;

public class PrintStreamTest {
    public static void main(String[] args)throws IOException {
        FileOutputStream fileOutputStream=new FileOutputStream("G:\\a.txt");
        PrintStream ps=new PrintStream(fileOutputStream);//对字节流进行包装
        ps.println("嘿嘿嘿");
        ps.println("哈哈哈哈");//可以将里面的内容进行存储
        ps.close();//我们只需要关闭最上层的处理流,包装的节点流也就关闭了

    }
}
           

转换流:

将字节流转换成字符流,有两个InputStreamReader和OutputStreamWriter

为什么只是字节流转换成字符流?

因为大家都知道,字节流用途更广,但是字符流操作起来比较方便,当我们知道一个文件都是文本内容,但是我们只有一个字节流,操作起来相当繁琐,所以我们需要转换流来对字节流进行转换,这样操作起来就十分的方便。

就比如说我们要从键盘上获取数据,但是标准的输入流是InputStream是字节流,处理起来十分难受,但是键盘输入的都是文本内容。普通的Reader的方法读取文本也很繁琐,所以我们引入转换输入流InputStreamReader(字符输入流),再将字符输入流包装成为BufferedReader。使用readLine方法进行一行一行读取,十分方便。

package chuliStream;

import java.io.*;

public class ZhuanHuanLiu {
    public static void main(String[] args)throws Exception {
        InputStreamReader inputStreamReader=new InputStreamReader(System.in);
        BufferedReader b=new BufferedReader(inputStreamReader);//包装转换字符流
//        System.out.println(b.readLine());//将键盘输入的进行打印

        FileOutputStream file=new FileOutputStream("G:\\b.txt");
        OutputStreamWriter outputStreamWriter=new OutputStreamWriter(file);
        BufferedWriter bufferedWriter=new BufferedWriter(outputStreamWriter);//处理流效率高
        bufferedWriter.write(b.readLine());
        bufferedWriter.close();
        b.close();
    }
}
           

对象的序列化:

 对象的序列化就是将对象目标保存在磁盘中,或者允许网络中直接传输对象,Java序列化的机制是允许将对象直接转化为网络中的二进制流,可以通过这种二进制流传输到网络中的另一个节点,其他网络中或者程序中获得了该二进制流都可以将其还原成Java中之前的对象。

对象的序列化:是将Java中的对象写入IO流中。

对象的反序列化:从IO流中读取到 Java对象。

为了让某个类的对象可以序列化,这个类必须要是可以序列化的,所以就需要导入Serializable接口。

因为传输的是 对象,所以我们需要引入两个处理流

ObjectInputStream、ObjectOutputStream    对象输入流和对象输出流

因为这两个流都是处理流,需要包装节点类,所以在使用他们的时候还需要一个节点流来搭配着使用

ObjectOutputStream使用方法

TCP 发送方 和接收方,发送方发送对象,接收方接受对象,返回ok

package socket;

import java.io.*;
import java.net.Socket;

public class SSocket {
    public static void main(String[] args) throws Exception{
        Socket socket=new Socket("192.168.55.16",9999);
        ObjectOutputStream objectOutputStream=new ObjectOutputStream(
           socket.getOutputStream());
        Person p=new Person("刘大",11);
        Person p2=new Person("六二",15);
        objectOutputStream.writeObject(p);
        objectOutputStream.writeObject(p2);


        InputStreamReader inputStreamReader=new InputStreamReader(socket.getInputStream());
        BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
        String str=bufferedReader.readLine();
        System.out.println(str);



        objectOutputStream.close();
        inputStreamReader.close();
        socket.close();
    }
}
           
package socket;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerSocketTest {
    public static void main(String[] args)throws Exception {
        ServerSocket serverSocket=new ServerSocket(9999);
        while (true) {
            Socket socket = serverSocket.accept();
            ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
            System.out.println(objectInputStream.readObject());
            System.out.println(objectInputStream.readObject());


            OutputStreamWriter outputStreamWriter=new OutputStreamWriter(socket.getOutputStream());
            BufferedWriter bufferedWriter=new BufferedWriter(outputStreamWriter);
            bufferedWriter.write("ok");
            //刷新
            bufferedWriter.newLine();
            bufferedWriter.flush();

            objectInputStream.close();
            outputStreamWriter.close();
            socket.close();
        }
    }
}