Day24
字符流
应用场景:处理纯文本数据
abstract class Reader -- 字符输入流(字符流的基类)abstract class Writer -- 字符输出流(字符流的基类)
class InputStreamReader extends Reader -- 字符输入转换流(将字节流转换为字符流)class OutputStreamWriter extends Writer -- 字符输出转换流(将字节流转换为字符流)
注意:
- 将字节流转换为字符流,用于传输文本数据
- 字符流要加上编码格式,防止乱码
- 字符流底层是字节流+编码器
class FileReader extends InputStreamReader -- 文件字符输入流class FileWriter extends OutputStreamWriter -- 文件字符输出流
class BufferedReader extends Reader -- 带缓冲区的字符输入流class BufferedWriter extends Writer -- 带缓冲区的字符输出流
缓冲区大小:8192字符 -- new char[8192]
使用:当需要将字节文件转换为字符的时候,用OutputStreamReader和OutputStreamWriter,或以OutputStreamReader和OutputStreamWriter为参数的BufferedWriter和BufferedReader;
当使用平台默认字符编码,处理小文件或对性能要求不高的场景需要从文件里读取和获取字符内容时,用以FileWriter和FileReader作为参数的BufferedWriter和BufferedReader。
java//文件字节输出流 -> 字符输出转换流 -> 带缓冲区的字符输出流 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("123.txt", true))); //文件字符输出转换流 -> 带缓冲区的字符输出流 BufferedWriter bw = new BufferedWriter(new FileWriter("123.txt"));
Reader InputStreamReader FileReader Writer OutputStreamWriter FileWriter BufferedReader BufferedWriter
字符输出转换流 与 字符输入转换流
知识点:利用 字符输出转换流 向文件写入数据
1)不处理异常的情况
2)文件存在的情况
javapublic static void main(String[] args) throws IOException { //1.创建流对象 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("hhy.txt")); //1.创建流对象 + 在末尾追加 + 使用默认编码格式 //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("hhy.txt",true)); //1.创建流对象 + 在末尾追加 + 使用指定编码格式 //OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("hhy.txt",true),Charset.forName("GBK")); // OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("hhy.txt",true),"UTF-8"); //2.写入数据 //osw.write(97);//写入Unicode码 //char[] cs = {'1','2','3','a','b','c','木','头','人'}; //osw.write(cs);//写入字符数组 //osw.write(cs, 3, 3);//写入字符数组,偏移量,写入长度 String str = "123abc木头人"; osw.write(str);//写入字符串 //osw.write(str, 3, 3);//写入字符串,偏移量,写入长度 //3.关闭资源 osw.close(); }
3)文件不存在的情况
经验:所有的输出流,当文件不存在时,都会创建文件,再写入数据。
4)处理异常的情况
javapublic static void main(String[] args) { OutputStreamWriter osw = null; try { //1.创建流对象 + 在末尾追加 + 使用指定编码格式 osw = new OutputStreamWriter(new FileOutputStream("hhy.txt",true),"GBK"); //2.写入数据 osw.write("123abc木头人"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { //3.关闭资源 if(osw != null){ try { osw.close(); } catch (IOException e) { e.printStackTrace(); } } } }
知识点:利用 字符输入转换流 读取文件里的数据
1)不处理异常的情况
2)文件存在的情况
javapublic static void main(String[] args) throws IOException { //1.创建流对象 InputStreamReader isr = new InputStreamReader(new FileInputStream("hhy.txt")); //2.读取数据 //read():读取字符的Unicode码,读取到文件末尾就返回-1 int read; while((read = isr.read()) != -1){ System.out.println((char)read); } //3.关闭资源 isr.close(); }
3)文件不存在的情况
经验:
所有的输出流,当文件不存在时,都会创建文件,再写入数据
所有的输入流,当文件不存在时,都会报错 - FileNotFoundException
javapublic static void main(String[] args) throws IOException { //1.创建流对象 + 使用默认的编码格式 // InputStreamReader isr = new InputStreamReader(new FileInputStream("hhy.txt")); //1.创建流对象 + 使用自定义的编码格式 // InputStreamReader isr = new InputStreamReader(new FileInputStream("hhy.txt"),Charset.forName("GBK")); InputStreamReader isr = new InputStreamReader(new FileInputStream("hhy.txt"),"GBK"); //2.读取数据 //isr.read(cs):读取cs数组长度的数据,并把数据存入到数组中,返回有效字节数,读取到文件末尾则返回-1 char[] cs = new char[1024]; int len; while((len = isr.read(cs)) != -1){ System.out.println(new String(cs, 0, len)); } //3.关闭资源 isr.close(); }
4)处理异常的情况
javapublic static void main(String[] args){ InputStreamReader isr = null; try { //1.创建流对象 + 使用自定义的编码格式 isr = new InputStreamReader(new FileInputStream("hhy.txt"),"GBK"); //2.读取数据 //isr.read(cs):读取cs数组长度的数据,并把数据存入到数组中,返回有效字节数,读取到文件末尾则返回-1 char[] cs = new char[1024]; int len; while((len = isr.read(cs)) != -1){ System.out.println(new String(cs, 0, len)); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { //3.关闭资源 if(isr != null){ try { isr.close(); } catch (IOException e) { e.printStackTrace(); } } } }
文件字符输出流 与 文件字符输入流
知识点:利用 文件字符输出流 向文件写入数据
javapublic static void main(String[] args) throws IOException { //1.创建流对象 //FileWriter fw = new FileWriter("hhy.txt"); //1.创建流对象 + 在文件末尾追加 FileWriter fw = new FileWriter("hhy.txt",true); //2.写入数据 fw.write("123abc木头人"); //3.关闭资源 fw.close(); }
知识点:利用 文件字符输入流 读取文件里的数据
javapublic static void main(String[] args) throws IOException { //1.创建流对象 FileReader fr = new FileReader("hhy.txt"); //2.读取数据 char[] cs = new char[1024]; int len; while((len = fr.read(cs)) != -1){ System.out.println(new String(cs, 0, len)); } //3.关闭资源 fr.close(); }
拷贝:
javapublic class Copy { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("小说.txt"); FileWriter fw = new FileWriter("copy.txt"); char[] cs = new char[1024]; int len; while((len = fr.read(cs)) != -1){ fw.write(cs, 0, len); } fr.close(); fw.close(); } }
带缓冲区的字符输出流 与 带缓冲区的字符输入流
知识点:利用 带缓冲区的字符输出流 向文件写入数据
javapublic static void main(String[] args) throws IOException { //1.创建流对象(文件字节输出流 -> 字符输出转换流 -> 带缓冲区的字符输出流) //BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("hhy.txt"), "GBK")); //1.创建流对象(文件字节输出流 -> 字符输出转换流 -> 带缓冲区的字符输出流) + 末尾追加 //BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("hhy.txt",true), "GBK")); //1.创建流对象(文件字符输出流 -> 带缓冲区的字符输出流) //BufferedWriter bw = new BufferedWriter(new FileWriter("hhy.txt")); //1.创建流对象(文件字符输出流 -> 带缓冲区的字符输出流) + 末尾追加 BufferedWriter bw = new BufferedWriter(new FileWriter("hhy.txt",true)); //2.写入数据 bw.write("123abc木头人"); //3.关闭资源 bw.close(); }
知识点:利用 带缓冲区的字符输入流 读取文件里的数据
javapublic static void main(String[] args) throws IOException { //1.创建流对象(文件字节输入流 -> 字符输入转换流 -> 带缓冲区的字符输入流) //BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("hhy.txt"), "GBK")); //1.创建流对象(文件字符输入流 -> 带缓冲区的字符输入流) BufferedReader br = new BufferedReader(new FileReader("hhy.txt")); //2.读取数据 char[] cs = new char[1024]; int len; while((len = br.read(cs)) != -1){ System.out.println(new String(cs, 0, len)); } //3.关闭资源 br.close(); }
拷贝:
全文
javapublic class Copy01 { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("小说.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("copy.txt")); char[] cs = new char[1024]; int len; while((len = br.read(cs)) != -1){ bw.write(cs, 0, len); } br.close(); bw.close(); } }
分行:
javapublic static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("小说.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("copy.txt")); //readLine()读取一行数据 boolean flag = false; String readLine; while((readLine = br.readLine()) != null){ if(flag){ bw.newLine();//换行 } bw.write(readLine); flag = true; } br.close(); bw.close(); }
对象流
理解:将对象写入到文件,将文件里的对象读取到程序中
class ObjectInputStream -- 对象输入流class ObjectOutputStream -- 对象输出流
序列化/钝化:程序里的对象 写入到 文件中反序列化/活化:文件中的对象 读取到 程序中
注意:
- 对象所属的类必须实现序列化接口 - Serializable
- Serializable接口没有任何抽象方法
- 没有任何抽象方法的接口叫做标记型接口
- Serializable的实现类必须添加序列化ID - serialVersionUID
- transient修饰的成员属性,该属性不会随着对象写入到文件中
- 静态属性不会随着对象写入到文件中,因为静态属性不属于对象
知识点:利用 对象输出流 向文件写入数据
javapublic static void main(String[] args) throws FileNotFoundException, IOException { //1.创建流对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hhy.txt")); //2.写入数据 oos.writeInt(100);//写入int类型的数据 oos.writeDouble(123.123);//写入double类型的数据 oos.writeUTF("用良心做教育");//写入UTF-8编码格式的字符串类型的数据 oos.writeObject(new Date());//写入对象类型的数据 //3.关闭资源 oos.close(); }
知识点:利用 对象输入流 读取文件里的数据
javapublic static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { //1.创建流对象 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hhy.txt")); //2.写入数据(注意:读取顺序必须和写入顺序一致) int readInt = ois.readInt(); double readDouble = ois.readDouble(); String readUTF = ois.readUTF(); Date date = (Date) ois.readObject(); System.out.println(readInt); System.out.println(readDouble); System.out.println(readUTF); System.out.println(date); //3.关闭资源 ois.close(); }
知识点:利用 对象输出流 向文件写入自定义对象
javaimport java.io.Serializable; public class User implements Serializable{ private static final long serialVersionUID = 8798250558176997713L; private String username; private transient String password; private String nickName; private String role; private double hp; private double mp; public User() { } public User(String username, String password, String nickName, String role, double hp, double mp) { this.username = username; this.password = password; this.nickName = nickName; this.role = role; this.hp = hp; this.mp = mp; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } public double getHp() { return hp; } public void setHp(double hp) { this.hp = hp; } public double getMp() { return mp; } public void setMp(double mp) { this.mp = mp; } @Override public String toString() { return "User [username=" + username + ", password=" + password + ", nickName=" + nickName + ", role=" + role + ", hp=" + hp + ", mp=" + mp + "]"; } }
javapublic static void main(String[] args) throws FileNotFoundException, IOException { //1.创建流对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hhy.txt")); //2.写入数据 oos.writeObject(new User("1111111179", "123123", "撕裂的忧伤", "艾瑞莉娅", 1200, 800)); oos.writeObject(new User("2333333330", "321321", "沙漠野猪", "DJ", 1000, 1000)); oos.writeObject(new User("1234532143", "123456", "玛卡巴卡", "元歌", 800, 1200)); //3.关闭资源 oos.close(); }
知识点:利用 对象输入流 读取文件里的自定义对象
javapublic static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException { //1.创建流对象 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hhy.txt")); //2.写入数据(注意:读取顺序必须和写入顺序一致) try { User user; while((user = (User) ois.readObject()) != null){ System.out.println(user); } } catch (EOFException e) { } //3.关闭资源 ois.close(); }
内存流
理解:以前我们学习的流是内存(程序)到硬盘(文件)的通道,内存流是程序到内存的通道。内存流是将数据存储到内存里,所以他是非数据持久化
class ByteArrayInputStream -- 内存输入流class ByteArrayOutputStream -- 内存输出流
注意:内存流是程序到内存的通道,是关闭不掉的
知识点:内存输出流
javapublic static void main(String[] args) throws IOException { //1.创建流对象 ByteArrayOutputStream baos = new ByteArrayOutputStream(); //关闭资源(注意:内存流是程序到内存的通道,是关闭不掉的) baos.close(); //2.写入数据 baos.write("123abc木头人".getBytes()); //获取数据 byte[] byteArray = baos.toByteArray(); System.out.println(new String(byteArray)); String str = baos.toString(); System.out.println(str); }
知识点:内存输入流
javapublic static void main(String[] args) throws IOException { //1.创建流对象 ByteArrayInputStream bais = new ByteArrayInputStream("123abc木头人".getBytes()); //关闭资源(注意:内存流是程序到内存的通道,是关闭不掉的) bais.close(); //2.读取数据 byte[] bs = new byte[1024]; int len; while((len = bais.read(bs)) != -1){ System.out.println(new String(bs,0,len)); } }
打印流
理解:打印流是程序到文件,只有一个方向
class PrintStream -- 字节打印流class PrintWriter -- 字符打印流(底层是由字节打印流实现的)
PrintStream vs PrintWriterPrintStream:可以将字节流转换为字节打印流
PrintWriter :可以将字节流、字符流转换为字符打印流
知识点:字节打印流
javapublic static void main(String[] args) throws FileNotFoundException { //1.创建流对象 //PrintStream ps = new PrintStream("hhy.txt"); //1.创建流对象(将字节流转换为字节打印流) //PrintStream ps = new PrintStream(new FileOutputStream("hhy.txt")); //1.创建流对象(将字节流转换为字节打印流) + 末尾追加 PrintStream ps = new PrintStream(new FileOutputStream("hhy.txt", true)); //2.写入数据 ps.println("用良心做教育"); //3.关闭资源 ps.close(); }
知识点:字符打印流
javapublic static void main(String[] args) throws IOException { //1.创建流对象 //PrintWriter pw = new PrintWriter("hhy.txt"); //1.创建流对象(将字节流转换为字符打印流) //PrintWriter pw = new PrintWriter(new FileOutputStream("hhy.txt")); //1.创建流对象(将字节流转换为字符打印流) + 末尾追加 //PrintWriter pw = new PrintWriter(new FileOutputStream("hhy.txt", true)); //1.创建流对象(将字符流转换为字符打印流) //PrintWriter pw = new PrintWriter(new FileWriter("hhy.txt")); //1.创建流对象(将字符流转换为字符打印流) + 末尾追加 PrintWriter pw = new PrintWriter(new FileWriter("hhy.txt",true)); //2.写入数据 pw.println("用良心做教育"); //3.关闭资源 pw.close(); }
重定向
重定向
System.setIn(new FileInputStream("hhy.txt")); -> 重定向后(方向:文件->程序)
InputStream in = System.in; -> 系统标准的输入流(方向:控制台->程序)
System.setOut(new PrintStream("hhy.txt"));->重定向后(方向:程序->文件)
PrintStream ps = System.out; -> 系统标准的输出流(方向:程序->控制台)
System.setErr(new PrintStream("hhy.txt"));->重定向后(方向:程序->文件)
PrintStream ps = System.err; -> 系统标准的错误输出流(方向:程序->控制台)
javapublic static void main(String[] args) throws FileNotFoundException { //重定向后(方向:文件->程序) System.setIn(new FileInputStream("hhy.txt")); //系统标准的输入流(方向:控制台->程序) InputStream in = System.in; Scanner scan = new Scanner(in); String string = scan.next();//不是从控制台输入,而是从文件中读取 System.out.println(string); scan.close(); }
javapublic static void main(String[] args) throws FileNotFoundException { //重定向后(方向:程序->文件) System.setOut(new PrintStream(new FileOutputStream("hhy.txt", true))); //系统标准的输出流(方向:程序->控制台) PrintStream ps = System.out; ps.println("用良心做教育"); }
javapublic static void main(String[] args) throws FileNotFoundException { //重定向后(方向:程序->文件) System.setErr(new PrintStream(new FileOutputStream("hhy.txt", true))); //系统标准的错误输出流(方向:程序->控制台) PrintStream ps = System.err; ps.println("用良心做教育"); }
随机访问流
理解:该流认为文件是一个大型的byte数组,该流有一个隐藏的指针(默认为0),可以从指针开始读取或写入(该流有两个方向),模式r为读,模式rw为写。可以设置指针的位置。
知识点:利用 随机访问流 将数据写入到文件
1)写入数字、英文、中文
javapublic static void main(String[] args) throws IOException { //1.创建流对象 RandomAccessFile w = new RandomAccessFile("hhy.txt", "rw"); //2.写入数据 w.write("123abc木头人".getBytes()); //3.关闭资源 w.close(); }
2)在文件末尾追加
javapublic static void main(String[] args) throws IOException { //1.创建流对象 File file = new File("hhy.txt"); RandomAccessFile w = new RandomAccessFile(file, "rw"); //设置指针 w.seek(file.length()); //2.写入数据 w.write("123abc木头人".getBytes()); //3.关闭资源 w.close(); }
知识点:利用 随机访问流 读取文件里的数据
1)读取数据
javapublic static void main(String[] args) throws IOException { //1.创建流对象 RandomAccessFile r = new RandomAccessFile("hhy.txt", "r"); //2.读取数据 byte[] bs = new byte[1024]; int len; while((len = r.read(bs)) != -1){ System.out.println(new String(bs, 0, len)); } //3.关闭资源 r.close(); }
2)从英文处开始读取
javapublic static void main(String[] args) throws IOException { //1.创建流对象 RandomAccessFile r = new RandomAccessFile("hhy.txt", "r"); //设置指针 r.seek(3); //2.读取数据 byte[] bs = new byte[1024]; int len; while((len = r.read(bs)) != -1){ System.out.println(new String(bs, 0, len)); } //3.关闭资源 r.close(); }
知识点:拷贝文件 -- 断点续传
javapublic static void main(String[] args) throws IOException { RandomAccessFile r = new RandomAccessFile("源文件.mp4", "r"); File targetFile = new File("copy.mp4"); RandomAccessFile w = new RandomAccessFile(targetFile, "rw"); //设置指针 -- 断点续传 long length = targetFile.length(); r.seek(length); w.seek(length); byte[] bs = new byte[1024]; int len; while((len = r.read(bs)) != -1){ w.write(bs, 0, len); } r.close(); w.close(); }
提升方向:
BIO(目前学习的) -> NIO -> AIO