字节流-FileInputStream_FileOutputStream_BufferedInputStream_BufferedOutputStream

20.01_IO流(IO流概述及其分类)

  • 1.概念

    • IO流用来处理设备之间的数据传输
    • Java对数据的操作是通过流的方式
    • Java用于操作流的类都在IO包中
    • 流按流向分为两种:输入流,输出流。
    • 流按操作类型分为两种:
      • 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
      • 字符流 : 字符流只能操作纯字符数据,比较方便。
  • 2.IO流常用父类
    • 字节流的抽象父类:

      • InputStream
      • OutputStream
    • 字符流的抽象父类:
      • Reader
      • Writer
  • 3.IO程序书写
    • 使用前,导入IO包中的类
    • 使用时,进行IO异常处理
    • 使用后,释放资源

20.02_IO流(FileInputStream)

  • read()一次读取一个字节
public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("xxx.txt");       //创建流对象
        int b;
        while((b=fis.read())!=-1){                                  //从硬盘上读取一个字节,读到文件结尾,返回-1
            System.out.println(b);
        }
        fis.close();                                                //关闭流对象
    }

20.03_IO流(read()方法返回值为什么是int)

  • read()方法读取的是一个字节,为什么返回是int,而不是byte
  • 因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111

    那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上

    24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型

20.04_IO流(FileOutputStream)

  • write()一次写出一个字节
public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("yyy.txt");   //创建流对象
        int b;
        while((b=fis.read())!=-1){                              //从硬盘上读取一个字节,读到文件结尾,返回-1
            System.out.println(b);                              //这里读取的一个字节,前面补24个0,凑成4个字节,转为int
        }
        fis.close();                                            //关闭流对象

        FileOutputStream fos = new FileOutputStream("yyy.txt"); //创建写流对象,如果文件不存在,则创建
        fos.write(97);                                          //写入一个字节,写入时会去掉前面补的24个0,则作为一个字节存入
        fos.write(98);
        fos.write(99);
        fos.close();
    }

20.05_IO流(FileOutputStream追加)

  • A:案例演示

    • FileOutputStream的构造方法写出数据如何实现数据的追加写入

FileOutputStream在创建对象的时候,如果没有这个文件就帮我创建出来,如果有这个文件,就会先将文件清空,再写入。在第二个参数传true,则是继续追加。

  • FileOutputStream fos = new FileOutputStream(“bbb.txt”,true); //如果没有bbb.txt,会创建出一个

    //fos.write(97); //虽然写出的是一个int数,但是在写出的时候会将前面的24个0去掉,所以写出的一个byte

    fos.write(98);

    fos.write(99);

    fos.close();

20.06_IO流(拷贝图片)

  • FileInputStream读取
  • FileOutputStream写出
  • IO流核心代码:
    FileInputStream fis = new FileInputStream("致青春.mp3");   //创建输入流对象,关联致青春.mp3
    FileOutputStream fos = new FileOutputStream("copy.mp3");//创建输出流对象,关联copy.mp3
    
    int b;
    while((b = fis.read()) != -1) {
        fos.write(b);
    }
    
    fis.close();
    fos.close();
    

20.07_IO流(拷贝音频文件画原理图)

  • A:案例演示

    • 字节流一次读写一个字节复制音频
  • 弊端:效率太低

20.08_IO流(字节数组拷贝之available()方法)

  • A:案例演示

    • int read(byte[] b):一次读取一个字节数组
    • write(byte[] b):一次写出一个字节数组
    • available()获取读的文件所有的字节个数
  • 弊端:有可能会内存溢出
    //一次性读取到字节数组中,但是当文件过大时,会发生内存溢出
        FileInputStream fis = new FileInputStream("致青春.mp3");
        FileOutputStream fos = new FileOutputStream("copy.mp3");
        byte[] arr = new byte[fis.available()];                 //根据文件大小做一个字节数组
        fis.read(arr);                                          //将文件上的所有字节读取到数组中
        fos.write(arr);                                         //将数组中的所有字节一次写到了文件上
        fis.close();
        fos.close();

20.09_IO流(定义小数组)

  • write(byte[] b)
  • write(byte[] b, int off, int len)写出有效的字节个数

20.10_IO流(定义小数组的标准格式)(可以)

  • A:案例演示

    • 字节流一次读写一个字节数组复制图片和视频

      FileInputStream fis = new FileInputStream(“致青春.mp3”);

      FileOutputStream fos = new FileOutputStream(“copy.mp3”);

      int len;

      byte[] arr = new byte[1024 * 8]; //自定义字节数组,1024的整数倍

      while((len = fis.read(arr)) != -1) {

      //fos.write(arr);

      fos.write(arr, 0, len); //写出字节数组写出有效个字节个数

      }

      fis.close();

      fos.close();

20.11_IO流(BufferedInputStream和BufferOutputStream拷贝)(可以)

  • A:缓冲思想

    • 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
    • 这是加入了数组这样的缓冲区效果,java本身在设计的时候,
    • 也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流
  • B.BufferedInputStream
    • BufferedInputStream内置了一个缓冲区(数组)
    • 从BufferedInputStream中读取一个字节时
    • BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个
    • 程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
    • 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
  • C.BufferedOutputStream
    • BufferedOutputStream也内置了一个缓冲区(数组)
    • 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
    • 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
  • D.拷贝的代码
    FileInputStream fis = new FileInputStream("致青春.mp3");           //创建文件输入流对象,关联致青春.mp3
    BufferedInputStream bis = new BufferedInputStream(fis);         //创建缓冲区对fis装饰
    FileOutputStream fos = new FileOutputStream("copy.mp3");        //创建输出流对象,关联copy.mp3
    BufferedOutputStream bos = new BufferedOutputStream(fos);       //创建缓冲区对fos装饰
    
    int b;
    while((b = bis.read()) != -1) {
        bos.write(b);
    }
    
    bis.close();                        //只关装饰后的对象即可
    bos.close();
    

  • E.小数组的读写和带Buffered的读取哪个更快?
    • 定义小数组如果是8192个字节大小和Buffered比较的话
    • 定义小数组会略胜一筹,因为读和写操作的是同一个数组
    • 而Buffered操作的是两个数组

20.12_IO流(flush和close方法的区别)

  • flush()方法

    • 用来刷新缓冲区的,刷新后可以再次写出
  • close()方法
    • 用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出

20.13_IO流(字节流读写中文)

  • 字节流读取中文的问题

    • 字节流在读中文的时候有可能会读到半个中文,造成乱码
  • 字节流写出中文的问题
    • 字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组
    • 写出回车换行 write(“\r\n”.getBytes());
/**
     * 字节流操作中文,可能出现乱码
     * 读的时候,会出现乱码,但是写的时候没事
     * 解决办法:字符流操作
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        //Demo1();
        FileOutputStream fos = new FileOutputStream("yyy.txt");
        fos.write("你好你好啦啦啦".getBytes());
        fos.write("\r\n".getBytes());
    }

    private static void Demo1() throws FileNotFoundException, IOException {
        FileInputStream fis = new FileInputStream("xxx.txt");
        FileOutputStream fos = new FileOutputStream("yyy.txt");

        byte[] arr = new byte[4];
        int len;
        while((len=fis.read(arr))!=-1){
            fos.write(arr,0,len);
            System.out.println(new String(arr,0,len));
        }
        fis.close();
        fos.close();
    }

20.14_IO流(流的标准处理异常代码1.6版本及其以前)

  • try finally嵌套,,,尽可能关闭流

    FileInputStream fis = null;
    FileOutputStream fos = null;
    try {
        fis = new FileInputStream("aaa.txt");
        fos = new FileOutputStream("bbb.txt");
        int b;
        while((b = fis.read()) != -1) {
            fos.write(b);
        }
    } finally {
        try {
            if(fis != null)
                fis.close();
        }finally {
            if(fos != null)
                fos.close();
        }
    }
    

20.15_IO流(流的标准处理异常代码1.7版本)

  • try close
public class Demo5_FileInputStream {

    public static void main(String[] args) throws Exception {
        try(
                FileInputStream fis = new FileInputStream("xxx.txt");
                FileOutputStream fos = new FileOutputStream("yyy.txt");
                MyClose mc = new MyClose();
            ){
            int b;
            while((b=fis.read())!=-1){
                fos.write(b);
            }
        }
        //把流写在try的()里,{}执行完,会自动关闭,
        //因为FileInputStream,FileOutputStream都实现了AutoCloseable里的close(),
        //所以我自定义MyClose类,实现AutoCloseable里的close(),也可以自动关闭了。
    }
}
class MyClose implements AutoCloseable{

    @Override
    public void close() throws Exception {
        System.out.println("我关了");
    }

}
  • 原理

    • 在try()中创建的流对象必须实现了AutoCloseable这个接口,如果实现了,在try后面的{}(读写代码)执行后就会自动调用,流对象的close方法将流关掉

20.16_IO流(图片加密)

  • 给图片加密

    将写出的字节异或上一个数,这个数就是秘钥,解密的时候再异或上这个数就可以了。

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(“a.jpg”));

    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(“b.jpg”));

    int b;
    while((b = bis.read()) != -1) {
        bos.write(b ^ 123);
    }
    
    bis.close();
    bos.close();
    

20.17_IO流(拷贝文件)

  • 在控制台录入文件的路径,将文件拷贝到当前项目下
package com.hongwei.FileStream;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;

public class Demo6_FileInputStream {

    /**
     * 在控制台录入文件的路径,将文件拷贝到当前项目下
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        File file = getFile();
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file.getName()));

        int len;
        byte[] arr =new byte[8192];
        while((len=bis.read(arr))!=-1){
            bos.write(arr,0,len);
        }
        bos.close();
        bis.close();
    }
    public static File getFile(){
        System.out.println("请输入文件路径:");
        Scanner sc = new Scanner(System.in);
        while(true){
            String line = sc.nextLine();
            File file = new File(line);
            if(!file.exists()){
                System.out.println("文件路径不存在!请重新输入文件路径:");
            }else if(file.isDirectory()){
                System.out.println("您输入的是文件夹,请重新输入文件路径:");
            }else{
                return file;
            }
        }
    }

}

20.18_IO流(录入数据拷贝到文件)

  • 将键盘录入的数据拷贝到当前项目下的text.txt文件中,键盘录入数据当遇到quit时就退出
public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        FileOutputStream fos = new FileOutputStream("text.txt");
        System.out.println("请输入数据:");

        while(true){
            String line = sc.nextLine();
            if("quit".equals(line)){
                break;
            }else{
                fos.write(line.getBytes());
                fos.write("\r\n".getBytes());
            }
        }
        fos.close();
    }
    fos.close();

20.19_day20总结

  • 把今天的知识点总结一遍。
时间: 2024-11-05 23:31:20

字节流-FileInputStream_FileOutputStream_BufferedInputStream_BufferedOutputStream的相关文章

深入理解JAVA I/O系列二:字节流详解

流的概念 JAVA程序通过流来完成输入/输出.流是生产或消费信息的抽象,流通过JAVA的输入输出与物理设备链接,尽管与它们链接的物理设备不尽相同,所有流的行为具有相同的方式.这样就意味一个输入流能够抽象多种不同类型的输入:从磁盘文件.从键盘或从网络套接字:同样,一个输出流可以输出到控制台.磁盘文件或相连的网络. 在我们平时接触的输入/输出流中,有这样一个概念必须要弄明白,何谓输入.何谓输出?讨论这个问题的前提是要知道以什么为参考物,这个参考物就是程序或者内存.输入:就是从磁盘文件或者网络等外部的

字节流

FileInputStream 构造方法 public FileInputStream(String filePathName) public FileInputStream(File file) 成员方法 public int read() ; 一次读取一个字节 public int read(byte[] bytes) ; 字节数组拷贝之available()方法 案例演示 int read(byte[] b):一次读取一个字节数组 write(byte[] b):一次写出一个字节数组 av

java之IO输出字节流相关操作

输出字节流: --------| OutputStream 是所有输出字节流 的父类. 抽象类 -----------| FileOutStream 向文件输出数据的输出字节流. FileOutputStream如何使用呢? 1. 找到目标文件 2. 建立数据的输出通道. 3. 把数据转换成字节数组写出. 4. 关闭资源 方法一: import java.io.File; import java.io.FileOutputStream; import java.io.IOException; p

JAVA IO ( 字节流输入输出 )

<!--字节流 写 --> public class WriterDemo { public static void main(String[] args) { //实例化文件对象,文件不存在会自动创建,目录不存在会报错 File file = new File("src/文件字节流输入输出/text.txt"); try { //实例化文件流对象(参数:文件对象,是否追加,true向文件追加数据,false覆盖数据) FileOutputStream outputStre

java IO的字节流和字符流及其区别

1. 字节流和字符流的概念    1.1 字节流继承于InputStream    OutputStream,    1.2 字符流继承于InputStreamReader    OutputStreamWriter.在java.io包中还有许多其他的流,主要是为了提高性能和使用方便. 2. 字节流与字符流的区别    2.1 要把一片二进制数据数据逐一输出到某个设备中,或者从某个设备中逐一读取一片二进制数据,不管输入输出设备是什么,我们要用统一的方式来完成这些操作,用一种抽象的方式进行描述,这

java-HttpGetPost-图片字节流上传

在java程序开发中经常用到与服务端的交互工作,主要的就是传递相应的参数请求从而获取到对应的结果加以处理 可以使用Get请求与Post请求,注意!这里的Get请求不是通过浏览器界面而是在程序代码中设置的,达到Get请求的目的,具体请详见下列描述 以下get与post请求需要引入的包: import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; import org.apache.commo

IO流(字节流)

一.File类的构造方法: File(String pathname) 指定文件或者文件夹的路径创建一个File文件. File(File parent, String child)   根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例. File(String parent, String child) 注意:在windows机器上 的目录分隔符是 \  ,在linux机器上的目录分隔符是/ . .   当前路径 .. 上一级路径 字节流: 字节流读取得都是

Java学习之IO字节流

字节流分为FileInputStream 和FileOutputStream 1 package com.io; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.IOException; 7 import java.io.InputStream; 8 /** 9 * 文件字节流的读取 10 * @author ga

IO(Input Output)流___字符流、字节流

一.IO流简述------用于操作数据的 IO流用来处理设备之间的数据传输; Java对数据的操作是通过流的方式; Java用于操作流的对象都是在IO包中; 流按操作数据分为: 字节流(通用)和字符流: 按流向分为: 输入流和输出流. 字节流的抽象基类: InputStream , OutputStream 字符流的抽象基类: Reader, Writer 注: 由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀. 如: InputStream的子类FileInputStream :Re