IO流(二)字节流

来源:互联网 发布:如何评价网络架构 编辑:程序博客网 时间:2024/05/19 15:39

##1. 概念

1.IO流的概述

1.  IO流用来处理设备之间的数据传输  2.  Java对数据的操作是通过流的方式3.  Java用于操作流的类都在IO包中4.  流按流向分为两种:输入流,输出流。5.  流按操作类型分为两种: 字节流  字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的 字符流  符流只能操作纯字符数据,比较方便(也就是说只能操作文本文件)。

2. IO流常用父类

1.字节流的抽象父类:InputStream   OutputStream2.字符流的抽象父类:Reader Writer        

3. IO程序书写

使用前,导入IO包中的类,使用时,进行IO异常处理,使用后,释放资源

2. FileInputStream和FileOutputStream


FileInputStream fis = new FileInputStream("aaa.txt"); //创建一个文件输入流对象,并关联aaa.txt
int b; //定义变量,记录每次读到的字节
while((b = fis.read()) != -1) { //将每次读到的字节赋值给b并判断是否是-1
System.out.println(b); //打印每一个字节
}
fis.close();

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();

read()方法返回值为什么是int,而不是byte?

注意: java项目中一般文件是以补码的方式存储(提高开发效率)

因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte,有可能在读到中间的时候遇到111111111
那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收,如果11111111会在其前面补上
24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型

3. 复制文件的演变历程

a. 读一个字节写一个字节(慢的不行了)

    FileInputStream fis = new FileInputStream("文件名");       //创建输入流对象,文件                   FileOutputStream fos = new FileOutputStream("复制文件名");    //创建输出流对象,关联copy.mp3        int b;        while((b = fis.read()) != -1) {            fos.write(b);        }        fis.close();        fos.close();

b. 全部读取文件再复制(但在实际开发中,容易内存溢出)

FileInputStream fis = new FileInputStream("文件名");        FileOutputStream fos = new FileOutputStream("复制文件名");        byte[] arr = new byte[fis.available()];             //根据文件大小做一个字节数组        fis.read(arr);                                                  //将文件上的所有字节读取到数组中        //将数组中的所有字节一次写到了文件上        fis.close();        fos.close();

c. 自定义缓冲区
字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,就像把一堆皮球搬到另一个地方,装在框里运一筐筐的运比一个一个的运明显要快。

FileInputStream fis = new FileInputStream("文件名");        FileOutputStream fos = new FileOutputStream("复制文件名");        int len;        byte[] arr = new byte[1024 * 8];        //自定义字节数组        while((len = fis.read(arr)) != -1) {            //fos.write(arr);            fos.write(arr, 0, len);                                     //写出字节数组写出有效个字节个数        }        fis.close();        fos.close();

d. BufferedInputStream 和FileOutputStream ‘

底层用的装饰模式,也就像是一个程序媛,化了妆,但她还是她,所以关闭文件流。直接关闭BufferedInputStream和FileOutputStream 对象就可以。默认大小8192,自己定义的缓冲数组如果是8192个字节大小和Buffered比较的话定义小数组会略胜一筹,因为读和写操作的是同一个数组而Buffered操作的是两个数组

                //创建文件输入流对象        FileInputStream fis = new FileInputStream("文件名");                       //创建缓冲区对fis装饰        FileOutputStream fos = new FileOutputStream("复制文件名");                     //创建输出流对象        BufferedOutputStream bos = new BufferedOutputStream(fos);                  //创建缓冲区        int b;        while((b = bis.read()) != -1) {                 bos.write(b);        }        bis.close();                                //只关装饰后的对象即可        bos.close();

e. flush和close方法的区别

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

4. IO流(字节流读写中文)

  • 字节流读取中文的问题
    • 字节流在读中文的时候有可能会读到半个中文,造成乱码
  • 字节流写出中文的问题
    • 字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组
    • 写出回车换行 write(“\r\n”.getBytes());
原创粉丝点击