java IO流详解

2016.08.22-2016.08.24

 

上课类容:IO流

 

请别和我说话,小心我一言不和就放图。好吧,如果作为一名初学者,我相信你看到下面这幅图,整个人就不好了。

 

 一看到这幅图,宝宝吓坏了,瞬间整个人就不好了。

请自行看3遍,谢谢!

下面我们再分别叙述一下字节流和字符流。

 

一:字节流

 

1.IO流体系:对数据进行读写操作,所以说IO流不是读就是写咯。

2.IO流相关的类:都在java.io包下。

   有关的io操作都会产生IOException异常。

3.IO:参照物是程序

   i:input.进来,读取数据到程序中。

   o:output:出去,将数据从程序中写出去。

再放一图




 
 

4:io流的分类,相关的类都会有相应的单词。

         4.1:从数据的流向分。个人理解为就是内存和硬盘之间的数据交换,内存上的数据是暂时性的,而硬盘上的数据是永久性的。

                   Input(输入):读取数据,数据往程序中流。或者说:将硬盘上的数据放到内存上

                   Output(输出):写出数据,将数据从程序中写出去。或者说:将内存上的数据放到硬盘上

         4.2:字节流和字符流

                   Stream:字节流,所有的数据都可以用字节流操作。计算机真正能识别的就是010101这些东西,8个0或者1组合成位,8位就是一个字节了。

                   Reader或者Writer:字符流。字符流是在字节流的基础上加了编码机制。只能对文字进行操作,虽说是文字,更贴切的说是文本文件,并不包括.doc等富文本文件,因为这些文件里面可以放图片或者其他的非文字内容。不能够对图片或者音频文件进行操作。

         InputSteam:读取字节流。OutputStream:输出字节流。

         Reader:读取字符流,   Writer:写出字符流。

5:文件字节流

         OutputStream,:抽象类  

                            文件输出字节流:FileOutputStream:节点流,跟目标设备相关联。

    实例一:

 import java.io.FileOutputStream;
 import java.io.IOException;
 
 public class FileOutputStreamDemo1 {
      
     public static void main(String[] args) throws IOException {
        //1.创建文件输出流对象,参数为全路径名
         FileOutputStream fos = new FileOutputStream("e:\\aa.txt");
         //2.写出数据
         //2.1准备数据
         String str = "要写出的数据";
         //2.2将数据转为字节数组的形式
         byte[] b = str.getBytes();
         //3.0将数据按照一个个字节地写出目标文件中
         /*for(int i=0; i<b.length; i++){
             fos.write(b[i]);
         }*/
         //3.1以下是将整个数组输出去,和3.0可到达相同的效果
         fos.write(b);
         //4.释放资源
        fos.close();
     }
 
 }

 BufferedInputStream:处理流,必须先有节点流。为了增加效率。处理的方式是将节点流包装起来

public static void testBufferedOutputStream() throws IOException{
         //在使用带缓冲区的字节流的时候先要有一个节点流作为参数,或者说先指定一个目标文件
         FileOutputStream fos = new FileOutputStream("d:\\test.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);
         
         //将以下文字写到目标文件中去
         String str = "这几个文字即将通过带缓冲区的字节流写到一个文本文件中";
         bos.write(str.getBytes());
         //写完之后记得要刷新才能真正写入到文件中,不然还会保存在缓冲区里,直到释放资源
         bos.flush();
         //释放资源(关闭流)
         bos.close();
         
     }

 InputStream:抽象类。

                            文件输入字节流:FileInputStream:节点流,和要读取那个文件关联起来

import java.io.FileInputStream;
import java.io.IOException;
 
 public class FileInputStreamDemo1 {
     public static void main(String[] args) throws IOException {
         //1.创建字节输入流对象
        FileInputStream fis = new FileInputStream("e:\\bb.txt");
        //2.开始读取数据
 //        System.out.println((char)fis.read());
         int b;
         while((b=fis.read())!=-1){
             System.out.print((char)b);
         }
         fis.close();
     }
 }

  BufferedOutputStream:带缓冲区的。也是为了增加效率,处理的方式是将节点流包装起来

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

/*
 * 将一个文件的文字输出到控制台
 */
public class BufferedInputStreamDemo1 {
    
    public static void main(String[] args) {
        
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        try {
            fis = new FileInputStream("d:\\aa.txt");
            bis = new BufferedInputStream(fis);
            //byte数组用来装读取到的数据
            byte[] b = new byte[1024];
            int len = -1;
            while((len = bis.read(b))!=-1){
                System.out.println(new String(b, 0, len));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
    }

}

 

6:字节流:在文件系统中,任何文件都是以二进制形式存储的,二进制用位体现(8位为一个二进制单元),8位=1字节,所以字节流可以处理任何文件。

         6.1字节流常用的一些类:

                   6.1.1输入流read(), 读到末尾返回-1

常用read(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。

                            FileInputStream:文件输入流

                            BufferedInputStream:带缓冲区的输入流,先要传入一个节点流(输入流)作为参数

                   6.1.2输出流write()

常用write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。

                            FileOutputStream:文件输入流

                            BufferedOutputStream:带缓冲区的输入流,先要传入一个节点流(输入流)作为参数

  结合输入输出流写一个文件复制的工具

public static boolean copyFile( String filePath,String target){
    
        boolean flag = false;
        //输出流,将数据写入到目标文件中
        FileOutputStream fos = null;
        //输入流,将要用的文本拿到程序中
        FileInputStream fis = null;
        //读取文本
        byte[] b = new byte[1024];
        //每次读取字符数据的有效长度
        int length = -1;
        
        try {
            fis = new FileInputStream(filePath);
            fos = new FileOutputStream(target);
            /*
             * fis.read(b):从fis关联的文件中每次读取 1024 个字节,
             * 并把读取到的字节数据保存这个数组里面,
             * 但是这个文件并不是只有1024 这个么大,有可能要读多次,所以要用循环
             * 寻到的条件是读到文件没有得读了,就是读到最后了就不读了,
             * 读到末尾的返回值是-1,如果返回值是-1则停止循环
             * 
             */
            while((length=fis.read(b)) != -1){//读到文件末尾就返回-1,不在往下读取
                //将读到的数据写入目标文件中
                fos.write(b, 0, length);
                fos.flush();//将数据刷到目标文件
            }
            System.out.println("文件复制成功!");
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            //关闭释放资源
            try {
                fos.close();
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        flag = true;
        return flag;
    }

 

二.字符流

 

1.字符流:在字节流的基础上添加了编码机制。很大程度上和字节流操作一样的,字符流只能操作文本类文件,准确的说应该是纯文本类文件。例如.txt,.java,.cpp,.html等

                   编码:每一个国家都有自己的编码,编码不一致往往导致的结果就是!!乱码!!。中国编码的编码:gbk

                            gbk:英文字母:1个字节,中文:2个字节,系统的默认编码。

                            unicode:统一编码。中文还是英文字母都是占2个字节。

                            utf-8: 国际编码。英文占1个字节,中文占3个字节。

                            文件是用什么编码来写的,那么就用什么编码来读取。最常用的编码是gbk和utf-8.一般的情况下,都设置为utf-8.(还有其他的很多编码:例如GB2312,big5等等)。如果想测试是否像上面所说那么多个字节的话,建议使用Notepad2文本软件,体积小功能强!(似乎再买广告了。。。)

                   Reader:读取数据

                            FileReader:文件读取字符流

                            BufferedReader://带缓冲区的字符输入流

                                     readLine() ;读取一行数据

                                     LineNumberReader;带行号.通过getLineNumber()方法获取行号

 

带行号功能的字符输入流

 

 import java.io.FileReader;
 import java.io.IOException;
 import java.io.LineNumberReader;
 
 /*LineNumberReader是BufferedReader的子类,
  * 比BufferedReader多了设置行号和获取行号的功能。
  * 使用LineNumberReader流读取文本文件,并打印在控制台上。
  * 在每行的前面添加行号。
  */

 public class LineNumberReaderDemo1 {
     public static void main(String[] args) throws IOException {
         String str = null;
           while((str = lnr.readLine()) != null){
//            lnr.setLineNumber(90);//设置行号
             System.out.print(lnr.getLineNumber()+" : ");
            System.out.println(str);
        }
        lnr.clo

 

Writer:写入数据

                            FileWrite:写入数据,记得刷新。

                            BufferedWriter://带缓冲区的字符输出流

                                     newLine():写入换行字符。

 

                                     write(String str):写入字符串。

 

/*
     * 2:用字符流复制文本文件。
     */
    public static boolean copyText(String textPath, String targetPath){
        boolean flag = false;
        if(textPath==null || textPath.trim().equals("")){
            return flag;
        }
        if(targetPath == null || targetPath.trim().equals("")){
            int end = textPath.lastIndexOf(".");
            String endStr = textPath.substring(end);//后缀名
            int index = textPath.lastIndexOf("\\");
            if(index == 0){
                index = textPath.lastIndexOf("/");
            }
            targetPath = textPath.substring(0,end)+"2"+endStr;//新文件名
        }
        
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            //字符输入流
            FileReader fr = new FileReader(textPath);
            br = new BufferedReader(fr);
            //字符输出流
            FileWriter fw = new FileWriter(targetPath);
            bw = new BufferedWriter(fw);
            
            String str = "";
            while((str=br.readLine()) != null){
                bw.write(str);
                bw.newLine();
                bw.flush();
            }
            flag = true;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try{
                bw.close();
                br.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        return flag;
    }
  转换流:可带编码格式的流

 

                            InputStreamReader;字节转换为字符流

转换流示例

public class SystemReadDemo1 {
    
    public static void main(String[] args) throws IOException {
        //获取键盘输入
        InputStream is = System.in;
        //将字节流转换为字符流,用到InputStreamReader(InputStream in)---转换流
        InputStreamReader isr = new InputStreamReader(is,"utf-8");
        //将字符流再转为带缓冲区的字符流
        BufferedReader br = new BufferedReader(isr);
        
        String str = null;
        while(true){
            str = br.readLine();
            if("886".equals(str)){
                break;
            }
            System.out.println(str);
        }
        br.close();
    }

}

OutputStreamWriter ;字符流转换为字节流。

转换流示例二

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;

/*
 * 1:获取键盘录入的数据,将数据写到文件中,但是以utf-8编码的形式写到文件中去。
 */
public class HomeWork1 {
    
    public static void main(String[] args) {
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            br = new BufferedReader(new InputStreamReader(System.in));
            bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("e:\\aa.txt"), "utf-8"));
            
            String str = "";
            while(true){
                str = br.readLine();
                if("exit".equals(str)){
                    //可以尝试不同的编码
                    OutputStreamWriter osw = new OutputStreamWriter(System.out, "GBK");
                    BufferedWriter bw2 = new BufferedWriter(osw);
                    bw2.write("输入结束!");
                    bw2.flush();
                    break;
                }
                bw.write(str);
                bw.newLine();
                bw.flush();
            }
            
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
这一段代码的作用是:因为BufferedInputStream为别的输入流添加缓冲功能,在创建BufferedInputStream时会创建一个内部缓冲数组,
用于缓冲数据,提高性能。默认的缓冲大小是8192KB,如果你要读取的文件大于这个默认的大小时,缓冲区没有读满是不会被写入文件的。
所以要关闭输入流,释放这个流的资源。或者用flush()这个命令强制写入。
 
            try {
                bw.close();
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

 

三.练习

 

1.使用字节流读取500MB~1G的文件,然后再使用缓冲流读取500MB~1G的文件,测试两者的区别

 

猜你喜欢

转载自3056434592.iteye.com/blog/2320158