Java—IO流

IO流原理

一、流的分类

  1. 操作数据单位:字节流、字符流
  2. 数据流向:输入流、输出流
  3. 流的角色:字节流、处理流

二、流的体系结构

抽象基类节点流(或文件流)缓冲流(处理流的一种)
InputStreamFileInputStreamBufferedInputStream
OutputStreamFileOutputStreamBufferedOutputStream
ReaderFileReaderBufferedReader
WriterFileWriterBufferedWriter

三、具体代码分析

3.1 FileReader字符流的使用

3.1.1 read的简单使用
public class FileReaderWriterTest {   
    @Test
    public void testFileReader() {
        //1、实例化File类的对象,指明要操作的文件
        File file=new File("hello");
        //2、提供具体的流
        FileReader fr= null;
        try {
            fr = new FileReader(file);
            //数据的读入
            //read():返回读入的字符。如果到达文件的末尾则返回-1;
            int data;
            while((data=fr.read())!=-1){
                System.out.print((char)data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //流的关闭
            try {
                //当fr = new FileReader(file);出现异常时,可能会导致没有造好对象,有可能导致空指针
                if(fr!=null){
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
3.1.2 总结说明
  • read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1。
  • 异常处理:为了保证资源一定可以执行关闭操作,需要使用try-catch-finally处理。
  • 读入的文件一定要存在,否则会报FileNotFoundException异常。
3.1.3 read的重载方法
public class FileReaderWriterTest {  
    @Test
	public void testFileReader1(){
        //1、File类的实例化
        File file=new File("hello");
        //2、FileReader流的实例化
        FileReader fr=null;
        try {
            fr=new FileReader(file);
            //3、读入操作
            //read(char[] tmp):返回每次读入tmp数组中的字符的个数。如果达到文件末尾返回-1.
            char [] tmp=new char[5];
            int len;
            while((len=fr.read(tmp))!=-1){
                //方式一:
                //错误写法
//                for (int i = 0; i <tmp.length ; i++) {
//                    System.out.print(tmp[i]);
//                }
                //正确写法
//                for (int i = 0; i <len ; i++) {
//                    System.out.print(tmp[i]);
//                }
                //方式二:
                //错误写法
//                String str=new String(tmp);
//                System.out.print(str);
                //正确写法
                String str=new String(tmp,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //3、资源的关闭
                if(fr!=null){
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.2 FileWriter字符流的使用

3.2.1 writer方法的使用
public class FileReaderWriterTest {    
    @Test
    public void testFileWriter()  {
        //1、提供File类的对象,指明写出到的文件
        File file=new File("helloworld");
        FileWriter fw=null;
        try {
            //2、提供FileWriter的对象,用于数据的写出
            fw=new FileWriter(file);

            //3、写出
            fw.write("I have a dream!\n");
            fw.write("you need to have a dream!");
            
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、流的关闭
            try {
                if(fw!=null){
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
3.2.2 总结说明
  • 输出操作对应文件可以不存在,并不会报异常
  • File对应的硬盘中的文件如果存在:
  • 如果使用构造器:FileWriter(file,false)/FileWriter(file):对原有文件进行覆盖
    - 如果使用构造器:FileWriter(file,true):不会对原有文件进行覆盖,而是在原有文件基础上追加内容。

3.3 文件的复制操作

3.3.1 代码实现
  • FileReader和FileWriter
public class FileReaderWriterTest {
    @Test
    public void testFileReaderWriter() {
        //1、创建File类的对象,指明读入和写出的文件
        File srcFile=new File("helloworld");
        File desFile=new File("hello1");
        FileReader fr= null;
        FileWriter fw= null;
        try {
            //2、创建输入和输出流对象
            fr = new FileReader(srcFile);
            fw = new FileWriter(desFile);
            //3、数据的读入和写出操作
            char [] cbuf=new char[5];
            int len;
            while((len=fr.read(cbuf))!=-1){
                fw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //4、关闭流资源
                if(fw!=null){
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fr!=null){
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
3.3.2 总结说明
  • 相当于是对一个文件进行复制
  • 不能去操作图片等字节数据

3.4 FileInputStream的使用

  • 字节流

  • 代码实现

public class FileInputOutputStreamTest {
    @Test
    public void teatFileInputStream() {
        //1、创建文件
        File file=new File("hello");
        FileInputStream fis= null;
        try {
            //2、创建输入流
            fis = new FileInputStream(file);
            //3、读入数据
            byte[] buffer=new byte[5];
            int len;//记录每次读取的字节的个数
            while((len=fis.read(buffer))!=-1){
                String str=new String(buffer,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fis!=null){
                    //4、关闭资源
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.5 图片复制

  • FileOutputStream
public class FileInputOutputStreamTest {
    //实现对图片的复制操作
    @Test
    public void testFileInputOutputStream() {
        //创建文件
        File srcFile=new File("1000610.jpg");//源路径
        File desFile=new File("2.jpg");//目的路径
        FileInputStream fis= null;
        FileOutputStream fos= null;
        try {
            //创建流
            fis = new FileInputStream(srcFile);
            fos = new FileOutputStream(desFile);
            //复制的过程
            byte[] buffer=new byte[5];
            int len;
            while((len=fis.read(buffer))!=-1){
                fos.write(buffer,0,len);
            }
            System.out.println("复制成功!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fos!=null){
                    //关闭流
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fis!=null){
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.6 总结

  • 对于文本文件(.txt .java .c .cpp…),使用字符流处理。
  • 对于非文本文件(.jpg .mp3 .mp4 .avi .doc .ppt …)使用字节流处理。
  • 步骤:
    • 创建文件
    • 创建流
    • 读或写数据
    • 关闭流

四、流的转换

4.1 处理流到缓冲流

4.1.1 概述
  • 缓冲流在内部提供了一个缓冲区,会提高读写速率
  • 处理流,就是“套接”在已有流之上
4.1.2 具体分类
  • BufferedInputStream(字节流)
  • BufferedOutputStream(字节流)
  • BufferedReader(字符流)
  • BufferedWriter(字符流)
4.1.3 代码实现
  • 字节流
public class BufferedTest {
    @Test
    public void BufferedStreamTest() {
        BufferedInputStream bis= null;
        BufferedOutputStream bos= null;
        try {
            //1、造文件
            File srcFile=new File("2.jpg");
            File desFile=new File("3.jpg");
            //2、造流
            //2.1 造节点流
            FileInputStream fis=new FileInputStream(srcFile);
            FileOutputStream fos=new FileOutputStream(desFile);
            //2.2 造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);
            //3、复制的细节:读取、写入
            byte[] buffer=new byte[10];
            int len;
            while((len=bis.read(buffer))!=-1){
                bos.write(buffer,0,len);
//                bos.flush();//刷新缓冲区
            }
            System.out.println("复制成功!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4、资源关闭
            //先关闭外层,后关闭内层
            try {
                if(bis!=null){
                    bis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(bos!=null){
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //说明:在关闭外层流的同时,内层流会自动关闭。
//        fis.close();
//        fos.close();
    }
}
  • 字符流
public class BufferedTest {
    /**
     * 使用BufferedReader和BufferedWriter实现对文本文件的复制
     */
    }
    @Test
    public void testBufferedReaderBufferedWriter2(){
        BufferedReader bf = null;
        BufferedWriter bw= null;
        try {
            //1、创建文件和相应的流
            bf = new BufferedReader(new FileReader(new File("hello")));
            bw = new BufferedWriter(new FileWriter(new File("hello3")));
            //2、读写操作
            //方式一:
            char[] buffer=new char[10];
            int len;
            while((len=bf.read(buffer))!=-1){
                bw.write(buffer,0,len);
            }
            //方式二:readLine():一次读一行
            String data;
            while((data=bf.readLine())!=null){
                //方法一:
//                bw.write(data);//data中不包含换行符
                //方法二:
                bw.write(data);
                bw.newLine();//提供换行操作
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //3、关闭资源
                if(bf!=null){
                    bf.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(bw!=null) {
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4.2 处理流到转换流

4.2.1 概述

转换流属于字符流,将一个字节的输入流转换为字符的书输入流,将一个字符的输出流转换为字节的输出流。

4.2.2 具体分类
  • InputStreamReader:将一个字节的输入流转换为字符的输出流
  • OutputStreamWriter:将一个字符的输出流转换为字节的输出流
4.2.3 代码实现
  • InputStreamReader的使用
public class InputStreamReaderTest {
    @Test
    public void test1() {
        InputStreamReader isr= null;
        try {
            FileInputStream fis=new FileInputStream("hello1");
            isr = new InputStreamReader(fis,"UTF-8");//默认为文件保存时的字符集

            char [] cbuf=new char[5];
            int len;
            while((len=isr.read(cbuf))!=-1){
                String str=new String(cbuf,0,len);
                System.out.print(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(isr!=null){
                    isr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  • 综合使用InputStreamReader和OutputStreamWriter
public class InputStreamReaderTest {
	@Test
    public void teat2(){
        //1、造文件、造流
        File file1=new File("hello1");
        File file2=new File("hello_gbk");
        InputStreamReader isr= null;
        OutputStreamWriter osw= null;
        try {
            FileInputStream fis=new FileInputStream(file1);
            FileOutputStream fos=new FileOutputStream(file2);

            isr = new InputStreamReader(fis,"utf-8");
            osw = new OutputStreamWriter(fos,"gbk");
            //2、读写过程
            char[] cbuf=new char[5];
            int len;
            while((len=isr.read(cbuf))!=-1){
                osw.write(cbuf,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3、资源关闭
            try {
                if(isr!=null){
                    isr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(osw!=null){
                    osw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4.3 其他流

4.3.1 标椎的输入输出流
  • System.in:标准的输入流,默认从键盘输入
  • System.out:标准的输出流,默认从控制台输出
  • System类的setIn()/setOut()方式重新指定输入和输出流
4.3.2 代码实现
public class OtherStreamTest {
    public static void main(String[] args) {
        test1();
    }
    public static void test1() {
        BufferedReader br = null;
        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            br = new BufferedReader(isr);
            while (true) {
                System.out.println("请输入字符串:");
                String data = br.readLine();
                if (data.equalsIgnoreCase("e") || data.equalsIgnoreCase("exit")) {
                    System.out.println("程序退出!");
                    break;
                }
                String upperCase = data.toUpperCase();
                System.out.println(upperCase);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ysw!不将就

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值