IO流

输入输出流分类

java,io定义了多个流类型来实现输入/输出功能,从不同角度分类如下:

  • 按数据流方向不同分为:输入流,输出流
  • 按处理的数据单位不同分为:字节流,字符流
  • 按功能不同分为:节点流和处理流

字节流:最原始的流,按照字节来读。一个字节(Byte)是8位(bit)。

字符流:字符流是一个字符一个字符的读取数据,一个字符是2个字节。

所有流类型都位于java.io包中,分别继承自四种抽象类类型:

  • 输入流:InputStream(字节流),Reader(字符流)
  • 输出流:OutputStream(字节流),Writer(字符流)

输入输出流是站在程序的角度来说的

节点流和处理流

 

 节点流类型

类型 字符流 字节流
File(文件)

FileReader,FileWriter

FileInputStream,FileOutputStream
Memory Array

CharArrayReader,CharArrayWriter

ByteArrayInputStream,ByteArrayOutputStream
Memory String StringReader,StringWriter -
Pipe(管道) PipedReader,PipedWriter PipedInputStream,PipedOutputStream

处理流类型

处理类型 字符流 字节流
Buffering BufferedReader,BufferedWriter BufferedInputStream,BufferedOutputStream
Filtering FilterReader,FilterWriter FilterInputStream,FilterOutputStream
Converting between bytes and character InputStreamReader,OutputStreamWriter -
Object Serialization - ObjectInputStrem,ObjectOutputStream
Data conversion   DataInputStream,DataOutputStream
Counting LineNumberReader LineNumberInputStream
Peeking ahead PushbackReader PushbackInputStream
Printing PrintWriter PrintStream

InputStream(输入流)

 

 

public class JavaTest {
    public static void main(String[] args) throws IOException {
        //读取中文是乱码,因为其是一个字节一个字节读取的,而汉字占用两个字节,所以读取出来的汉字无法正确显示
        FileInputStream in =null;
        try{
            in=new FileInputStream("F:\\Java笔记\\test.txt");
        } catch (FileNotFoundException e) {
            System.out.println("找不到文件");
            e.printStackTrace();
            System.exit(-1);
        }
        long num=0;//存放读取到字节数
        int b=0;//存放调用read的返回值
        try{
            //read()读取到输入流末尾就返回-1
            while((b=in.read())!=-1){
                //b是read()方法返回的0-255的数字,强制转换为char类型才能显示成英文
                System.out.println((char)b);
                num++;
            }
        }catch(IOException e1){
            System.out.println("读取出错");
        }finally {
            //关闭流,释放内存资源
            in.close();
        }
    }
}

OutputStream(输出流)

 

 

public class JavaTest {
    public static void main(String[] args) throws IOException {
        //读取中文是乱码,因为其是一个字节一个字节读取的,而汉字占用两个字节,所以读取出来的汉字无法正确显示
        FileInputStream in =null;
        FileOutputStream out=null;
        try{
            in=new FileInputStream("F:\\Java笔记\\test.txt");
            out=new FileOutputStream("F:\\Java笔记\\cpye_test.txt");//没有文件会自己创建文件
        } catch (FileNotFoundException e) {
            System.out.println("找不到文件");
            e.printStackTrace();
            System.exit(-1);
        }
        int b=0;//存放调用read的返回值
        try{
            //read()读取到输入流末尾就返回-1
            while((b=in.read())!=-1){
                out.write(b);
            }
        }catch(IOException e1){
            System.out.println("文件复制失败");
            System.exit(-1);
        }finally {
            //关闭流,释放内存资源
            in.close();
            out.close();
        }
    }
}

Reader流

和InputStream一样,区别就是读取的数据单位不同

 

 Writer流

和OutputStream一样,区别就是数据的单位是字符

 

 

public class JavaTest {
    public static void main(String[] args) throws IOException {
        FileWriter fw=null;
        FileReader fileReader=null;
        try{
            fw=new FileWriter("F:\\Java笔记\\test.txt");
            for(int i=0;i<1000;i++){
                fw.write(i);
            }
            int b=0;
            long num=0;
            fileReader=new FileReader("F:\\Java笔记\\test.txt");
            while((b=fileReader.read())!=-1){
                System.out.println((char)b);
                num++;
            }
            System.out.println("读取了"+num);
        }catch(Exception e){
            e.printStackTrace();
        }finally {
            fw.close();
            fileReader.close();
        }
    }
}

处理流

节点流就是直接和数据源连接的流,处理流就是套接在其他流上的流,处理流不直接和数据源连接

缓冲流(Buffering)

缓冲流要套接在相应的节点流之上,对读写的数据提供缓冲功能,提高读写得效率,有4种缓冲流,对应构造方法如下:

BufferedReader(Reader in)
BufferedReader(Reader in,int size)//size为自定义的缓冲区大小
BufferedWriter(Writer out)
BufferedWriter(Writer out,int size)
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out,int size)

对于输出的缓冲流,写的数据会先在内存中缓存,使用flush()方法将会使内存中的数据立刻写入。

读写数据时,先把数据放到缓冲区里,减少IO对硬盘的访问次数。

public class JavaTest {
    public static void main(String[] args) throws IOException {
        FileInputStream in=null;
        try{
            in =new FileInputStream("F:\\Java笔记\\test.txt");
            //在FileInputStream节点流外在套一层处理流
            BufferedInputStream bf=new BufferedInputStream(in);
            int c=0;
            System.out.println((char)bf.read());
            System.out.println((char)bf.read());
            System.out.println("=======");
            bf.mark(20);//加标记
            for(int i=0;i<=10&&(c=bf.read())!=-1;i++){
                System.out.println((char)c);
            }
            System.out.println("========");
            bf.reset();//回到标记处
            for(int i=0;i<10&&(c=bf.read())!=-1;i++){
                System.out.println((char)c);
            }
            bf.close();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (Exception e1){
            e1.printStackTrace();
        }
    }
}

BufferedReader,BufferedWriter

public class JavaTest {
    public static void main(String[] args) throws IOException {
        try {
            FileWriter fileWriter = new FileWriter("F:\\Java笔记\\copy_test.txt");
            BufferedWriter bw=new BufferedWriter(fileWriter);
            String s=null;
            for(int i=0;i<100;i++){
                s=String.valueOf(Math.random());
                bw.write(s);
                bw.newLine();//换行
            }
            bw.flush();
            BufferedReader br=new BufferedReader(new FileReader("F:\\Java笔记\\copy_test.txt"));
            while((s=br.readLine())!=null){
                System.out.println(s);
            }
            bw.close();
            br.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

转换流

InputStreamReader和OutputStreamWriter用于字节数据到字符数据之间的转换,InputStreamReader需要和InputStream套接,OutputStreamWriter需要和OutputStream套接。转换流在构造时可以指定编码集

public class JavaTest {
    public static void main(String[] args) throws IOException {
        try{
            OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("F:\\Java笔记\\test.txt"));
            osw.write("wjzzu,wsdsb");
            System.out.println(osw.getEncoding());//获得当前字符编码
            osw=new OutputStreamWriter(new FileOutputStream("F:\\Java笔记\\test1.txt",true),"ISO8859_1");//在文件后追加,并指定编码
            System.out.println(osw.getEncoding());
            osw.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

数据流

DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,提供可以存取与机器无关的java原始数据类型(int,double)等方法

   public static void main(String[] args) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream=new ByteArrayOutputStream();//在内存里创建一个字节数组
        DataOutputStream dataOutputStream=new DataOutputStream(byteArrayOutputStream);
        try{
            dataOutputStream.writeDouble(Math.random());//把随机double类型的数写入到字节数组中
            dataOutputStream.writeBoolean(false);
            ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
            System.out.println(byteArrayInputStream.available());//获取字节数组有几个字节
            DataInputStream dataInputStream=new DataInputStream(byteArrayInputStream);
            System.out.println(dataInputStream.readDouble());
            System.out.println(dataInputStream.readBoolean());
            dataInputStream.close();
            dataOutputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

注:读取的数据是先写进去的先被读取

打印流

PrintStream和PrintWriter都是打印流,分别针对字节和字符

PrintStream和PrintWriter分别提供了重载的print

Println方法用于多种类型的输出

PrintStream和PrintWriter有自动flush功能,

PrintStream和PrintWriter不会抛出异常,通过检测错误状态来获取错误信息

public class JavaTest {
    public static void main(String[] args) throws IOException {
       PrintStream ps=null;
       try{
           FileOutputStream fos=new FileOutputStream("F:\\Java笔记\\print.txt");
           ps=new PrintStream(fos);
           if(ps!=null){
               System.setOut(ps);//将打印输出窗口连接到流,在文件里输出
           }
           for(char c=0;c<=100;c++){
               System.out.println(c);
           }
       }catch(Exception e){
           e.printStackTrace();
       }
    }
}

对象流

直接将Object写入或读入

对象序列化:

  • transient关键字:用它来修饰的成员变量在序列化的时候不考虑,即当做不存在(默认值)
  • serializable接口:标记型接口
  • externalizable接口
 public static void main(String[] args) throws IOException {
       T t =new T();
       t.k=8;
       try{
           FileOutputStream fos=new FileOutputStream("F:\\Java笔记\\test2.txt");
           ObjectOutputStream ojs=new ObjectOutputStream(fos);
           ojs.writeObject(t);
           ojs.flush();
           ojs.close();
           FileInputStream fis=new FileInputStream("F:\\Java笔记\\test2.txt");
           ObjectInputStream ois=new ObjectInputStream(fis);
           T t1=(T)ois.readObject();
           System.out.println(t1.d+"\t"+t1.k);
           ois.close();
       }catch(Exception e){
           e.printStackTrace();
       }
}

public class T implements Serializable {
    int j=10;
    int i=9;
    double d=2.3;
    int k=15;
}

直接实现Serializable接口的类是JDK自动把这个类的对象序列化,而实现Externalizable接口的类是自己控制对象序列化。

 

posted @ 2021-04-22 16:15  我还有头发  阅读(264)  评论(0编辑  收藏  举报