OutputStram/InputStream 字节流

OutputStream:字节输出流

  • 结构图


FileOutputStream 文件字节输出流

构造方法

FileOutputStream提供4个常用的构造方法,其实底层只有一个。

构造方法描述
FileOutputStream​(File file)使用File对象打开本地文件,并创建对象且使对象指向该文件。
FileOutputStream​(String name)根据传入路径打开本地文件,并创建对象且使对象指向该文件。该构造方法的源代码,其内部使用了File对象打开文件
FileOutputStream​(File file, boolean append)打开文件,并使对象指向该文。件第二个参数决定字节写入文件末尾而还是开头【追加写入】
FileOutputStream​(String name, boolean append)同上
public class Demo{
    public static void main(String[] args) throws FileNotFoundException {
        File f = new File("e:\\360sd\\1.txt");
        FileOutputStream fos = new FileOutputStream(f,true);
    }
}

注意:创建FileOutputStream对象,会打开File对象封装路径指向的文件,并让创建好的对象指向该文件。如果找不到路径或者指向的不是文件将抛出文件不存在异常。

写数据方法

写入方法描述
void write​(int b)将指定的字节写入此文件输出流
void write​(byte[] b)将指定字节数组中的字节写入此文件输出流
void write​(byte[] b, int off, int len)将字节数组中,指定下标和指定长度的字节写入此文件输出流
  • 写入一个字节的数据 write​(int b)

    public class Demo{
        public static void main(String[] args) throws IOException {
            File f = new File("e:\\360sd\\1.txt");
            FileOutputStream fos = new FileOutputStream(f,true);
            fos.write(97);
        }
    }
    ---*---
    输出结果:
    e:\\360sd\\1.txt 文件中写入了 97 通过文本文档查看显示 a
    

    注意:读写数据都会抛出IOException。(读写异常)

  • 写入一个byte数组的数据 write​(byte[ ] b)

    public class Demo{
        public static void main(String[] args) throws IOException {
            File f = new File("e:\\360sd\\1.txt");
            FileOutputStream fos = new FileOutputStream(f,true);
            byte[] byt = {97,98,99,100};
            fos.write(byt);
        }
    }
    ---*---
    输出结果:
    e:\\360sd\\1.txt 文件中写入了 97 98 99 100 通过文本文档查看显示 abcd
    
  • 字符串转byte数组 (补充)

    public class Demo{
        public static void main(String[] args) throws IOException {
            File f = new File("e:\\360sd\\1.txt");
            FileOutputStream fos = new FileOutputStream(f,true);
            byte[] byt = "中国四川".getBytes();
            fos.write(byt);
        }
    }
    ---*---
    输出结果:
    e:\\360sd\\1.txt 文件中写入了 中国四川转换的字节数组 通过文本文档查看显示 中国四川
    
  • 写入byte数组指定位置的指定长度的字节 write​(byte[] b, int off, int len)

    public class Demo{
        public static void main(String[] args) throws IOException {
            File f = new File("e:\\360sd\\1.txt");
            FileOutputStream fos = new FileOutputStream(f,true);
            byte[] byt = {97,98,99,100,101};
            fos.write(byt,1,3);
        }
    }
    ---*---
    输出结果:
    e:\\360sd\\1.txt 文件中写入了 98 99 100 通过文本文档查看显示
    

    将 3 个字节的数据,并从数组byt的 1 位置开始写入到输出流

  • 写入数据换行 \r\n

    public class Demo{
        public static void main(String[] args) throws IOException {
            File f2 = new File("e:\\360sd\\1.txt");
            FileOutputStream fos = new FileOutputStream(f2,true);
            byte[] bs = "\r\n".getBytes();
            fos.write(97);
            fos.write(bs);
            fos.write(98);
            fos.close();
        }
    }
    ---*---
    输出结果:
    a
    b
    

关闭流

关闭方法描述
void close()关闭此文件输出流并释放与此流关联的所有系统资源

复制文件/图片/视频

  • 复制文件 基础版

    public class Demo{
        public static void main(String[] args) throws IOException {
            File f1 = new File("e:\\360sd\\1.txt");
            File f2 = new File("e:\\360sd\\2.txt");
            //创建新文件
            f2.createNewFile();
            //创建IO对象打开文件,指向文件
            FileInputStream fis = new FileInputStream(f1);
            FileOutputStream fos = new FileOutputStream(f2);
            //暂存变量
            int a;
            while ((a=fis.read())!=-1){//读一个字符,不为 -1 代表还有数据
                fos.write(a);//写一个字符
            }
            //查看复制的内容
            FileInputStream fis1 = new FileInputStream(f2);
            System.out.print("复制的内容是:");
            while ((a=fis1.read())!=-1){
                System.out.print((char) a);//为了和文本文档中看到的一样强转为char
            }
        }
    }
    ---*---
    输出结果:
    复制的内容是:ABCD
    e:\\360sd\\1.txt 文件通过文本文档查看显示 ABCD
    e:\\360sd\\2.txt 文件中写入了 65 66 67 68 通过文本文档查看显示 ABCD
    
  • 复制文件 升级版

    public class Demo{
        public static void main(String[] args) throws IOException {
            File f1 = new File("e:\\360sd\\1.txt");
            File f2 = new File("e:\\360sd\\2.txt");
            //创建新文件
            f2.createNewFile();
            //复制文件
            copyFile(f1,f2);
            //查看复制的文件内容
            FileInputStream fis = new FileInputStream(f2);
            byte[] bs = new byte[1024];
            while ((fis.read(bs))!=-1){
    		System.out.println("复制的内容是:"+new String(bs));
    		}
        }
        public static void copyFile(File a,File b){
            if (!a.exists()) {
                System.out.println("源文件不存在!");
                return;
            }
            try {
                FileInputStream fis = new FileInputStream(a);
                FileOutputStream fos = new FileOutputStream(b);
                //读写用的中转byte数组
                byte[] bs = new byte[1024];
                //读数据
                while (fis.read(bs)!=-1){
                	 //写数据
    				fos.write(bs);
    			}
                //刷新缓冲区
                fos.flush();
                //关闭文件
                fis.close();
                fos.close();
                System.out.println("复制完成!");
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    ---*---
    输出结果:
    复制完成!
    复制的内容是:ABCD
    
  • 复制图片

    public class Oop{
        public static void main(String[] args) throws IOException {
            File f1 = new File("e:\\360sd\\新建文件夹1\\图片.jpg");
            File f2 = new File("e:\\360sd\\新建文件夹2\\图片(拷贝).jpg");
            //打开文件,创建输入输出流对象指向文件
            FileInputStream fis = new FileInputStream(f1);
            FileOutputStream fos = new FileOutputStream(f2);
            //通过读写复制
            byte[] bs = new byte[1024];
            int len;
            while((len=fis.read(bs))!=-1){
                fos.write(bs,0,len);
            }
            //关闭文件
            fis.close();
            fos.close();
        }
    }
    ---*---
    输出结果:
    在f2对象封装的路径下复制了一个 图片(拷贝).jpg 文件
    

    注意:此程序可以复制任意格式文件,就不演示视频文件复制了。

io异常处理

进行io操作会调用系统资源,所以我们处理异常时要保证占用的资源一定被释放掉。

  • try…catch…finally

    public class Demo {
        public static void main(String[] args) {
        	//变量定义在try外,否则finally块看不到
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;
            try {
                bis = new BufferedInputStream(new FileInputStream("e:\\360sd\\视频.mp4"));
                bos = new BufferedOutputStream(new FileOutputStream("e:\\360sd\\视频1.mp4"));
                byte[] bs = new byte[1024];
                int len;
                while ((len = bis.read(bs)) != -1) {
                    bos.write(bs);
                }
            }catch(IOException e){
                e.printStackTrace();
            }finally {
                //对象不为null,就关闭流
                if (bis!=null) {
                    try {
                        bis.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
                if (bos!=null){
                    try {
                        bos.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    ---*---
    //这是处理io流保证资源是否的标准格式
    
  • JDK7改进方案:在try后的括号定义流对象

    public class Demo {
        public static void main(String[] args) {
            try(	//将流对象定义在此括号中
                    BufferedInputStream bis = 
                            new BufferedInputStream(new FileInputStream("e:\\360sd\\视频.mp4"));
                    BufferedOutputStream bos = 
                            new BufferedOutputStream(new FileOutputStream("e:\\360sd\\视频1.mp4"));
                    ) {
                byte[] bs = new byte[1024];
                int len;
                while ((len = bis.read(bs)) != -1) {
                    bos.write(bs);
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
    ---*---
    /*
    将流对象定义在try后的()中,省去了finally块。
    程序更简洁,推荐使用。
    */
    
  • JDK9改进方案

    public class HelloWorld {
        public static void main(String[] args) throws IOException {
    
            BufferedInputStream bis =
                    new BufferedInputStream(new FileInputStream("e:\\360sd\\视频.mp4"));
            BufferedOutputStream bos =
                    new BufferedOutputStream(new FileOutputStream("e:\\360sd\\视频1.mp4"));
            try(bis;bos) {
                byte[] bs = new byte[1024];
                int len;
                while ((len = bis.read(bs)) != -1) {
                    bos.write(bs);
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
    ---*---
    /*
    在JDK7基础上改进,仅将流对象放在try后的()中,
    创建流对象的异常依然需要方法来处理。
    */
    

BufferedOutputStream 字节缓冲输出流

该类为字节输出流提供一个可设置大小的缓冲区,先将数据写入缓冲区,之后再一次写入目标文件。注意:真正的写数据还是字节输出流,该类仅提供一个缓冲区。

  • 构造方法

    构造方法描述
    BufferedOutputStream​(OutputStream out)为传入的字节输出流提供一个缓冲区以提高效率
    BufferedOutputStream​(OutputStream out, int size)为传入的字节输出流提供一个缓冲区以提高效率,并可设置缓冲区大小
    public class Demo {
        public static void main(String[] args) throws IOException {
            //创建字节缓冲输出流
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("h:\\360sd\\1.txt"));
            //写入一个byte数组数据
            bos.write("ABC".getBytes());
            bos.write("DEF".getBytes());
            //关闭资源
            bos.close();
        }
    }
    ---*---
    输出结果:
    		//h:\\360sd\\1.txt 文件中写入了ABCDEF
    

    注意:缓冲输出流的使用和字节输出流相同

  • 使用字节流和缓冲字节流耗时对比

    public class Demo {
        public static void main(String[] args) throws IOException {
            long l1 = System.currentTimeMillis();
    //        method1();    //耗时87978毫秒
    //        method2();    //耗时131毫秒
    //        method3();    //耗时365毫秒
            method4();    //耗时37毫秒
            long l2 = System.currentTimeMillis();
            System.out.println("耗时"+(l2-l1)+"毫秒");
        }
        //一次读写一个 字节数据
        public static void method1() throws IOException {
            FileInputStream fis = new FileInputStream("h:\\360sd\\视频.mp4");
            FileOutputStream fos = new FileOutputStream("h:\\360sd\\视频(拷贝).mp4");
            int by;
            while ((by=fis.read())!=-1){
                fos.write(by);
            }
            fis.close();
            fos.close();
        }
        //一次读写一个 字节数组数据
        public static void method2() throws IOException {
            FileInputStream fis = new FileInputStream("h:\\360sd\\视频.mp4");
            FileOutputStream fos = new FileOutputStream("h:\\360sd\\视频(拷贝).mp4");
            byte[] bs = new byte[1020];
            int len;
            while ((len=fis.read(bs))!=-1){
                fos.write(bs,0,len);
            }
            fis.close();
            fos.close();
        }
        //字节缓冲流 一次读写一个字节数据
        public static void method3() throws IOException {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("h:\\360sd\\视频.mp4"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("h:\\360sd\\视频(拷贝).mp4"));
            int by;
            while ((by=bis.read())!=-1){
                bos.write(by);
            }
            bis.close();
            bos.close();
        }
        //字节缓冲流 一次读写一个字节数组数据
        public static void method4() throws IOException {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("h:\\360sd\\视频.mp4"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("h:\\360sd\\视频(拷贝).mp4"));
            byte[] bs = new byte[1024];
            int len;
            while ((len=bis.read(bs))!=-1){
                bos.write(bs,0,len);
            }
            bis.close();
            bos.close();
        }
    }
    ---*---
    输出结果:
    //        method1();    //耗时87978毫秒
    //        method2();    //耗时131毫秒
    //        method3();    //耗时365毫秒
    //        method4();    //耗时37毫秒
    

    注意:从输出结果可以看出,推荐使用 缓冲字节流+byte数组 形式,不推荐使用单字节读取形式。

InputStream:字节输入流

  • 结构图


FileInputStream 文件字节输入流

构造方法

构造方法描述
FileInputStream​(File file)打开file对象封装路径指向的文件,并创建对象指向该文件
FileInputStream​(String name)打开name路径指向的文件,并创建对象指向该文件
public class Demo {
    public static void main(String[] args) throws IOException {
        File f = new File("h:\\360sd\\1.txt");
        FileInputStream fis = new FileInputStream(f);
    }
}

注意:创建FileOutputStream对象,会打开File对象封装路径指向的文件,并让创建好的对象指向该文件。如果找不到路径或者指向的不是文件将抛出文件不存在异常。

读数据方法

读取方法描述
int read()从此输入流中读取一个字节的数据
int read​(byte[] b)从此输入流中读取一个字节数组的数据,返回真是读取到的字节的个数
int read​(byte[] b, int off, int len)从此输入流读取len个字节数据,从off下标开始存储到字节数组
int available()返回可以从此输入流中读取(或跳过)的剩余字节数的估计值【查看还有多少个字节可以读】
  • 读取一个字节数据 int read()

    public class Demo {
        public static void main(String[] args) throws IOException {
            File f = new File("h:\\360sd\\1.txt");
            FileInputStream fis = new FileInputStream(f);
            //读取一个字节数据
            int a = fis.read();
            System.out.println(a);
            System.out.println((char) a);
        }
    }
    ---*---
    输出结果:
    97
    a
    

    注意:当读取数据时,返回值为 -1 说明没有可读取的字节。

  • 读取一个字节数组的数据 int read​(byte[] b) 返回真实读取到的数据个数

    public class Demo {
        public static void main(String[] args) throws IOException {
            File f = new File("h:\\360sd\\1.txt");
            FileInputStream fis = new FileInputStream(f);
            //创建byte数组,长度为所指文件字节数
            byte[] bs = new byte[fis.available()];//获取当前文件剩余数据数
            //读数据
            fis.read(bs);
            //查看读取的数据
            for (byte b : bs) {
                System.out.print(b+"\t");
                System.out.println((char) b);
            }
        }
    }
    ---*---
    输出结果:
    97	a
    98	b
    99	c
    100	d
    101	e
    102	f
    103	g
    

    注意:available 方法返回当前输入流剩余的字节数,这里直接将byte数组长度设为输入流剩余的字节数,一次读取所有字节到 byte 数组。

  • 补充 String​(byte[] bytes, int off, int len) 将byte数组转位字符串,长度为len,起点为off

    public class Demo {
        public static void main(String[] args) throws IOException {
            File f = new File("h:\\360sd\\1.txt");
            FileInputStream fis = new FileInputStream(f);
            //创建读取数据用的byte数组
            byte[] bs = new byte[5];
            //读取数据到bs数组中,并返回真实读取到的数据个数
            int len = fis.read(bs);
            //通过字节数组转字符串
            while (len!=-1){
                String s = new String(bs,0,len);
                System.out.print(s);
                len = fis.read(bs);
            }
        }
    }
    ---*---
    输出结果:
    abcdefg
    d		
    

    关闭流

关闭方法描述
void close()关闭此文件输入流并释放与此流关联的所有系统资源

复制文件

参考OutputStream

io异常处理

进行io操作会调用系统资源,所以我们处理异常时要保证占用的资源一定被释放掉。

  • try…catch…finally

    public class Demo {
        public static void main(String[] args) {
        	//变量定义在try外,否则finally块看不到
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;
            try {
                bis = new BufferedInputStream(new FileInputStream("e:\\360sd\\视频.mp4"));
                bos = new BufferedOutputStream(new FileOutputStream("e:\\360sd\\视频1.mp4"));
                byte[] bs = new byte[1024];
                int len;
                while ((len = bis.read(bs)) != -1) {
                    bos.write(bs);
                }
            }catch(IOException e){
                e.printStackTrace();
            }finally {
                //对象不为null,就关闭流
                if (bis!=null) {
                    try {
                        bis.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
                if (bos!=null){
                    try {
                        bos.close();
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    ---*---
    //这是处理io流保证资源是否的标准格式
    
  • JDK7改进方案:在try后的括号定义流对象

    public class Demo {
        public static void main(String[] args) {
            try(	//将流对象定义在此括号中
                    BufferedInputStream bis = 
                            new BufferedInputStream(new FileInputStream("e:\\360sd\\视频.mp4"));
                    BufferedOutputStream bos = 
                            new BufferedOutputStream(new FileOutputStream("e:\\360sd\\视频1.mp4"));
                    ) {
                byte[] bs = new byte[1024];
                int len;
                while ((len = bis.read(bs)) != -1) {
                    bos.write(bs);
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
    ---*---
    /*
    将流对象定义在try后的()中,省去了finally块。
    程序更简洁,推荐使用。
    */
    
  • JDK9改进方案

    public class HelloWorld {
        public static void main(String[] args) throws IOException {
    
            BufferedInputStream bis =
                    new BufferedInputStream(new FileInputStream("e:\\360sd\\视频.mp4"));
            BufferedOutputStream bos =
                    new BufferedOutputStream(new FileOutputStream("e:\\360sd\\视频1.mp4"));
            try(bis;bos) {
                byte[] bs = new byte[1024];
                int len;
                while ((len = bis.read(bs)) != -1) {
                    bos.write(bs);
                }
            }catch(IOException e){
                e.printStackTrace();
            }
        }
    }
    ---*---
    /*
    在JDK7基础上改进,仅将流对象放在try后的()中,
    创建流对象的异常依然需要方法来处理。
    */
    

BufferedInputStream 字节缓冲输入流

该类为字节输入流提供一个可设置大小的缓冲区,先将数据读入缓冲区,之后再一次读入内存中。注意:真正的读数据还是字节输入流,该类仅提供一个缓冲区。

  • 构造方法

    构造方法描述
    BufferedInputStream​(InputStream in)为传入的字节输入流提供一个缓冲区以提高效率
    BufferedInputStream​(InputStream in, int size)为传入的字节输入流提供一个缓冲区以提高效率,并可设置缓冲区大小
    public class Demo {
        public static void main(String[] args) throws IOException {
            //创建字节缓冲输入流
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("h:\\360sd\\1.txt"));
            //一次读取一个字节数据
            int by;
            while ((by=bis.read())!=-1){
                System.out.print((char) by);
            }
            //释放资源
            bis.close();
        }
    }
    ---*---
    输出结果:
    abcdefg //h:\\360sd\\1.txt 文件中存有abcdefg
    

    注意:缓冲输入流的使用和字节输入流相同

  • 使用字节流和缓冲字节流耗时对比

    public class Demo {
        public static void main(String[] args) throws IOException {
            long l1 = System.currentTimeMillis();
    //        method1();    //耗时87978毫秒
    //        method2();    //耗时131毫秒
    //        method3();    //耗时365毫秒
            method4();    //耗时37毫秒
            long l2 = System.currentTimeMillis();
            System.out.println("耗时"+(l2-l1)+"毫秒");
        }
        //一次读写一个 字节数据
        public static void method1() throws IOException {
            FileInputStream fis = new FileInputStream("h:\\360sd\\视频.mp4");
            FileOutputStream fos = new FileOutputStream("h:\\360sd\\视频(拷贝).mp4");
            int by;
            while ((by=fis.read())!=-1){
                fos.write(by);
            }
            fis.close();
            fos.close();
        }
        //一次读写一个 字节数组数据
        public static void method2() throws IOException {
            FileInputStream fis = new FileInputStream("h:\\360sd\\视频.mp4");
            FileOutputStream fos = new FileOutputStream("h:\\360sd\\视频(拷贝).mp4");
            byte[] bs = new byte[1020];
            int len;
            while ((len=fis.read(bs))!=-1){
                fos.write(bs,0,len);
            }
            fis.close();
            fos.close();
        }
        //字节缓冲流 一次读写一个字节数据
        public static void method3() throws IOException {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("h:\\360sd\\视频.mp4"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("h:\\360sd\\视频(拷贝).mp4"));
            int by;
            while ((by=bis.read())!=-1){
                bos.write(by);
            }
            bis.close();
            bos.close();
        }
        //字节缓冲流 一次读写一个字节数组数据
        public static void method4() throws IOException {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("h:\\360sd\\视频.mp4"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("h:\\360sd\\视频(拷贝).mp4"));
            byte[] bs = new byte[1024];
            int len;
            while ((len=bis.read(bs))!=-1){
                bos.write(bs,0,len);
            }
            bis.close();
            bos.close();
        }
    }
    ---*---
    输出结果:
    //        method1();    //耗时87978毫秒
    //        method2();    //耗时131毫秒
    //        method3();    //耗时365毫秒
    //        method4();    //耗时37毫秒
    

    注意:从输出结果可以看出,推荐使用 缓冲字节流+byte数组 形式,不推荐使用单字节读取形式。

总结

1.创建字节流对象,必然会调用File类来打开指定路径的文件。

2.字节输出流可以选择是否追加写入。

3.字符/字节缓冲流可以看成字符/字节流的一套装备并可以设置加强的力度(缓冲区大小),带上装备的字符/字节流更加强大。所以推荐使用。

4.字节流可以读写任意文件数据,一般采用字节缓冲流一次读写一个byte数组数据的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值