IO流,一篇简单了解

目录

1.File类

1.1File类概述

1.2 File类中的构造方法

1.3 File类新增功能

1.4 File类的删除和重命名功能

1.5 File类的判断功能

1.6 File类的获取功能

2.IO流介绍

2.1 IO流概述

2.2 IO流的分类和使用步骤

3,字节流

3.1字节输入流

3.2字节输出流

3.3文件的复制

3.4字节高效缓冲流

4.字符流

4.1字节流读取中文乱码问题

4.2字符输入流

4.3字符输出流

4.4flush和close方法的比较

4.5字符流复制纯文本文件

4.6字符流不能复制非纯文本文件

4.7高效缓冲字符流

4.8高效缓冲字符流特有方法

5,转换流

6.IO流的标准异常处理方式(扩展)


1.File类

1.1File类概述

  a : File类,来自于java.io包, 表示一个文件或者文件夹的路径(就表示一个文件或者文件夹)

  b : 路径, 表示文件或者文件夹存在位置的字符串, 举例 :  “D:\\abc.txt”

  1. 绝对路径 : 表示唯一的, 带有根路径的, 没有任何歧义的路径存在, 在windows操作系统中, 绝对路径是带有盘符的路径

                  D:\\1012系统班

  1. 相对路径 : 表示路径存在是相对而言, 不是唯一的, 有一些歧义的

                      a\\123.txt

  c : 在eclipse中, 如果给出的文件是一个相对路径, 那么文件的绝对路径就会拼接当前正在操作的项目工程根目录

 

1.2 File类中的构造方法

    1.File(String path) : 将path所表示的文件或者文件夹路径封装到File类型中

    2.File(String fu, String zi) : 将fu+zi拼接成一个完整路径, 路径封装到File类型中

    3.File(File fu, String zi) : 将File类型的fu + zi拼接成一个完整路径, 路径封装到File类型中

package com.ujiuye.file;
import java.io.File;
public class Demo01_FileConstructor {
	public static void main(String[] args) {
	   String s = "D:\\1012系统班";
       File f = new File(s);
       System.out.println(f);// D:\1012系统班
       
       File f1 = new File(s,"day01");
       System.out.println(f1);// D:\1012系统班\day01
       
       File f2 = new File(f1, "笔记");
       System.out.println(f2);// D:\1012系统班\day01\笔记
	}
}

1.3 File类新增功能

  1. createNewFile() : 当File表示一个文件, 并且文件路径存在, 文件不存在的时候, 此方法新建出一个空的文件, 返回值类型       boolean类型, 创建文件成功返回true

  2. mkdir() : 每次只能创建出File类所表示的最后一级文件夹, 如果最后一级文件夹父路径不存在, 创建失败,返回值类型boolean类    型, 创建成功返回true

  3. mkdirs() : 每次可以创建一级或者多级文件夹路径, 返回值类型boolean类型, 创建成功返回true

 

代码

package com.ujiuye.file;
import java.io.File;
import java.io.IOException;
public class Demo02_FileAddMethod {
	public static void main(String[] args) throws IOException{
		
        File f = new File("D:\\123.txt");
        // createNewFile() : 当File表示的一个文件, 并且文件路径存在, 文件不存在时候, 此方法新建出一个空的文件, 
        // 返回值类型boolean类型, 创建成功返回true
        boolean boo = f.createNewFile();
        System.out.println(boo);
        
        File f1 = new File("D:\\a");
        // 每次只能创建出File类所表示的最后一级文件夹, 如果最后一级文件夹父路径不存在,创建失败,返回值类型boolean类型, 创建成功返回true
        boolean boo1 = f1.mkdir();
        System.out.println(boo1);
        
        File f2 = new File("D:\\create\\file\\day01");
        // mkdirs() : 每次可以创建一级或者多级文件夹路径, 返回值类型boolean类型, 创建成功返回true
        boolean boo2 = f2.mkdirs();
        System.out.println(boo2);
	}
}

1.4 File类的删除和重命名功能

  1. delete() : 删除File所表示文件或者文件夹, 删除成功返回true. 删除失败返回false

  注意 : 如果删除的是文件夹, 要求文件夹是空的才能删除, 这是安全保证; delete方法表示直接删除, 不走回收站

  2.renameTo(File f): 将方法调用者的file所表示的文件进行重命名

    1.参数f的路径与方法调用者路径一致, 只表示修改文件名

    2.参数f的路径与方法调用者路径不一致, 先剪切到目标f路径下, 再重命名

package com.ujiuye.file;
import java.io.File;
public class Demo03_FileDeleteAndRename {
	public static void main(String[] args) {
          File f = new File("D:\\123.txt");
          // 1. 直接删除文件, 如果文件真实存在, 删除成功
          System.out.println(f.delete()); 
          
          File f1 = new File("D:\\a");
          // 2. 直接删除一个空的文件夹, 删除功能
          System.out.println(f1.delete());
          
          File f2 = new File("D:\\create");
          // 3. 删除非空文件夹, 删除失败
          System.out.println(f2.delete());
          
          File f3 = new File("D:\\aa.txt");
          // 4. f3的路径与参数路径一致, 只表示文件重命名
          f3.renameTo(new File("D:\\aabbc.txt"));
          File f4 = new File("D:\\bb.txt");
          // 5. f3的路径与参数路径不一致 , 先将f3表示的文件剪切到目标参数路径下, 再重命名为change.txt
          f4.renameTo(new File("D:\\1012系统班\\change.txt"));
	}
}

1.5 File类的判断功能

  1. exists() : 验证File所表示文件或者文件夹是否真实存在, 如果存在返回true; 否则返回false;

  2. isFile() : 验证File所表示的是否是一个文件, 如果是文件返回true; 否则返回false;

  3. isDirectory() : 验证File所表示的是否是一个文件夹, 如果是文件返回true; 否则返回false;

package com.ujiuye.file;
import java.io.File;
public class Demo04_FileCheckMethod {
	public static void main(String[] args) {
        File  f = new File("D:\\1012系统班\\change.txt");
        //1. exists() : 验证FIle所表示文件或者文件夹是否真实存在, 如果存在返回true; 否则返回false;
        System.out.println(f.exists());// true
        System.out.println(new File("D:\\hello.java").exists());// false
        
        // 2. isFile() : 验证File所表示的是否是一个文件, 如果是文件返回true; 否则返回false;
        System.out.println(f.isFile());
        // 3. isDirectory() : 验证File所表示的是否是一个文件夹, 如果是文件返回true; 否则返回false;
        System.out.println(f.isDirectory());// false
	}
}

1.6 File类的获取功能

    1. getAbsolutePath() : 将File类型所表示的文件或者文件夹的绝对路径以字符串的形式进行返回

    2. getPath() : 将File类型所封装的文件或者文件夹路径以字符串的形式进行返回

    3. getName() : 将File类型所封装的文件或者文件夹路径最后一个部分的名字获取到, 返回String类型名字结果

    4. length() : 表示获取File所表示的文件的长度(文件的大小), 以字节为丈量粒度, 返回值类型long类型(注意 : 不能丈量文件夹的        大小, 文件夹数据不能保证正确)

    实际场景使用 : 有时, 需要到指定路径下读取文件, 读取文件之前, 需要判断

     File f = new File(“D:\\core.txt”);

      if( f.exists() && f.length() > 0){

         读取文件内容

     }

   5.list() : 将File所表示的文件夹路径下, 所有的子级别(当前文件夹级别下)的文件和文件夹都获取到, 将获取到结果放置到String[]       中

  6.listFiles() : 将File所表示的文件夹路径下, 所有的子级别(当前文件夹级别下)的文件和文件夹都获取到, 将获取到结果放置到            File[]中。

package com.ujiuye.file;
import java.io.File;
import java.util.Arrays;
public class Demo05_FileGetMethod {
	public static void main(String[] args) {
         File f = new File("D:\\aabbc.txt");
         // 1.getAbsolutePath() : 将File类型所表示的文件或者文件夹的绝对路径以字符串的形式进行返回
         String path = f.getAbsolutePath();
         System.out.println(path);//  D:\aabbc.txt
         
         File f1 = new File("123.txt");
         System.out.println(f1.getAbsolutePath());// D:\workspace\day16\123.txt
         
        // 2.getPath() : 将File类型所封装的文件或者文件夹路径以字符串的形式进行返回
         System.out.println(f.getPath()); // D:\aabbc.txt
         System.out.println(f1.getPath());// 123.txt
         
         // 3.getName() : 将File类型所封装的文件或者文件夹路径最后一个部分的名字获取到, 返回String类型名字结果
         System.out.println(f.getName());// aabbc.txt
         
         File f2 = new File("D:\\1012系统班\\day01\\笔记");
         System.out.println(f2.getName());//笔记
         
         // 4.length() : 表示获取File所表示的文件的长度(文件的大小), 以字节为丈量粒度
         System.out.println(f.length());// 10
         
         // 5. list() : 将File所表示的文件夹路径下, 所有的子级别(当前文件夹级别下)的文件和文件夹都获取到,
         // 将获取到结果放置到String[]中
         String[] arr = f2.list();
         System.out.println(Arrays.toString(arr));
         
         // 6.listFiles() : 将File所表示的文件夹路径下, 所有的子级别(当前文件夹级别下)的文件和文件夹都获取到,
         // 将获取到结果放置到File[]中
         System.out.println(Arrays.toString(f2.listFiles()));
         
         File f3 = new File("D:\\1012系统班");
         System.out.println(Arrays.toString(f3.list()));
	}
}

list   listFile

public static void main(String []args) {
		File f1 = new File("e:\\a");
		String []str =f1.list();             //list 输出的是当前文件夹下所有文件以及文件夹
		File []f2 = f1.listFiles();          //listFile  输出的是当前文件以及文件夹的File类 
                                             //型,并且是全路径
		for(int index = 0;index < str.length;index++) {
		System.out.println(str[index]);
		System.out.println(f2[index]);
				}
	}

2.IO流介绍

2.1 IO流概述

      1,IO : I是i的大写字母, 表示input, 输入

            O是o的大写字母, 表示output, 输出

     2,IO流的主要作用就是进行数据传输, 不同的设备使用不同的IO流资源进行数据传输

     3,IO的流向:

2.2 IO流的分类和使用步骤

   1, IO流从功能性上分类:

         字节流 : 以字节方式进行文件内容操作(读写)

               输入流 : InputStream

               输出流 : OutputStream

         字符流 : 以字符方式进行文件内容操作(读写)

              输入流 : Reader

              输出流 : Writer

   2,IO流使用的步骤:

        1,使用IO流资源之前, 需要导包, java.io

        2,使用IO流资源同时, 需要处理异常

        3,使用IO流资源结束之后, 必须关系资源, close()

 

3,字节流

  1. 直接使用字节进行数据的操作
  2. 从流向上进行分类:

                 输入流 : InputStream

                 输出流 : OutputStream

3.1字节输入流

1,字节输入流 : InputStream, 来自于java.io包, 是所有的字节输入流的父类;

2,因为InputStream是抽象类, 不能实例化对象, 于是需要一个子类, FileInputStream, 来自于java.io包;

3,FileInputStream : 主要功能就是与磁盘上文件进行交互, 可以从磁盘上文件中读取出内容; 所有的文件都是以字节的形式组成, 因此FileInputStream 可以读取很多类型的文件内容, 例如 : txt, 图片, 视频...

4,FileInputStream的构造方法:

            ①, FileInputStream(String path) : 将path所表示的文件路径封装在一个字节输入流中, 以后字节输入流就可以从绑定的                        文件中读取出内容

             ②,FileInputStream(File file) : 将file所表示的文件路径封装在一个字节输入流中, 以后字节输入流就可以从绑定的文件中                      读取出内容

      注意 : 构造方法中, 只能封装文件, 千万不能是文件夹, IO流资源只能对文件进行操作, 无法操作文件夹

              常用方法:available():返回流中剩余可以读取的字节个数。

                                close():关闭这个流。

5,读取文件中内容:

      1,read() : 表示每次从文件中读取出一个字节, 返回值int类型结果; 返回的就是读取到的字节所对应的整数结果, 如果读取到-1,证明文件读取完毕;

              延伸 : 1个字节是8个连续的二进制位, 返回值类型int, 4字节大小, 因此读取到的字节需要补位成为一个4字节大小int, 因此                前三个字节都补充0, 最高位相当于符号位, 0符号位就表示正数, read()方法读取到的结果全部都是正数

      2,read(byte[] b) : 表示每次最多从文件中读取出b.length个字节, 读到的数据都同步到了参数b数组中, 通过查看数组b, 就相当于查看文件内容; 返回值类型int, 返回的是本次读取到的字节的个数, 如果读取到-1,证明文件读取完毕.

注意 : 按照数组进行文件内容读取比单个字节读取文件效率高很多

      3.读取文件的原理:

单个字节读取文件代码:

package com.ujiuye.io;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Demo01_FileInputStream {

	// 可以随时查看类型之间的继承关系 : 把鼠标定位在类型上, ctrl + T可以查看这个类型的继承关系
	public static void main(String[] args) throws IOException{
         // 1. 创建出一个字节输入流, 相当于绑定一个数据源
		 FileInputStream fis = new FileInputStream("D:\\aabbc.txt");
		 // 注意 : IO流资源只能操作文件, 不能操作文件夹
		 // FileInputStream fis1 = new FileInputStream(new File("D:\\1012系统班"));
	     /*int first = fis.read();
	     int second = fis.read();
	     int thrid = fis.read();
	     int four = fis.read();
	     int five = fis.read();
	     int six = fis.read();
		 System.out.println(first);// 97
		 System.out.println(second);// 98
		 System.out.println(thrid);// 99
		 System.out.println(four);// 33
		 System.out.println(five);// -1
		 System.out.println(six);// -1
    */		 
		 // len表示每次读取到的字节数据
		 int len;
		 while((len = fis.read()) != -1) {
			 System.out.print((char)len);
		 }
		 
		 // 一定要关闭资源
		 fis.close();
	}
}

字节数组读取文件代码:

3.2字节输出流

  1. OutputStream : 是所有字节输出流的抽象父类, 来自于java.io包中
  2. 因为OutputStream 是抽象类, 不能实例化对象, 因为需要一个子类 FileOutputStream
  3. FileOutputStream : 是字节输出流, 主要功能就是与文件进行数据交互, 将字节数据写入到文件中, 因为所有文件都是由字节组成的, 因此FileOutputStream 可以向很多类型文件中写入数据, 例如 :  txt, 图片, 视频...
  4. FileOutputStream构造方法:

                 1,FileOutputStream(String path) : 将path所表示的文件路径封装在一个字节输出流中, 以后字节输出流就可以向目标                         文 件 中写入数据内容

                 2,FileOutputStream(File file) : 将file所表示的文件路径封装在一个字节输出流中, 以后字节输出流就可以向目标文件                           中写入数据内容

             注意 : 构造方法中, 只能封装文件, 千万不能是文件夹, IO流资源只能对文件进行操作, 无法操作文件夹

                        FileOutputStream(String path ,boolean b)     FileOutputStream(File file, boolean b),后面的布尔类型如果为true,                          不覆盖,false会覆盖文件中的内容,从新写入。

     5,向文件中写入数据: write方法都没有返回值类型

                  1,write(int b) : 将字节数据b写入到文件中

                  2, write(byte[] b) : 将字节数组b中的所有内容写入到文件中

                  3,write(byte[] b, int index, int length) : 将数组b从index索引位置开始, 写入length个字节到文件中

                 注意 : 流资源使用完毕, 记得关闭资源; 按照字节数组写入数据比单个字节写入数据性能高很多

package com.ujiuye.io;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo03_FileOutputStream {
	public static void main(String[] args) throws IOException{
		File f = new File("second.txt");
		if(!f.exists()) {
			f.createNewFile();
		}
        // 1. 创建出一个字节输出流, 相当于绑定一个数据目的
		FileOutputStream fos = new FileOutputStream(f);
		//aABCDECD
		// 2. 向文件中写入数据
		// 1)write(int b) : 将字节数据b写入到文件中
		fos.write(97);// a
		fos.write(65);// A
		
		byte[] b = {66,67,68,69};
		// 2)write(byte[] b) : 将字节数组b中的所有内容写入到文件中
		fos.write(b);
		
		// 3)write(byte[] b, int index, int length) : 将数组b从index索引位置开始, 
		// 写入length个字节到文件中
		fos.write(b, 1, 2);// 67 68
		
		// getBytes() : 将字符串转成字节数组
		fos.write("你好".getBytes());
		
		// 记得关闭资源
		fos.close();
	}
}

 

3.3文件的复制

文件复制 : 本质就是边读(数据源)边写(数据目的)

注意 : 实际开发中, 通过数组形式进行文件读写, 可以很大提高IO流的效能, 数组大小一般都是1024的倍数比较常见

最常见 : 1024  1024 * 4  1024 * 8 (1024*8数组大小一般是JDK底层源代码比较倾向的数组大小设置)

package com.ujiuye.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo04_PictureCopy {
	public static void main(String[] args) throws IOException{
       // 1. 创建出一个字节输入流, 绑定一个数据源
	   FileInputStream fis = new FileInputStream("D:\\1012系统班\\day02\\图解\\变量定义和赋值过程.png");
	   // 2.  创建出一个字节输出流, 绑定一个数据目的
	   FileOutputStream fos = new FileOutputStream("D:\\变量定义copy2.png");
	   
	   // 3. 单个字节复制
	   // len表示每次读取到的字节数据结果
	   /*int len;
	   while((len = fis.read()) != -1) {
		   fos.write(len);
	   }*/
	   
	   // 4. 使用字节数组读写文件, 提高效率
	   byte[] b = new byte[1024*4];
	   // len表示读取到的字节的个数
	   int len;
	   while((len = fis.read(b)) != -1) {
		   fos.write(b, 0, len);
	   }
	   
	   fos.close();
	   fis.close();
	}
}

 

3.4字节高效缓冲流

1,  字节高效缓冲流 : 作用就是提高普通字节流资源的读写效率, 缓冲流底层自动使用1024*8字节数组进行文件的读写

BufferedInputStream : 字节高效缓冲输入流, 也是一个包装类, 功能将一个普通字节输入流,包装成一个高效字节缓冲流

 2,  通过构造方法可以看到包装过程 : BufferedInputStream(InputStream in)

BufferedOutputStream : 字节高效缓冲输出流, 也是一个包装类, 功能将一个普通字节输出流,包装成一个高效字节缓冲流

3,   通过构造方法可以看到包装过程 : BufferedOutputStream(OutputStream out)

 

4,   高效原理:

BufferedInputStream : 当创建出一个BufferedInputStream 类型的输入流资源, 代码底层自动创建出一个大小为8192(1024 * 8)的字节数组; 每次调用read方法读取数据, 都最多从文件中读取出8192个字节, 将读取到的字节数据放置到底层数组缓冲中, 以后读取数据,从底层数组缓冲中读取, 以此减少与磁盘交互, 从而提高读取效能; 直到读取到的结果为-1,读取完毕

BufferedOutputStream  : 当创建出一个BufferedOutputStream 类型输出流资源,代码底层自动创建出一个大小为8192(1024 * 8)字节数组;每次向文件中写入数据, 都是写入到了底层数组缓冲中, 等到将8192数组写满, 自动同步数据到文件中; 如果数组没有写满, 可以通过close方法, 关闭资源, 关闭资源之前, 会先将数组缓冲中的数据同步到文件中, 后关闭资源; 减少了与磁盘交互, 从而提高写入效能

package com.ujiuye.file;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class BufferedInputStream01 {
	public static void main(String[] args) throws IOException{
		InputStream is =new FileInputStream("e:\\a\\01.day14内容回顾.mp4");
		OutputStream os = new FileOutputStream("e:\\day1内容回顾.mp4");
		BufferedInputStream bs = new BufferedInputStream(new FileInputStream("e:\\a\\01.day14内容回顾.mp4"));
		BufferedOutputStream bO = new BufferedOutputStream(new FileOutputStream("e:\\create\\day1内容回顾.mp4"));
		int len = 0;
		long beginTime = System.currentTimeMillis();
		while((len = bs.read())!=-1) {
			bO.write(len);
		}
		long endTime = System.currentTimeMillis();
		System.out.println(endTime-beginTime);
		
		
		
		long beginTime1 = System.currentTimeMillis();
		int len1 = 0;
		while((len1 = is.read()) != -1) {
			os.write(len1);
		}
		long endTime1 = System.currentTimeMillis();
		System.out.println(endTime1 - beginTime1);
        os.close();
        is.close();
        bs.close();
        bO.close();		
	}
}

BufferedOutputStream的效率远高于FileOutputStream.

4.字符流

4.1字节流读取中文乱码问题

            

   1,问题 : 通过字节输入流读取一个带有中文文本文件

          1,按照单个字节进行读取, 读取到结果乱码(实际结果与预期结果不符), 原因 : 默认的GBK编码中, 一个中文占有2个字节, 通             过单个字节读取文件, 就将中文拆分了, 拆分之后转换成对应的字符, 导致乱码

          2,按照字节数组读取, 设置大小为2字节数组, 如果文件中是中英文混合, 仍然有可能将中文拆分开读取, 结果还是乱

        结论 : 不要使用字节流读取带有中文的文本文件

   2,解决中文文本读取乱码问题?  按照字符读取,就可以解决中文被拆分的问题, 因为一个字母, 一个符号, 或者是一个中文, 一个数        字, 统统都是一个字符

package com.ujiuye.io;
import java.io.FileInputStream;
import java.io.IOException;
public class Demo01_FileInputStreamReadChinese {
	public static void main(String[] args) throws IOException{
		 // 1. 绑定一个数据源
         FileInputStream fis = new FileInputStream("chinese.txt");
         // 2. 使用单个字节进行文件内容读取
         // len表示每次读取到的字节对应的数据结果
        /* int len;
         while((len = fis.read()) != -1) {
        	 System.out.print((char)len);
         }*/
         
         // 3. 使用字节数组读取文件内容
         byte[] b = new byte[2];
         // len表示每次读取到的字节的个数
         int len;
         while((len = fis.read(b)) != -1) {
        	 System.out.print(new String(b,0,len));
         }
         fis.close();
	}
}

 

4.2字符输入流

1,Reader : 字符输入流抽象父类, 来自于java.io包

2,抽象类不能实例化对象, 因此需要子类 FileReader, 来自于java.io包, 作用就是通过字符读取文件内容, 注意 : FileReader主要读取文本文件(txt文件)

3.字符输入流FileReader读取原理:

   所有文件都是字节组成, 在默认的GBK编码表中, 一个数字, 一个符号, 一个大小写字母, 都占有一个字节, 来自于ASCII编码表中, 都是正数(0-127); 一个中文占有2个字节, 第一个字节为负数;

   字符输入流会先从文件中读取出一个字节, 判断如果这个字节为正数, 证明读取到了ASCII编码表中的一个字符, 直接参考编码表转字符; 如果读取到的第一个字节是负数, 那么动态再向下读取出另外一个字节, 将两个字节一起参考编码表转换成字符

 

4,FileReader构造方法:

  a : FileReader(String fileName)

  b: FileReader(File file)

 

5,读取文件的方式:

read() : 每次读取一个字符, 返回值类型int, 返回的就是读取到的字符在编码表中的整数结果, 如果返回-1,证明读取完毕

read(char[] ch) : 每次最多读取出ch.length个字符, 将读取到的字符数据同步到参数ch数组中, 查看ch数组相当于在查看文件内容; 返回值类型int, 表示本次读取到的字符的个数, 如果读取到-1,证明文件读取完毕

package com.ujiuye.io;
import java.io.FileReader;
import java.io.IOException;
public class Demo02_FileReader {
	public static void main(String[] args) throws IOException{
        // 1. 创建出一个字符输入流, 绑定一个数据源
		FileReader fr = new FileReader("chinese.txt");
		// 2. 使用单个字符读取文件内容
		// len表示读取到的字符在编码表中对应的整数结果
		/*int len;
		while((len = fr.read()) != -1 ) {
			System.out.print((char)len);
		}*/
		
		// 3. 使用字符数组读取文件内容
		char[] ch = new char[3];
		// len表示读取到的字符的个数
		int len;
		while((len = fr.read(ch)) != -1) {
			System.out.print(new String(ch, 0, len));
		}
		fr.close();
	}
}

 

4.3字符输出流

1,Writer : 字符输出流的抽象父类, 来自于java.io包

2,抽象类不能实例化对象, 因此需要子类FileWriter, 来自于java.io包. 主要功能就是以字符方式向文件中写入数据

3,FileWriter构造方法:

           FileWriter(String fileName)

           FileWriter(File file)

4,向文件中写入数据方式:  write方法返回值类型 void

           write(int c) : 表示每次写个一个字符

           write(char[] ch) : 表示每次可以将ch数组中的所有字符内容写入到文件中

            write(char[] ch , int index , int length) : 表示每次将ch数组中的一部分写入到文件中; 从index索引位置开始写, 写入length               个          字符

             write(String s): 将字符串s写入到文件中

            write(String s, int index, int length) : 表示将字符串s从index索引位置开始, 写入length个字符到文件中

package com.ujiuye.io;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Demo03_FileWriter {
	public static void main(String[] args) throws IOException{
         File f = new File("abc.txt");
         if(!f.exists()) {
        	 f.createNewFile();
         }
         
         // 1. 创建出一个字符输出流, 绑定一个数据目的
         FileWriter fw = new FileWriter(f);
         //A1a&中a&我爱我家,天气真好我家,天
         // 2. 向文件中写入数据
         // 写入单个字符
         fw.write('A');
         char[] ch = {'1','a','&','中'};
         // 写入字符数组
         fw.write(ch);
         // 写入字符数组一部分
         fw.write(ch, 1, 2);
         String s = "我爱我家,天气真好";
         // 写入字符串
         fw.write(s);
         // 写入字符串一部分
         fw.write(s, 2, 4);
         // 3. 一定要关闭资源
         fw.close();
	}
}

 

4.4flush和close方法的比较

IO流资源中的数组缓冲 : 带有数组缓冲流资源在读写效能上更高, 但是举例 : 向文件中写入内容; 写的数据都是自动存储在底层数组缓冲区域中, 如果缓冲区写满, 自动同步到文件中; 或者通过flush或者close方法让缓冲区中的数据同步到文件中

1,flush() : 表示刷新, 将当前正在使用的IO流资源在底层缓冲区中的数据同步到文件中, flush刷新之后的流资源还可以继续使用

2,close() : 表示关闭资源, 当调用close方法关闭资源之前, 先调用flush功能, 将缓冲区中数据同步到文件中, 同步数据结束, 再关闭流资源和相关系统资源; close关闭资源之后,流资源不能再继续使用

注意 : 使用IO流, 一定必须要关闭资源

package com.ujiuye.io;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Demo03_FileWriter {
	public static void main(String[] args) throws IOException{
         File f = new File("abc.txt");
         if(!f.exists()) {
        	 f.createNewFile();
         }
         
         // 1. 创建出一个字符输出流, 绑定一个数据目的
         FileWriter fw = new FileWriter(f);
         //A1a&中a&我爱我家,天气真好我家,天
         // 2. 向文件中写入数据
         // 写入单个字符
         fw.write('A');
         char[] ch = {'1','a','&','中'};
         // 写入字符数组
         fw.write(ch);
         // 写入字符数组一部分
         fw.write(ch, 1, 2);
         // 刷新数组缓冲区中数据到文件中
         fw.flush();
         String s = "我爱我家,天气真好";
         // 写入字符串
         fw.write(s);
         // 写入字符串一部分
         fw.write(s, 2, 4);
         // 3. 一定要关闭资源
         fw.close();
         // 关闭流资源之后, 流不能再继续使用, 否则代码会报错 : IOException
         // fw.write("helloworld");
	}
}

 

4.5字符流复制纯文本文件

结论 :

如果使用字符流复制文件, 只能复制纯文本文件(使用txt记事本形式可以打开, 还能读懂的文件, 称为纯文本文件)

复制过程效率不高(效率低)

package com.ujiuye.io;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo04_字符串Copy {
	public static void main(String[] args) throws IOException{
         // 1. 创建出一个字符输入流, 读取文件 , 绑定一个数据源
		 FileReader fr = new FileReader("abc.txt");
		 // 2. 创建出一个字符输出流, 写入文件, 绑定一个数据目的
		 FileWriter fw = new FileWriter("abcCopy.txt");
		 // len表示每次读取到的字符的个数
		 int len;
		 char[] ch = new char[10];
		 while((len = fr.read(ch)) != -1) {
			 fw.write(ch, 0, len);
		 }
		 
		 fw.close();
		 fr.close();
	}
}

 

4.6字符流不能复制非纯文本文件

非纯文本文件中字节, 例如 : 图片,音频,视频...在编码表中不存在, 也没有办法转换成正确字符, 导致文件复制过程中, 字节转换成字符的过程出错; 将错误的字符转换成字节, 写入到目的文件中, 目的文件中字节与源文件已经不同, 导致复制失败

package com.ujiuye.io;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo05_字符流复制非纯文本失败 {
	public static void main(String[] args) throws IOException{
          FileReader fr = new FileReader("D:\\1012系统班\\day06\\图解\\两个对象在内存中理解.png");
          FileWriter fw = new FileWriter("D:\\对象Copy.png");
          
          int len;
          char[] ch = new char[1024];
          while((len = fr.read(ch)) != -1) {
        	  fw.write(ch, 0, len);
          }        
          fw.close();
          fr.close();
	}
}

 

4.7高效缓冲字符流

  1. 高效缓冲字符流 : 作用就是可以提高字符流读写效率, 将字符数组作为读写的缓冲, 从而减少与磁盘交互, 进而提高读写效率
  2. BufferedReader: 是Reader的子类, 称为高效缓冲字符输入流, 本身是一个包装类, 将一个最普通字符输入流,包装成一个高效字符输入流

   从构造方法封装可以看出包装性 : BufferedReader(Reader in)

    3.BufferedWriter: 是Writer的子类, 称为高效缓冲字符输出流, 本身是一个包装类, 将一个最普通字符输出流,包装成一个高效字            符输出流

   4,从构造方法封装可以看出包装性 : BufferedWriter(Writer out)

  1. 简单描述高效缓冲流的高效原理:
  1. BufferedReader, 当创建出一个BufferedReader类型流资源对象时, 代码底层自动创建出一个大小为8192(1024*8)的字符数组, 每次调用read方法读取文件, 都最多读取出8129个字符放置到底层字符数组中, 以后读取就从底层数组中读取, 如果8192读取完毕,继续从文件中最多读8192个,以此类推, 直到读取到-1,文件结束为止; 如此减少与磁盘的交互, 提高读取效率
  2. BufferedWriter, 当创建出一个BufferedWriter流资源对象时, 代码底层自动创建出一个大小为8192(1024*8)的字符数组, 每次向文件中写入数据, 都是先写入到底层数组中, 如果8192写满了, 自动将数组中的内容同步到文件中, 如果8192没有写满, 可以使用flush或者close方法将缓冲区中数据同步到文件中; 如此减少与磁盘的交互, 提高读取效率
package com.ujiuye.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo06_BufferedStream {
	public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(
        		new FileReader("chinese.txt"));
        
        BufferedWriter bw = new  BufferedWriter(
        		new FileWriter("chineseCopy.txt"));
        
        int len;
        while((len = br.read()) != -1) {
        	bw.write(len);
        }
        
        br.close();
        bw.close();
	}
}

 

4.8高效缓冲字符流特有方法

  1. BufferedReader : 中有特殊方法功能

   readLine() : 每次从文件中读取出一行文字, 返回值类型String类型; 如果返回的结果为null, 证明文件读取完毕

  1. BufferedWriter : 中有特殊方法功能

   newLine() : 在文件中写入一个换行符, 不受操作系统限制

package com.ujiuye.io;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Demo07_字符缓冲流特有方法 {
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(
        		new FileReader("javaCode.txt"));
        
        BufferedWriter bw = new  BufferedWriter(
        		new FileWriter("javaCodeCopy.txt"));
        
        // s表示每次读取到的一行内容
        String s;
        while((s = br.readLine()) != null) {
        	bw.write(s);
        	// 向文件中写入回车换行
        	bw.newLine();
        }       
        bw.close();
        br.close();
	}
}

5,转换流

  1. 编码表 :

                    GBK : 中国标准码表, 底层兼容ASCII编码, 一个中文占有2字节大小

                     UTF-8 : 万国码表, 底层兼容ASCII编码, 一个中文占有3字节大小

  1. 读写带有中文文本文件时, 发生乱码情况一般有两种:

                    流资源选择不正确, 例如字节流读取中文, 可能将中文拆开读取, 导致乱码, 改成字符流读取

                  读写文件时, 因为文件的编码集不同, 也会导致读写文件是发生乱码问题, 使用转换流解决不同编码集文件读写乱码问题

 

  1. 将文件编码集进行修改 : 如下图

                    点击指定需要修改编码集的文件--->鼠标右键--->properties(属性)

4.转换流 : 主要功能就是可以根据文件指定的编码集读写文件

           1),InputStreamReader : 字节到字符的桥梁, 父类Reader, 字符输入流

                        构造方法 : InputStreamReader(InputStream in, String charsetName)

                           a : 第一个参数 in , 表示一个字节输入流, 从文件中读取出字节数据

                           b : 将读取到的字节通过第二个参数charsetName编码集, 将字节通过指定编码集转换成字符

            2),OutputStreamWriter : 字符到字节桥梁, 父类Writer, 字符输出流

                       构造方法 :  OutputStreamWriter(OutputStream out, String charsetName)

                           a : 将文件中读取到的字符, 参考第二个参数charsetName, 参考指定编码表转换成字节数据

                           b : 将字节使用第一个参数out写入到文件中

 注意 : 使用转换流时, 给出编码集与要操作的文件的编码集一致

  举例 : 例如需要读取的文件编码是UTF-8, 转换流中给出的编码集就是UTF-8

         例如需要写入的文件的编码是GBK, 转换流中给出的编码集就是GBK

package com.ujiuye.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Demo10_转换流 {
	public static void main(String[] args) throws IOException{
        // 1. 创建出一个输入流, 读取文件
		InputStreamReader isr = new InputStreamReader(
				new FileInputStream("UTF-8.txt"), "UTF-8");
		
		// 2. 创建出一个输出流, 向文件中写入数据
		OutputStreamWriter osw = new OutputStreamWriter(
				new FileOutputStream("GBK.txt"), "GBK");
		
		int len;
		while((len = isr.read()) != -1) {
			osw.write(len);
		}
		
		osw.close();
		isr.close();	
	}
}

6.IO流的标准异常处理方式(扩展)

  1. 标准IO流异常处理方式很繁琐,但是很安全!
  2. 从JDK1.7版本开始, 为IO流资源使用提供新的异常处理语法结构:

try(

    IO流资源创建写入在try的小括号中;

){

    // 可能会发生异常的代码, 主要IO流资源的读写使用

}catch(异常类型 变量名){

// 对于异常处理方式

}

3,try代码块中的小括号作用 : 会在流资源使用结束后, 自动关闭资源;  因此新的语法结构中, IO流资源不需要手动关闭

JDK7对于IO流新异常处理方式:

package com.ujiuye.io;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo12_JDK7IO流资源新异常处理 {
   public static void main(String[] args) {
	   try(
			   FileInputStream fis = new FileInputStream("abc.txt");  
			   FileOutputStream fos = new FileOutputStream("abcCopy.txt");
		){
		     int len;
	         while((len = fis.read()) != -1) {
	        	 fos.write(len);
	         }
		   
	   }catch(IOException ex) {
		   ex.printStackTrace();
	   }
   }
}

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值