【Java】【基础篇】day19:IO流(字节流、转换流读写)

    技术2025-06-14  29

    前言

    本期任务:毕向东老师Java视频教程学习笔记(共计25天)

    原视频链接:黑马程序员_毕向东_Java基础视频教程day01:编写HelloWorld程序day02:操作符与条件选择语句day03:循环语句与函数day04:数组day07:继承、抽象类与接口day08:多态day09:异常处理day11:多线程day12:线程安全与同步机制day13:String类day14:集合(ArrayList,LinkedList,HashSet)day15:集合(TreeSet)和泛型)day16:集合(HashMap、TreeMap)day17:集合框架的工具类(Arrays、Collections)day18:IO流(字符流读写)day19:IO流(字节流、转换流读写)day20:IO流(File对象)

    代码

    /* 复制一个图片 思路: 1,用字节读取流对象和图片关联。 2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。 3,通过循环读写,完成数据的存储。 4,关闭资源。 */ import java.io.*; public class CopyPic { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("picture.png"); FileOutputStream fos = new FileOutputStream("copy_picture.png"); byte[] buf = new byte[1024]; int len = 0; while ((len = fis.read(buf)) != -1) { fos.write(buf, 0, len); fos.flush(); } fos.close(); } } /* 通过缓冲区复制一个.java文件。 */ import java.io.*; public class CopyTextByBuf { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("buf.txt"); FileWriter fw = new FileWriter("buf_copy.txt"); BufferedReader bufr = new BufferedReader(fr); BufferedWriter bufw = new BufferedWriter(fw); String line = null; while ((line = bufr.readLine()) != null) { bufw.write(line); bufw.newLine(); bufw.flush(); } bufr.close(); bufw.close(); } } import java.io.*; /* 演示mp3的复制。通过缓冲区。 BufferedOutputStream BufferedInputStream */ public class CopyMp3 { public static void main(String[] args) throws IOException { BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("夜曲.wav")); BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("copy_夜曲.wav")); int by = 0; while ((by = bufis.read()) != -1) { bufos.write(by); } bufis.close(); bufos.close(); } } /* 缓冲区的出现是为了提高流的操作效率而出现的。 所以在创建缓冲区之前,必须要先有流对象。 该缓冲区中提供了一个跨平台的换行符。 newLine(); */ import java.io.*; public class BufferedWriterDemo { public static void main(String[] args) throws IOException{ // 创建一个字符写入流对象 FileWriter fw = new FileWriter("buf.txt"); //为了提高字符写入流效率。加入了缓冲技术。 //只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。 BufferedWriter bufw = new BufferedWriter(fw); for (int x=0; x<5; x++){ bufw.write("abc"+x); bufw.newLine(); bufw.flush();//记住,只要用到缓冲区,就要记得刷新。 } //其实关闭缓冲区,就是在关闭缓冲区中的流对象。 bufw.close(); } } /* 字符读取流缓冲区: 该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。 当返回null时,表示读到文件末尾。 readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。 */ import java.io.*; public class BufferedReaderDemo { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("buf.txt"); //为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。 BufferedReader bufr = new BufferedReader(fr); String line = null; while ((line = bufr.readLine()) != null) { System.out.println(line); } bufr.close(); } } //练习:模拟一个带行号的缓冲区对象。 import java.io.*; public class LineNumberReaderDemo { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("buf.txt"); LineNumberReader lnr = new LineNumberReader(fr); String line = null; // lnr.setLineNumber(100); while ((line = lnr.readLine()) != null) { System.out.println(lnr.getLineNumber() + "::" + line); } lnr.close(); } } /* 读取键盘录入。 System.out:对应的是标准输出设备,控制台。 System.in:对应的标准输入设备:键盘。 需求: 通过键盘录入数据。 当录入一行数据后,就将该行数据进行打印。 如果录入的数据是over,那么停止录入。 */ import java.io.*; public class ReadIn { public static void main(String[] args) throws IOException { InputStream in = System.in; StringBuilder sb = new StringBuilder(); while (true) { int ch = in.read(); // 键盘录入的是字节,扩成int类型 if (ch == '\r') continue; if (ch == '\n') { String s = sb.toString(); if ("over".equals(s)) break; System.out.println(s.toUpperCase()); sb.delete(0, sb.length()); } else{ sb.append((char) ch); // 将int类型转换成字符类型 } } } } /* 字符流: FileReader FileWriter。 BufferedReader BufferedWriter 字节流: FileInputStream FileOutputStream BufferedInputStream BufferedOutputStream 通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。 也就是readLine方法。 能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢? readLine方法是字符流BufferedReader类中的方法。 而键盘录入的read方法是字节流InputStream的方法。 那么能不能将字节流转成字符流在使用字符流缓冲去的readLine方法呢? */ /* 1, 源:键盘录入。 目的:控制台。 2,需求:想把键盘录入的数据存储到一个文件中。 源:键盘。 目的:文件。 3,需求:想要将一个文件的数据打印在控制台上。 源:文件。 目的:控制台。 流操作的基本规律: 最痛苦的就是流对象有很多,不知道该用哪一个。 通过三个明确来完成。 1,明确源和目的。 源:输入流。InputStream Reader 目的:输出流。OutputStream Writer。 2,操作的数据是否是纯文本。 是:字符流。 不是:字节流。 3,当体系明确后,在明确要使用哪个具体的对象。 通过设备来进行区分: 源设备:内存,硬盘。键盘 目的设备:内存,硬盘,控制台。 1,将一个文本文件中数据存储到另一个文件中。复制文件。 源:因为是源,所以使用读取流。InputStream Reader 是不是操作文本文件。 是!这时就可以选择Reader 这样体系就明确了。 接下来明确要使用该体系中的哪个对象。 明确设备:硬盘。上一个文件。 Reader体系中可以操作文件的对象是 FileReader 是否需要提高效率:是!。加入Reader体系中缓冲区 BufferedReader. FileReader fr = new FileReader("a.txt"); BufferedReader bufr = new BufferedReader(fr); 目的:OutputStream Writer 是否是纯文本。 是!Writer。 设备:硬盘,一个文件。 Writer体系中可以操作文件的对象FileWriter。 是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter FileWriter fw = new FileWriter("b.txt"); BufferedWriter bufw = new BufferedWriter(fw); 练习:将一个图片文件中数据存储到另一个文件中。复制文件。要按照以上格式自己完成三个明确。 --------------------------------------- 2,需求:将键盘录入的数据保存到一个文件中。 这个需求中有源和目的都存在。 那么分别分析 源:InputStream Reader 是不是纯文本?是!Reader 设备:键盘。对应的对象是System.in. 不是选择Reader吗?System.in对应的不是字节流吗? 为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。 所以既然明确了Reader,那么就将System.in转换成Reader。 用了Reader体系中转换流,InputStreamReader InputStreamReader isr = new InputStreamReader(System.in); 需要提高效率吗?需要!BufferedReader BufferedReader bufr = new BufferedReader(isr); 目的:OutputStream Writer 是否是存文本?是!Writer。 设备:硬盘。一个文件。使用 FileWriter。 FileWriter fw = new FileWriter("c.txt"); 需要提高效率吗?需要。 BufferedWriter bufw = new BufferedWriter(fw); ************** 扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。 目的:OutputStream Writer 是否是存文本?是!Writer。 设备:硬盘。一个文件。使用 FileWriter。 但是FileWriter是使用的默认编码表。GBK. 但是存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。 所以要使用的对象是OutputStreamWriter。 而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8"); 需要高效吗?需要。 BufferedWriter bufw = new BufferedWriter(osw); 所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时, 需要用到转换流。 练习:将一个文本数据打印在控制台上。要按照以上格式自己完成三个明确。 */ import java.io.*; public class TransStreamDemo { public static void main(String[] args) throws IOException { // // 获取键盘对象 // InputStream in = System.in; // // // 将字节流对象转换成字符流对象,使用转换流:InputStreamReader // InputStreamReader isr = new InputStreamReader(in); // // // 为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferReader // BufferedReader bufr = new BufferedReader(isr); // 键盘的最常见写法 BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); // 同理 // OutputStream out = System.out; // OutputStreamWriter osw = new OutputStreamWriter(out); // BufferedWriter bufw = new BufferedWriter(osw); // 控制台输出的最常见写法 BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); String line = null; while ((line = bufr.readLine()) != null) { if ("over".equals(line)) break; bufw.write(line.toUpperCase()); bufw.newLine(); bufw.flush(); } bufr.close(); } } /* 装饰设计模式: 当想要对已有的对象进行功能增强时, 可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。 那么自定义的该类称为装饰类。 装饰类通常会通过构造方法接收被装饰的对象。 并基于被装饰的对象的功能,提供更强的功能。 */ class Person{ public void chiFan(){ System.out.println("吃饭"); } } class SuperPerson{ private Person p; SuperPerson(Person p){ this.p = p; } public void superChiFan(){ System.out.println("开胃酒"); p.chiFan(); System.out.println("甜点"); System.out.println("来一根"); } } public class 装饰和继承 { public static void main(String[] args) { Person p = new Person(); p.chiFan(); System.out.println("-----------------"); SuperPerson sp = new SuperPerson(p); sp.superChiFan(); } }
    Processed: 0.011, SQL: 9