Java学习之路(十二):IO流

IO流的概述及其分类

  • IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式
  • Java用于操作流的类都在IO包中

流按流向分为两种:输入流(读写数据)     输出流(写数据)

流按操作类型分为两种:

  • 字节流:字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
  • 字符流:字符流只能操作纯字符数据,比较方便

常用的IO流的类

字节流的抽象父类:InputStream     OutputStream

字符流的抽象方法:Reader   Writer

InputStream实现类FileInputStream

InputStream是抽象类,表示字节输入流

FileInputStream从文件系统中的某个文件中获得输入字节。FileInputStream用于读取图像数据之类的原始字节流。要读取字符流,就要用FileReader

构造方法:

  • FileInputStream(File file)
  • FileInputStream(String name)

FileInputStream的构造方法可以传一个File对象,也可以传一个字符串路径

成员方法:

  • int read()   从此输入流中读取到一个数据字节

案例:读取一个txt文件数据

package null08031628;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        File file = new File("C:/Users/Administrator/Desktop/baiduyunpan.txt");
        FileInputStream fis = new FileInputStream(file);
        int i = 0;
        while((i = fis.read()) != -1){
            System.out.println(i);
        }
     fis.close();
} }

 

OutputStream实现类FileOutputStream文件输出流

文件输出流就是用于将数据写入File的输出流

案例:从一个文件读入数据写入另一个文件package null08031638;import java.io.File;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        File filein = new File("C:/Users/Administrator/Desktop/baiduyunpan.txt");
        
        InputStream fis = new FileInputStream(filein);   //创建一个输入流
        
        File fileout = new File("C:/Users/Administrator/Desktop/baiduyunpan-2.txt");
        
        OutputStream fos = new FileOutputStream(fileout);   //创建一个输出流
        
        int i = 0;
        while((i=fis.read())!=-1){
            fos.write(i);
        }
     fos.close();
     fis.close();
} }

 

通过available()方法,进行字节数组拷贝(错误的,不推荐的,如果文件超级大怎么办?)

package null08031700;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        FileInputStream input = new FileInputStream("C:/Users/Administrator/Desktop/baiduyunpan.txt");
        
        FileOutputStream out = new FileOutputStream("C:/Users/Administrator/Desktop/baiduyunpan-3.txt");
        
        byte[] bs = new byte[input.available()];//定义一个文件输入流那么大的字节数组
        input.read(bs); //一次性将数据写入到字节数组中
        
        out.write(bs); //一次性将文件写入
        input.close();
        out.close();
        
        
        
    }

}

 

自定义一个大小的数组,进行一个流的读写(正确的方法)

package null08031707;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        FileInputStream input = new FileInputStream("C:/Users/Administrator/Desktop/baiduyunpan.txt");
        
        FileOutputStream out = new FileOutputStream("C:/Users/Administrator/Desktop/baiduyunpan-3.txt");
        
        byte[] bs = new byte[8*1024];
        
        int i = 0;
        while((i=input.read(bs))!=-1){
            out.write(i);
        }
        out.close();
        input.close();
        
    }

}

 

通过字节数组的方法操作流,其实就是相当于是创建了一个缓冲区

自带缓冲区的实现类BufferedInputStream和BufferedOutputStream

BufferedInputStream

  • 内置了一个缓冲区(就是之前定义的那个数组)
  • 从BufferedInputStream中读取一个字节时,BufferedInputStream会一次性的读入8192个,放在缓冲区,在返回给程序
  • 程序再次读取时,就不会再从文件中取了,直接从缓冲区获取
  • 知道缓冲区中的所有都被用过了,BufferedInputStream才重新从文件中读取8192个

BufferedOutputStream

  • 内置了一个缓冲区(数组)
  • 程序向流中写入字节时,不会直接写到文件,而是先写入缓冲区当中
  • 知道缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写入文件

一个小小的例子:

package null08031732;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        FileInputStream fis = new FileInputStream("C:/Users/Administrator/Desktop/baiduyunpan.txt");
        BufferedInputStream bis = new BufferedInputStream(fis);
        
        FileOutputStream fos = new FileOutputStream("C:/Users/Administrator/Desktop/baiduyunpan-4.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        
        int i;
        while((i=bis.read())!=-1){
            bos.write(i);
        }
        bis.close();
        bos.close();
    }

}

 

带Buffered的流和自己写的字节数组缓冲对比

  • 字节写的数组在速度上回略胜一筹,因为自己写的读和写的操作都是在同一个数组之中
  • 而Buffered操作的是两个数组,所以效率低于一个的

BufferedOutputStream中的一些方法

  • flush()方法:用来刷新缓冲区,刷新后就可以再次写入了
  • close()方法:关闭流,而且在关闭前后会刷新一次缓冲区

补充 

字节流读写中文时乱码的问题

字节流读取中文:

  • 字节流读取中文的问题
  • 字节流在读取中文的时候有可能会读到半个中文,造成乱码

字节流写入中文的问题:

  • 字节流直接操作的字节,所以写入中文的时候必须将字符串转换成字节数组
  • 写出回车换行write("\r\n".getBytes())

流的标准处理异常代码1.6版本前

package null08041019;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        FileInputStream fis = null;
        FileOutputStream fos = null;
        
        try{
            fis = new FileInputStream("");
            fos = new FileOutputStream("");
            
            int b;
            while((b=fis.read())!=-1){
                fos.write(b);
            }
        }finally{
            try{
                fis.close();
            }finally{
                fos.close();
            }
        }
    }
}

 

流的处理1.7版本

package null08041024;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        try(
            //写在括号中的代码,执行完成后,会自动调用对象的close方法
            //能写在括号中的代码的类一定是要继承AutoCloseable接口的类
            FileInputStream fis = new FileInputStream("");
            FileOutputStream fos = new FileOutputStream("");
                
        ){
            int i;
            while((i=fis.read())!=-1){
                fos.write(i);
            }
        }
    }

}

一个图片加密的例子:

package null08041031;

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

public class Demo01 {

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in); 
        System.out.println("请将图片放到和此文件的同级目录下");
        System.out.println("请输入要加密的文件名:");
        String fileName = sc.nextLine();
        System.out.println("请输入加密后的文件名:");
        String endFileName = sc.nextLine();
        System.out.println("请输入密码:");
        String pwd = sc.nextLine();
        int pwdInt = Integer.parseInt(pwd);
        
        try(
            FileInputStream fis = new FileInputStream(fileName);
            FileOutputStream fos = new FileOutputStream(endFileName);
            ){
            int i;
            while((i=fis.read())!=-1){
                fos.write(i^pwdInt);
            }
        }finally{
            System.out.println("加密结束");
        }

    }

}
代码

 

posted @ 2018-08-02 06:57  "%201  阅读(172)  评论(0编辑  收藏  举报