字符流
2.3.1 方便程序员的IO流
在IO开发过程中,我们传输最频繁的数据为字符,而以字节方式传输字符需要每次将字符串转换成字节再处理,而且也丧失了程序员对数据内容的判断(因为程序员只认识字符,不认识字节)。所以,为了让程序员方便对字符进行操作,Java提供了专门以字符作为操作单位的类——字符流,其底层仍然为字节流。
显然,字符流只能操作字符,无法操作其他数据,如声音、视频等。
2.3.2 字符输出流FileWirter
既然有专门用于读取字符的流对象,那么肯定也有写的字符流对象,查阅API,发现有一个Writer类,Writer是写入字符流的抽象类。其中描述了相应的写的动作。
FileWriter类
查阅FileOutputStream的API,发现FileOutputStream 用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用 FileWriter。
打开FileWriter的API介绍。用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节高效区大小都是可接受的。
4 FileWirter写数据
-
构造方法
-
FileWriter(String fileName) 传递一个文件名称
-
-
成员方法
-
void write(String str) 往文件中写入一个字符串。
-
void flush() 刷新该流的缓冲,把内存缓冲区中的数据刷新到文件中。
-
void close() 关闭此流,但要先刷新它。
-
-
输出流写数据的步骤:
-
1.创建输出流对象
-
2.调用输出流对象的写数据的方法
-
3.释放资源
-
-
5 FileWriter写入中文到文件中
-
写入字符到文件中,先进行流的刷新,再进行流的关闭。
package cn.demo.digui; import java.io.FileWriter; import java.io.IOException; public class Demo6 { public static void main(String[] args) throws IOException { // 创建输出流对象 FileWriter fw = new FileWriter("D:\FileDemo\a.txt"); /* * 创建输出流对象做了哪些事情: A:调用系统资源创建了一个文件 B:创建输出流对象 C:把输出流对象指向文件 */ // 调用输出流对象的写数据的方法 // 写一个字符串数据 fw.write("世界你好,我是中国人"); // 数据没有直接写到文件,其实是写到了内存缓冲区 fw.flush(); // 释放资源 // 通知系统释放和该文件相关的资源 fw.close(); // while(true) {} } }
-
.6 close()和flush()方法的区别:
flush():将流中的高效区高效的数据刷新到目的地中,刷新后,流还可以继续使用。
close():关闭资源,但在关闭前会将高效区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭。
package cn.demo.digui; import java.io.FileWriter; import java.io.IOException; public class Demo7 { public static void main(String[] args) throws IOException { //创建输出流对象,指定存在的路径 FileWriter fw = new FileWriter("D:\FileDemo\b.txt"); //调用输出流对象的写数据方法,并刷新缓冲区 fw.write("helloworld"); fw.flush(); fw.write("java"); fw.flush(); fw.write("我是中国人,我是地球人"); fw.flush(); //释放资源 fw.close(); } }
-
7 FileWriter写数据的5个方法
-
void write(String str):写一个字符串数据
-
void write(String str,int index,int len):写一个字符串中的一部分数据, index:开始索引,len:写几个
-
void write(int ch):写一个字符数据,这里写int类型的好处是既可以写char类型的数据,也可以写char对应的int类型的值。'a',97
-
void write(char[] chs):写一个字符数组数据
-
void write(char[] chs,int index,int len):写一个字符数组的一部分数据, index:开始索引,len:写几个
package cn.demo.digui; import java.io.FileWriter; import java.io.IOException; public class Demo8 { public static void main(String[] args) throws IOException { // 创建输出流对象 FileWriter fw = new FileWriter("D:\FileDemo\c.txt"); // void write(String str):写一个字符串数据 fw.write("abcde"); // void write(String str,int index,int len):写一个字符串中的一部分数据, // index:开始索引,len:写几个 fw.write("abcde", 0, 5); fw.write("abcde", 1, 3); // void write(int // ch):写一个字符数据,这里写int类型的好处是既可以写char类型的数据,也可以写char对应的int类型的值。'a',97 fw.write('a'); fw.write(97); // void write(char[] chs):写一个字符数组数据 char[] chs = { 'a', 'b', 'c', 'd', 'e' }; // fw.write(chs); // void write(char[] chs,int index,int len):写一个字符数组的一部分数据, // index:开始索引,len:写几个 fw.write(chs, 0, 5); fw.write(chs, 2, 3); // 释放资源 fw.close(); } }
-
8.FileReader类
查阅FileInputStream的API,发现FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。
打开FileReader的API介绍。用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节高效区大小都是适当的
package cn.demo.digui; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; public class FileReaderDemo { public static void main(String[] args) throws IOException { // 给文件中写中文 writeCNText(); // 读取文件中的中文 readCNText(); } // 读取中文 public static void readCNText() throws IOException { //创建文件读取流,指定读取的路径 FileReader fr = new FileReader("D:\FileDemo\e.txt"); //初始值 int ch = 0; while ((ch = fr.read()) != -1) { // 输出的字符对应的编码值 System.out.println(ch); // 输出字符本身 System.out.println((char) ch); } } // 写中文 public static void writeCNText() throws IOException { //创建文件输出流,指定文本路径 FileOutputStream fos = new FileOutputStream("D:\FileDemo\e.txt"); //向文本中写入中文 fos.write("我的奋斗不是梦,那是理想,请相信自己,如果自己都不相信自己,谁能相信你,加油".getBytes()); //关闭流 fos.close(); } }
-
练习:
-
将50-800(包含)之间的二十个随机数存在集合中,并将集合中是3的倍数的数字存放在文件number.txt中
package cn.demo.digui; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Random; //将50-800(包含)之间的二十个随机数存在集合中,并将集合中是3的倍数的数字存放在文件number.txt中 public class Text1 { public static void main(String[] args) throws IOException { // 创建一个ArrayList集合 ArrayList<Integer> a1 = new ArrayList<>(); // 创建随机数 Random random = new Random(); // 循环遍历获取二十个随机数, for (int i = 0; i < 20; i++) { // random.nextInt(800) 800的随机数 +50,表示50到800之间的数,获取随机数 int nextInt = random.nextInt(750) + 50; // 把这20个随机数添加到a1集合中 a1.add(nextInt); } // 遍历获取的随机数并存入number.txt文件中 // 1.创建字符输出流,FileWriter;输出到D盘 FileWriter fw = new FileWriter("D:\FileDemo\number.txt"); // 2.遍历符合条件的数据 for (int i = 0; i < a1.size(); i++) { // 判断条件 if (a1.get(i) % 3== 0) { // 获取符合条件的数字 Integer integer = a1.get(i); // 写出数据 fw.write(integer + ","); // 刷新 fw.flush(); } } // 关闭流 fw.close(); } }
练习二:使用字节流,将一个路径下的视频复制到另一路径下
package cn.demo.file; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class CopyVideo { public static void main(String[] args) throws IOException { //D:\FileDemo\video 存放路径 method("D:\FileDemo\video\01.avi", "D:\FileDemo\video\02.avi"); } // 字节流,一次可以一个字节一个字节的读写,但是效率太低,因此在这一次一个字节数组 public static void method(String srcPath, String destPath) throws IOException { //明确字节流 输入流和源相关联,输出流和目的关联。 //文件输入流 FileInputStream fis = new FileInputStream(srcPath); //文件输出流 FileOutputStream fos = new FileOutputStream(destPath); // 读取数据 byte[] buffer = new byte[1024]; int len = 0; //读取输入流 while ((len = fis.read(buffer)) != -1) { // 写数据到目的地,写输出流 将数组中的指定长度的数据写入到输出流中,buf 表示 存数据的数组, 0 表示开始的位置, len 有效字符个数 fos.write(buffer, 0, len); } //关闭输出流 fos.close(); //关闭输入流 fis.close(); } }
-
输出结果如下:
-
练习三:使用字符流,将一个路径下的文本文件复制到另一路径下
package cn.demo.file; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; //使用字符流,将一个路径下的文本文件复制到另一路径下 public class CopyFile { public static void main(String[] args) throws IOException { // 数据源,//D:\FileDemo\video 存放路径 String srcPath = "D:\FileDemo\video\a.txt"; // 目的地 String destPath = "D:\FileDemo\video\b.txt"; //递归调用method方法 method(srcPath, destPath); } // 字节流: public static void method(String srcPath, String destPath) throws IOException { //明确字节流 输入流和源相关联,输出流和目的关联。 //创建文件输入流 FileInputStream fis = new FileInputStream(srcPath); //创建文件输入流 FileOutputStream fos = new FileOutputStream(destPath); // 读 byte[] buffer = new byte[1024]; int len = 0; while ((len = fis.read(buffer)) != -1) { // 写数据到目的地 //将数组中的指定长度的数据写入到输出流中,buffer 表示 存数据的数组, 0 表示开始的位置, len 有效字符个数 fos.write(buffer, 0, len); } //关闭输入流 fis.close(); //关闭输出流 fos.close(); } }
-
运行结果如下图所示:
-
练习四:复制文件夹,将demo文件夹中的文本与图片等复制到demo1文件夹中
package cn.demo.file; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; //复制文件夹,将demo文件夹中的文本与图片等复制到demo1文件夹中 public class CopyFile2 { public static void main(String[] args) throws IOException { // 封装数据源 File srcPath = new File("D:\FileDemo\demo");//D:\FileDemo\demo // 封装目的地 File destPath = new File("D:\FileDemo\demo1"); // 创建目的地文件夹 destPath.mkdirs(); // 2:获取到数据源中所有的File对象 File[] files = srcPath.listFiles(); // 3:遍历, 得到每一个File对象 for (File file : files) { // 4:复制文件 // 得到名字 String name = file.getName(); // 组成目的地File对象 File dest = new File(destPath, name); copyFile(file, dest); } } // 复制文件 private static void copyFile(File srcPath, File destPath) throws IOException { //创建文件输入流 FileInputStream fis = new FileInputStream(srcPath); //创建文件输出流 FileOutputStream fos = new FileOutputStream(destPath); // 读取数据 byte[] buffer = new byte[1024]; int len = 0; //读取输入流的信息 while ((len = fis.read(buffer)) != -1) { // 写数据到目的地 //将数组中的指定长度的数据写入到输出流中,buffer 表示 存数据的数组, 0 表示开始的位置, len 有效字符个数 fos.write(buffer, 0, len); } //关闭输出流 fos.close(); //关闭输入流 fis.close(); } }
-
输出结果如下: