java基础复习(十八)

IO流

数据传输

IO流概念及其分类

1.概念

  • IO流用于处理设备之间的数据传输
  • Java对数据的操作是通过流的方式
  • Java用于操作流的类都在IO包中
  • 流按流向分为两种:输入流、输出流
  • 流按操作类型分为两种:

    • 字节流:字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的。
    • 字符流:字符流只能操作纯字符数据,比较方便。

IO流常用父类

  • 字节流的抽象父类

    • InputStream
    • OutputStream
  • 字符流的抽象父类

    • Reader
    • Writer

IO程序书写

  • 使用前,导入IO包中的类
  • 使用时,进行IO异常处理【硬盘和内存之间的关系,硬盘往内存读,或者内存往硬盘里面写】
  • 使用后,释放资源【内存和硬盘之间的管道】

IO流

FileInputStream

File file = new FileInputStream("xxx.txt");//此处会异常 方法中抛出异常 FileNotFound
int x = file.read();//有可能异常,因为可能不可读  从硬盘上读取一个字节 
System.out.println(x);
int y =file.read();//读取第二个字节
System.out.println(y);
file.close();//关闭流

//97 a以97的形式存取 ASCII 码表 GBK码表
// 文件结束的标记是 -1 只要不是-1就可以循环的读
FileInputStream fis = new FileInputStream("xxx.txt");
int b;
while((b = fis.read()) != -1){//读完整个文件
    System.out.println(b);
}

为什么读的时候返回int而不是返回byte 字节

原因:

10000001 byte类型-1的原码

11111110 -1的反码

11111111 -1的补码

很可能就提前结束了

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

FileOutputStream

FileOutputStream fos = new FileOutpuStream("yyy.txt");//创建字节输出流对象,如果没有就自动创建一个
fos.write(97);//虽然写出的是一个int数,但是到文件上的是一个字节,自动会转换成字符
fos.write(98);
fos.write(99);
//文件关闭
fos.close();

FileOutputStream的追加

FileOutputStream fos = new FileOutpuStream("yyy.txt");
fos.write(100); //d 原有内容都不见了,只剩下d了
//FileOutputStream 在创建对象的时候,如果没有这个文件会帮我们创建出来。如果有这个文件,会先将文件清空【不是删除】,然后再创建。构造方法之中有不同的,想要追加有追加的方法。
//
fos.close();
FileOutputStream fos =  new FileOutputStream("yyy.txt",true);//如果想续写,就在第二个参数传true;

IO流拷贝图片

FileInputStream fis = new FileInputStream("1.jpg");
FileOutpuStream fos = new FileOutputStream("copy.jpg");

int b;
while((b = fis.read()) != -1){
    fos.write(b);//逐个字节去拷贝
}

fis.close();
fos.close();

逐个字节去拷贝非常的慢

读写次数过多

效率太低

原理:

1555634306138

一次将所有的字节拷贝过来的方法

FileInputStream fis = new FileInputStream("xxx.mp3");
FileOutputStream fos = new FileOutputStream("yyy.my3");
byte[] arr = new byte[fis.available()];

fis.read(arr);//将文件上的字符读入到数组中
fos.write(arr);//将字节数组中的字节数据写到文件中

fis.close();
fos.close();

//开发中是否推荐使用这种方式呢?不推荐
//如果加载到一个虚拟机的内存中,10个g的文件,虚拟机内存就溢出了。

Array_copy

第三种拷贝

定义小数组

FileInputStream fis = new FileInputStream("xx.txt");
FileOutpustStream fos = new FileOutputStream("yy.txt");

byte[] arr = new byte[2];
int len;
while(( len = fis.read(arr)) != -1){
    //fos.write(arr);
    fos.write(arr,0,len);
}
fis.close();
fos.close();

//字节数组会存在部分数据余留,写入的时候会重复
//write();

定义小数组的标准格式

FileInputStream fis = new FileInputStream("xx.txt");
FileOutpustStream fos = new FileOutputStream("yy.txt");

byte[] arr = new byte[1024 * 8];//1024的整数倍
int len;
while(( len = fis.read(arr)) != -1){
    //fos.write(arr);
    fos.write(arr,0,len);
}
fis.close();
fos.close();

带Buffer的拷贝

FileInputStream fis = new FileInputStream("1.mp3");//创建输入流对象,关联1.mp3
FIleOutputStream fos = new FileOutputStream("copy.mp3");//创建输出流对象,关联copy.mp3

BufferedInputStream bis = new BufferedInputStream(fis);//创建缓冲区对象,对输入流进行包装,让其变得更加强大
BufferedOutputStream bos = new BufferedOutputStream(fos);

int b ;
while((b = bis.read()) !=-1){
    bos.write(b);
}
bis.close();
bos.close();
//只需要关闭包装后的流

1555636862863

效率很高

A:缓冲区思想

  • 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多
  • 这是加入了数组这样的缓冲区效果,java本身在设计的时候
  • 也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流

B:BufferedInputStream

  • BufferedInputStream内置了一个缓冲区(数组)
  • 从BufferedInputStream中读取一个字节的时
  • BufferedInputStream会一次性从文件中读取8192个,存在缓冲区中,返回给程序一个
  • 程序再次读取时,就不用找文件了,直接从缓冲区中获取
  • 直到缓冲区中所有的都被使用过,才重新从文件中读取8192个

C:BufferedOutputStream

  • BufferedOutputStream也内置了一个缓冲区(数组)
  • 程序向流中写出字节是,不会 直接写到文件,先写到缓冲区中
  • 直到缓冲区写满,BufferedOutputStream才会把缓冲区中的数据一次性写到文件里

小数组的读写和带Buffered的读取哪个更快

两种方式都行,相对而言自己定义的小数组会快一点,不过使用别人定义好了的更简单。

flush和close方法的区别

flush刷新缓冲区的

close关闭流的

具备刷新的功能,在关闭流之前,就会先刷新一次缓冲区,将缓冲区的字节全都刷新到文件上,再关闭。

flush方法?刷新缓冲区,不会关闭流,还可以继续写。

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("1.mp3"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp3"));

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

字节流读写中文的问题

FileInputStream fis = new FileInputStream("aaa.txt");
byte[] arr = new byte[2];
int len;
while((len = fis.read(arr)) != -1){
    System.out.println(new String(arr,0,len));//读取
}
fis.close();

//字节流去读取中文是可能会出现问题的,很可能会乱码

字节流写出中文

FileOutputStream fos = new FileOutputStream("zzz.txt");
fos.write("我读书少,你别骗我".getBytes());//转换成字节数组
fos.write("/r/n".getBytes());//写出回车换行
fos.close();

IO流的标准异常处理

直接抛出IOException是不太负责的,可能会导致之后流关闭不了。

//在关闭之前就异常抛出了

//使用finally最后来处理

jdk1.6之前

FileInputStream fis = null;
FileOutputStream fos = null;
try{
FileInputStream fis = new FileInputStream("xxx.txt");
FileOutputStream fos = new FileOutputStream("yyy.txt");
int b;
while((b = fis.read()) != -1){
    fos.write(b);
}
}finally{
    try{
    if(fis != null){
    fis.close();
    }
    }finally{
    if(fis != null){
    fos.close();
    }
    }
    //try finally的嵌套目的是能关一个才关一个 面试的时候会用到
}

jdk1.7之后

try{
FileInputStream fis = new FileInputStream("xxx.txt");
FileOutputStream fos = new FileOutputStream("yyy.txt");
}
{
int b;
while((b = fis.read()) != -1){
    fos.write(b);
}
}
//fis.close();
//fos.close();

JDK里面有 AutoClosed 自动关闭功能

IO流图片加密

BufferedInputStream bis = new BufferedInputStream("new FileInputStream("1.jpg"));
BufferedOutputStream bos = new BufferedOutputStream("new FileOutputStream("c.jpg""));

int b;
while((b = bis.read()) != -1){
    bos.write(b^123);//一个数异或另一个数两次,是原样, 123是密钥 
}//解密的时候读这个文件,再进行一次异或就可以了。
bis.close();
bis.close();

拷贝文件

在控制台录入文件的路径,将文件拷贝到当前项目下

分析:

1.创建键盘录入对象

2.定义方法,对键盘录入的路径进行判断,如果是文件就返回

3.在主方法中接收该文件

4.读和写该文件

将键盘录入数据拷贝到文件中

1.创建键盘录入对象

2.创建输入流对象,关联text.txt文件

3.定义无限循环

4.遇到quit退出循环

5.如果不quit,就将内容写出

本文链接:

https://heyzen.club/index.php/J/262.html
1 + 5 =
快来做第一个评论的人吧~