学习笔记——IO流

IO流

IO流主要分为字节流和字符流,流动方式分为输入和输出。

  1. 输入流中主要就是学习 读取的方法 read

  2. 输出流中主要就是学习 写出的方法 write

字节流

字节输入流 FileInputStream

  1. FileInputStream(File file) 表示从 file 指向的文件中读取

  2. FileInputStream(String name) name 表示文件的路径名(路径+文件名)

使用方式:

  1. int read()

    调用一次读到一个数据字节,返回的 int 值就是读到的数据

    如果已到达文件末尾,则返回 -1。

  2. int read(byte[] b)

    调用一次本方法表示可以读取多个数据

    读到的内容保存传入的 byte 数组 b 中

    返回的是本次调用方法读到的数据字节个数

    思考? b 数组是有长度,干嘛还要单独返回读到的个数呢?

    b数组是表示声明的用来存储读取的字节数据,但是实际并不一定能装满数组,所以返回的int表示一次读取实例存储的字节个数。

    比如流中一共1028个字节,定义的b组容量为1024,那你就得读两次,但是第二次只读了4个字节,所以实例返回的int就是4。

  3. int read(byte[] b, int off, int len)

    和上面的第二个类似,可以指定从 b 数组什么位置开始装

public static void main(String[] args) throws IOException {
   FileInputStream fis = new FileInputStream(new File("a.txt"));
   byte[] arr = new byte[10];
   int len;
   while ((len = fis.read(arr)) != -1) {
       System.out.println(new String(arr,0,len));
  }
   fis.close();
}

乱码怎么产生的:

  1. 编码和解码规则不一致

  2. 本身这个字符编码不支持某种语言(中文)

  3. read()无参默认读取一个字节,英文下字符是一个字节,不会乱码,但utf-8下中文 4个

  4. 读到半个中文字节,数据不完整,转成char就显示不了,乱码了。

  5. 字节流不太适合读文本。

字节输出流 FileOutputStream

通过输出流来把数据写入到文件中,实现将代码中的数据保存到记事本文件中。

new FileOutputStream("my.txt") 和 new FileOutputStream("my.txt",true) 区别是替换文本内容还是在后面添加内容。

注意: FileOutputStream 会自动创建一个文件(如果文件不存在,并且文件的路径存在的)

public static void main(String[] args) throws Exception{
   FileOutputStream fos = new FileOutputStream("my.txt",true);
   fos.write("空我".getBytes());
   fos.close();
}

文件复制:

public static void main(String[] args) throws IOException {
   FileInputStream fis = new FileInputStream("aa.jpg");
   FileOutputStream fos = new FileOutputStream(new File("aaq.jpg"));
   byte[] arr = new byte[10];
   int len;
   while ((len = fis.read(arr)) != -1) {
       fos.write(arr, 0, len);
  }
   fos.close();
   fis.close();
}

应用:文件加密;网络资源下载;文件转编码;音频拼接……

文件复制等流程:读流,并将读出来的数据写入新的文本中,应该弄一的输出流,一个输入流,输出流read()遍历读流,在循环中调用输入流write()写流。

字符流

使用字节流来操作中文的时候非常不方便,容易产生乱码,它不管你是哪种编码方式都按照一个字符一 个字符的方式读取数据。

字符流主要用来操作文本文件。可以复制文本,不能复制图片

文件输入流 FileReader

FileReader的构造方法和方法与字节流输入流 FileInputStream 非常类似,差别就是单位是 char。

public static void main(String[] args) throws IOException {
   FileReader fr = new FileReader("a.txt");
   char[] arr = new char[1024*10];
   int len ;
   while ((len= fr.read(arr))!=-1){
       System.out.println(new String(arr,0,len));
  }
   fr.close();
}

文件输出流 FileWriter

特有的方法: 可以直接写字符串

注意要关闭流,不然可能会写不进去。

字节流和字符流的区别

  1. 操作的单位不一样,一个是字节,一个是字符

  2. 操作中文的时候使用字符流更方便, 字节流更广泛:文本,视频,音频,图片...

  3. 字符流中有可以直接写字符串的方法

  4. 字节输出流 : 程序 ---> 磁盘文件 如果不关闭流也会写入

    字符输出流 : 程序 ---> 缓冲 ---> 磁盘文件 如果不关闭流或者刷新缓冲区,不会写入文件

    字符输出流,关闭的时候会先刷新,关闭之后不能够在操作,刷新之后可以继续操作

什么时候会用到刷新 : 写入的数据,比较多,可以在中途手动调用刷新的方法提交数据

转换流

如实现一个方法内部的代码,但是方法的结构式写好了的,如果我们需要覆写方法内部需要处理文本, 那么覆写的方法,方法参数改不了。所以可以在覆写的时候方法体将字节流参数,转换成字符流使用。

网络中传输基本都是字节流,如果传输的是文本,用字节操作不太方便,这个时候可以用转换流转成字符流来操作文本。

字节流转字符流 InputStreamReader

FileInputStream fis = new FileInputStream("a.txt");
InputStreamReader isr = new InputStreamReader(fis);

字符流转字节流 OutputStreamWriter

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a21a.txt"));
osw.write("kkk");
osw.close();

将字符"kkk"存在字节流a21a.txt里面

字符流一定要关流,不然文字不会写入进去

缓冲流

之前循环独写数据,操作磁盘的次数非常多,影响性能,通过缓冲流,可以先缓存大量读写数据,等到比较多了之后,在连接磁盘一次从磁盘读取或者写。避免多次连接磁盘影响性能。

其实用起来的话,跟上面的差不多,性能会相对更好。

public static void main(String[] args) throws Exception {
   long start = System.currentTimeMillis();
   BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.png"));
   BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("aa.png"));
   int len;
   byte[] arr = new byte[1024 * 10];
   while ((len = bis.read(arr))!=-1){
//       System.out.println(new String(arr,0,len));
       bos.write(arr,0,len);
  }
   bos.close();
   bis.close();
   long end = System.currentTimeMillis();
   System.out.println(end-start);
}
public static void main(String[] args) throws Exception {
   BufferedReader br = new BufferedReader(new FileReader("a.txt"));
   BufferedWriter bw = new BufferedWriter(new FileWriter("aa.txt"));
   String s;
   while ((s = br.readLine()) != null) {
       bw.write(s);
       bw.newLine();
  }
   bw.close();
   br.close();
}

为了防止程序运行中产生异常而导致流没有关闭,不对异常进行处理随意抛出是不合理的,所以应该对异常进行捕获,将对流的关闭操作放在finally中,确保流每次都会关闭。

对于java7新方式:自动关闭的流资源,必须是实现了AutoCloseable

小结

  1. IO 流操作一般都应该关闭;

  2. 就算读写过程中产生了异常,最后也应该关闭,所有关闭流资源的代码一般放在 finally 结构中

  3. Java7 新结构支持自动关闭,但是 try 的()中创建流的对象的流必须是支持自动关闭的(不过一般我

们用到的 IO 流都是有实现此接口的,以防万一,最好看一下Api文档)

 

 

posted @ 2021-12-20 20:22  Black空我  阅读(43)  评论(0)    收藏  举报