什么是io
为什么学习io
java中如何实现io
通过流模型(通过创建输入流,输出流去实现的)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m4WMhyFL-1642513915118)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115094140302.png)]
io的分类
按照流向分(以内存为参数)
按照数据类型分
4个抽象基类
字节输出流:OutputStream
字节输入流:InputStream
字符输出流:Writer
字符输入流:Reader
由这4个抽象基类派生出的子类都已其父类名字作为后缀的
FileOutputStream
FileInputStream
什么时候应该用什么流
一般对于文本数据,采用字符流.
字节流是万能的(在不知道什么样的数据格式的时候)
此抽象类是表示输出字节流的所有类的超类
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oEx2MON1-1642513915121)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115095230662.png)]
成员方法
void | close() 关闭此输出流并释放与此流有关的所有系统资源。 |
---|---|
void | flush() 刷新此输出流并强制写出所有缓冲的输出字节。 |
void | write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。 |
void | write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 |
abstract void | write(int b) 将指定的字节写入此输出流。 |
注意
write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略
文件输出流是用于将数据写入 File
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PJcwX5o0-1642513915123)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115100015525.png)]
构造方法
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 |
---|
FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 |
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。 |
FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流。 |
Demo
/* * FileOutputStream构造方法 * 创建日期:2022/1/15 10:04 * @return void */ @Test public void myTest1() throws FileNotFoundException { // FileOutputStream(File file) File file = new File("a.txt"); FileOutputStream out = new FileOutputStream(file); FileOutputStream outputStream = new FileOutputStream(new File("a.txt")); // FileOUtputStream(String fileName) FileOutputStream outputStream1 = new FileOutputStream("a.txt"); }
成员方法
void | write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。 |
---|---|
void | write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。 |
void | write(int b) 将指定字节写入此文件输出流。 |
Demo
/* * write方法 * 写数据的步骤 * 1.创建字节输出流对象 * 2.写数据 write方法 * 3.close * 创建日期:2022/1/15 10:08 * @return void */ @Test public void myTest2() throws IOException { //System.out.println(System.getProperty("user.dir")); // 创建字节输出流对象 FileOutputStream out = new FileOutputStream("a.txt"); // write // write(int b) //writeSingle(out); // write(byte[] b) String s = "abc"; byte[] bytes = s.getBytes(); //writeMulti(out, bytes); // 此时,文件内容是啥 // 1.aabc 2.abc // write(byte[] b,int off,int len) out.write(bytes, 0, bytes.length); // close out.close(); } private void writeMulti(FileOutputStream out, byte[] bytes) throws IOException { out.write(bytes); } private void writeSingle(FileOutputStream out) throws IOException { out.write(97); }
当我们创建字节输出流的时候,发生了什么?
如果实现文件内容追加?
利用构造方法FileOutputStream(String fileName, boolean append) 把append设置为true
/* * 实现文件追加功能 * 创建日期:2022/1/15 10:45 * @return void */ @Test public void myTest4() throws IOException{ // 创建字节输出流对象 利用带append的构造方法 FileOutputStream out = new FileOutputStream("a.txt", true); // write数据 out.write("abc".getBytes()); // close out.close(); }
如何实现换行功能?
换行符
/* * 实现换行功能 * 创建日期:2022/1/15 10:48 * @return void */ @Test public void myTest5() throws IOException{ // 创建字节输出流对象 FileOutputStream out = new FileOutputStream("a.txt"); // write数据 out.write("abc".getBytes()); // 写入换行符 // "\r\n" out.write("\r\n".getBytes()); out.write("abc".getBytes()); // "\r" out.write("\r".getBytes()); out.write("abc".getBytes()); // "\n" out.write("\n".getBytes()); out.write("abc".getBytes()); // 默认换行符 out.write(System.lineSeparator().getBytes()); out.write("abc".getBytes()); // close out.close(); }
异常处理
try-catch
/* * 异常处理 try-catch * 创建日期:2022/1/15 10:56 * @return void */ @Test public void myTest6(){ // 创建字节输出流对象 FileOutputStream out = null; try { out = new FileOutputStream("a.txt"); // write数据 out.write("abc".getBytes()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { try { // 判断out是否为null if (out != null) { // close out.close(); } } catch (IOException e) { e.printStackTrace(); } } }
try-with-resources
//语法 try(资源,实现了AutoCloseable接口的类){ // 当执行完try中的代码,会自动释放资源 }catch{ }finally{ }
/* * try-with-resources * 创建日期:2022/1/15 11:06 * @return void */ @Test public void myTest7() { try(FileOutputStream out = new FileOutputStream("a.txt")) { // write 数据 out.write("aaa".getBytes()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
证明自动释放
class A implements AutoCloseable{ @Override public void close() throws Exception { System.out.println("close方法执行了!"); } public void func(){ System.out.println("func 执行了!"); } } /* * 证明自动释放资源 * 创建日期:2022/1/15 11:10 * @return void * @author 景天 */ @Test public void myTest8(){ try (A a = new A()){ // 执行func方法 a.func(); } catch (Exception e) { e.printStackTrace(); } }
为什么要close?
该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DQIPNEIt-1642513915126)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117112630374.png)]
构造方法
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。默认缓冲区大小是8KB |
---|
BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。 |
像这种需要底层流作为参数的,叫做包装流
Demo
/* * BufferedOutputSteam 构造方法 * 创建日期:2022/1/17 11:37 */ @Test public void myTest6() throws IOException{ // 更多操作BufferedOutputStream(OutputStream out) // 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。 FileOutputStream out = new FileOutputStream("a.txt"); BufferedOutputStream bo = new BufferedOutputStream(out); BufferedOutputStream bo2 = new BufferedOutputStream(new FileOutputStream( new File("a.txt"))); // BufferedOutputStream(OutputStream out, int size) // 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流。 BufferedOutputStream bo3 = new BufferedOutputStream(new FileOutputStream("a.txt"),1024); }
带缓冲区的输入输出流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W9bUX2LM-1642513915128)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117113628095.png)]
成员方法
3个write方法
/* * BufferedOutputStream write * 创建日期:2022/1/17 11:43 * @return void */ @Test public void myTest7() throws IOException{ // 创建缓冲字节输出流对象 BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("a.txt")); // write方法写数据 // write(int b) bo.write(97); bo.write("\r\n".getBytes()); // write(byte[] b) bo.write("哈哈哈".getBytes()); bo.write(System.lineSeparator().getBytes()); // write(byte[] b, int off ,int len) bo.write("abc".getBytes(), 0, 2); // 执行flush操作 bo.flush(); // close bo.close(); }
注意:
为什么close会执行flush方法?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cFbZ6mJm-1642513915130)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117115120196.png)]
象类是表示字节输入流的所有类的超类
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4plnNwLq-1642513915132)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115111703052.png)]
成员方法
abstract int | read() 从输入流中读取数据的下一个字节。 |
---|---|
int | read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。 |
int | read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。 |
注意事项
FileInputStream
从文件系统中的某个文件中获得输入字节
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yS5wTYiu-1642513915134)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115112628236.png)]
构造方法
FileInputStream(File file) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。 |
---|
FileInputStream(String name) 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。 |
Demo
/* * FileInputStream 构造方法 * 创建日期:2022/1/15 11:27 * @return void */ @Test public void myTest9() throws IOException{ // FileInputStream(File file) FileInputStream in = new FileInputStream(new File("a.txt")); // FileInputStream(String fileName) FileInputStream inputStream = new FileInputStream("a.txt"); }
成员方法
int | read() 从此输入流中读取一个数据字节。 |
---|---|
int | read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 |
int | read(byte[] b, int off, int len) 从此输入流中将最多 len 个字节的数据读入一个 byte 数组中。 |
/* * FileInputStream read方法 * 读取数据 * 1.创建字节输入流对象 * 2.read方法读取数据 * 3.close * 创建日期:2022/1/15 11:30 * @return void */ @Test public void myTest10() throws IOException{ // 创建字节输入流对象 FileInputStream in = new FileInputStream("a.txt"); // read方法读取数据 // read() 读取单个字节,返回值是readData //readSingle(in); // read(byte[] b) // 这个字节数组相当于一个容器 byte[] bytes = new byte[1024]; // readCount代表了读取到的字节的个数 // readMulti(in, bytes); // read(byte[] b,int off , int len) int readCount = in.read(bytes, 1, 3); System.out.println(readCount); System.out.println(new String(bytes,1,readCount)); // close in.close(); } private void readMulti(FileInputStream in, byte[] bytes) throws IOException { int readCount = in.read(bytes); System.out.println("readCount = " + readCount); String s = new String(bytes, 0, readCount); System.out.println(s); } private void readSingle(FileInputStream in) throws IOException { int readData = in.read(); System.out.println(((char) readData)); int readData2 = in.read(); System.out.println(((char) readData2)); int readData3 = in.read(); System.out.println(((char) readData3)); int readData4 = in.read(); System.out.println(readData4); }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRdB0hR2-1642513915135)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220115113722846.png)]
细节
@Test public void myTest1() throws IOException { // 创建1个字节输入流 FileInputStream in = new FileInputStream("a.txt"); // 读取数据 read(byte [] b) byte[] bytes = new byte[4]; int readCount1 = in.read(bytes); System.out.println("readCount1 = " + readCount1); System.out.println(new String(bytes)); // 再读取1次 int readCount2 = in.read(bytes); System.out.println("readCount2 = " + readCount2); System.out.println(new String(bytes,0,readCount2)); // close in.close(); }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hB1S3tKH-1642513915136)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117095929946.png)]
循环读取
/* * 循环读取 * 创建日期:2022/1/17 10:00 * @return void */ @Test public void myTest2() throws IOException{ // 创建字节输入流对象 FileInputStream in = new FileInputStream("a.txt"); // 读取数据 循环读 // 简单方式 // readWhile1(in); // 高阶方式 // 读取单个字节 // 表示读取到的字节值 // readWhile2(in); // 读取多个字节 字节数组方式 // 表示读取到的字节的个数 int readCount; byte[] bytes = new byte[1024]; while ((readCount = in.read(bytes)) != -1) { System.out.println(new String(bytes,0,readCount)); } // close in.close(); } private void readWhile2(FileInputStream in) throws IOException { int readData; while ((readData = in.read()) != -1) { System.out.print(((char) readData)); } } private void readWhile1(FileInputStream in) throws IOException { int readData; while (true) { readData = in.read(); if (readData == -1) { break; } System.out.println(((char) readData)); } }
BufferedInputStream
为另一个输入流添加一些功能
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MISh4SHu-1642513915137)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117142323589.png)]
构造方法
BufferedInputStream(InputStream in) 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 默认缓冲区大小是8KB |
---|
BufferedInputStream(InputStream in, int size) 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 |
/* * BufferedInputStream 构造方法 * 创建日期:2022/1/17 14:25 * @return void */ @Test public void myTest8() throws IOException{ //| BufferedInputStream(InputStream in) // 创建一个 BufferedInputStream // 并保存其参数,即输入流 in,以便将来使用。 | BufferedInputStream bi = new BufferedInputStream( new FileInputStream("a.txt")); //| BufferedInputStream(InputStream in, int size) // 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 | BufferedInputStream bi2 = new BufferedInputStream( new FileInputStream("a.txt"),1024); }
成员方法
3个read方法
/* * BufferedInputStream read * 创建日期:2022/1/17 14:28 * @return void */ @Test public void myTest9() throws IOException{ // 创建输入流对象 BufferedInputStream bi = new BufferedInputStream( new FileInputStream("a.txt")); // read方法 // 读取到的字节值 // read() 单个字节 //readSingle(bi); // read(byte[] b) 字节数组 byte[] bytes = new byte[1024]; //readMulti(bi, bytes); // read(byte[] b, int off ,int len) int readCount = bi.read(bytes, 0, bytes.length); System.out.println(new String(bytes,0,readCount)); // close bi.close(); } private void readMulti(BufferedInputStream bi, byte[] bytes) throws IOException { // 表示读取到的字节个数 int readCount = bi.read(bytes); System.out.println(new String(bytes,0,readCount)); } private void readSingle(BufferedInputStream bi) throws IOException { int readData = bi.read(); System.out.println(readData); }
思路
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KOpOFyzy-1642513915139)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117101602649.png)]
文本文件
/* * 文本文件复制 * 创建日期:2022/1/17 10:16 * @return void */ @Test public void myTest3() throws IOException{ // 创建字节输入流对象 FileInputStream in = new FileInputStream("D:\\a.txt"); //创建字节输出流对象 FileOutputStream out = new FileOutputStream("copy_a.txt"); // 边读边写 判断条件 -1 // 采用单字节的方式 // copy1(in, out); // 字节数组的方式 byte[] bytes = new byte[1024]; // 表示读取到的字节个数 int readCount; while ((readCount = in.read(bytes)) != -1) { // write out.write(bytes, 0, readCount); } // 循环结束 意味着复制完成 // close in.close(); out.close(); } private void copy1(FileInputStream in, FileOutputStream out) throws IOException { // 表示读取到的字节值 int readData; while ((readData = in.read()) != -1) { // 写数据 out.write(readData); } }
图片文件
单字节耗时 177ms
字节数组方式耗时 2ms
视频文件
单字节 耗时: 15379ms
字节数组方式 耗时: 24ms
哪种方式效率更高?
从消耗的时间上看,字节数组的方式效率更高.数组的方式减少了跟操作系统交互
举例:
现在我在京东上买了5个快递,我家离快递站10公里.快递小哥送快递
单字节: 一次送1个快递,跑5次
字节数组: 东哥说了,咱们都是兄弟,给每个兄弟配了宝马.开着宝马送快递,一下送5个快递,跑1次.
缓冲流实现文件复制
/* * 使用缓冲流实现文件复制 * 创建日期:2022/1/17 14:35 * @return void */ @Test public void myTest10() throws IOException{ // 创建缓冲输入流对象 BufferedInputStream in = new BufferedInputStream( new FileInputStream("D:\\aa.mp4")); // 创建缓冲输出流对象 BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream("copy_aa.mp4")); // 边读边写 // 单字节 long start = System.currentTimeMillis(); // copy1(in, out); // 多字节 int readCount; byte[] bytes = new byte[1024]; while ((readCount = in.read(bytes)) != -1) { out.write(bytes, 0, readCount); } long end = System.currentTimeMillis(); System.out.println("耗时: " + (end-start) + "ms"); // close in.close(); out.close(); } private void copy1(BufferedInputStream in, BufferedOutputStream out) throws IOException { int readData; while ((readData = in.read()) != -1) { out.write(readData); } }
/* * 用字节流读取文件内容: * 1.英文 数字 * 2.带有中文的内容 * 创建日期:2022/1/17 15:10 * @return void */ @Test public void myTest1() throws IOException { // 创建输入流对象 FileInputStream in = new FileInputStream("a.txt"); // read方法读取数据 //int readData; //while ((readData = in.read()) != -1) { // // 打印 // System.out.print(((char) readData)); //} // 用字节数组的方式去处理 //int readCount; //byte[] bytes = new byte[11]; //while ((readCount = in.read(bytes)) != -1) { // // System.out.println(new String(bytes,0,readCount)); //} String s = "abc001你好"; byte[] bytes = s.getBytes(); System.out.println(Arrays.toString(bytes)); // close in.close(); }
基于某个编码表,存的时候是这个字符在编码表中所对应的整数值(编码值)
中文编码表 你 0x0001
日文编码表 の 0x0001
ASCII:美国标准信息交换码。
用一个字节的7位可以表示。0000 0000 - 0111 1111
ISO8859-1:拉丁码表。欧洲码表 0000 0000 - 1111 11111
用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。 2个字节表示1个中文字符
GB18030:GBK的取代版本
BIG-5码 :通行于台湾、香港地区的一个繁体字编码方案,俗称“大五码”。
Unicode:国际标准码,融合了多种文字。
UTF-8:可变长度来表示一个字符。
UTF-8不同,它定义了一种“区间规则”,这种规则可以和ASCII编码保持最大程度的兼容:
它将Unicode编码为00000000-0000007F的字符,用单个字节来表示 0111 1111 = 7F
它将Unicode编码为00000080-000007FF的字符用两个字节表示
它将Unicode编码为00000800-0000FFFF的字符用3字节表示
1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx 中文采用的是3个字节表示1个中文字符
utf-16:
jvm使用的编码表,用2个字节来编解码,表示1个字符
char : 2 字节
工作中常用的编码表
ASCII
GBK 2个字节表示1个中文
ISO8859-1 1个字节表示1个字符
utf-8 3个字节表示1个中文
乱码问题
默认的编码表
/* * 默认编码表 * 创建日期:2022/1/17 16:12 * @return void */ @Test public void myTest2() { System.out.println(Charset.defaultCharset()); }
/* * 默认编码表 * 创建日期:2022/1/17 16:12 * @return void */ @Test public void myTest2() { System.out.println(Charset.defaultCharset()); } /* * java中实现编解码 * 创建日期:2022/1/17 16:17 * @return void */ @Test public void myTest3() throws UnsupportedEncodingException { // 定义1个字符串 String s = "你好"; // 编码 // getBytes() // 使用平台的默认字符集将此 String 编码为 byte 序列, // 并将结果存储到一个新的 byte 数组中。 // byte[] getBytes(String charsetName) //使用指定的字符集将此 String 编码为 byte 序列, // 并将结果存储到一个新的 byte 数组中 byte[] encodingGbk = s.getBytes("GBk"); System.out.println(Arrays.toString(encodingGbk)); // 把编码值转化为字符串 解码 // String(byte[] bytes) // 通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。 //String s1 = new String(encodingGbk); //System.out.println(s1); // String(byte[] bytes, String charsetName) // 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String。 String strGbk = new String(encodingGbk, "GBk"); System.out.println(strGbk); }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lla80QXE-1642513915140)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117163914148.png)]
写入字符流的抽象类
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jNRzeXSL-1642513915142)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117170117935.png)]
成员方法
void | write(char[] cbuf) 写入字符数组。 |
---|---|
abstract void | write(char[] cbuf, int off, int len) 写入字符数组的某一部分。 |
void | write(int c) 写入单个字符。 |
void | write(String str) 写入字符串。 |
void | write(String str, int off, int len) 写入字符串的某一部分。 |
注意
写入单个字符。要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略。
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset
将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J5zSrci3-1642513915142)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117170711030.png)]
构造方法
OutputStreamWriter(OutputStream out) 创建使用默认字符编码的 OutputStreamWriter。 |
---|
OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的 OutputStreamWriter。 |
/* * 转换流的构造方法 * 创建日期:2022/1/17 17:09 * @return void */ @Test public void myTest4() throws IOException{ // 更多操作OutputStreamWriter(OutputStream out) // 创建使用默认字符编码的 OutputStreamWriter。 OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("a.txt")); // OutputStreamWriter(OutputStream out, String charsetName) // 创建使用指定字符集的 OutputStreamWriter。 OutputStreamWriter out2 = new OutputStreamWriter(new FileOutputStream("a.txt"), "GBk"); }
成员方法
void | write(char[] cbuf) 写入字符数组。 |
---|---|
abstract void | write(char[] cbuf, int off, int len) 写入字符数组的某一部分。 |
void | write(int c) 写入单个字符。 |
void | write(String str) 写入字符串。 |
void | write(String str, int off, int len) 写入字符串的某一部分。 |
/* * OutputStreamWriter 写数据 * 创建日期:2022/1/17 17:11 * @return void */ @Test public void myTest5() throws IOException{ // 创建输出流对象 OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("a.txt")); String s = "我变强了,也变秃了"; char[] chars = s.toCharArray(); // write方法写数据 // write(int c) 写入单个字符 // writeSingle(out, chars); // write(char[] c) 写入字符数组 out.write(chars); out.write(System.lineSeparator()); // write(char[] c,int off ,int len ) 写入字符数组部分 out.write(chars, 0, 4); out.write(System.lineSeparator()); // write(String s) 直接写字符串 out.write("嘤嘤嘤,小拳拳捶你胸口"); out.write(System.lineSeparator()); // write(String s, int off , int len)直接写字符串 out.write("我是一朵带刺的玫瑰",0,6); // flush out.flush(); // close out.close(); } private void writeSingle(OutputStreamWriter out, char[] chars) throws IOException { for (int i = 0; i < chars.length; i++) { out.write(chars[i]); } }
用来写入字符文件的便捷类
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nkcaZBnn-1642513915145)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118100030850.png)]
构造方法
FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象。 |
---|
FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。 |
FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。 |
FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。 |
/* * FileWriter 构造方法 * 创建日期:2022/1/18 10:02 * @return void */ @Test public void myTest2() throws IOException{ FileWriter fileWriter = new FileWriter(new File("a.txt")); FileWriter fileWriter1 = new FileWriter("a.txt"); FileWriter fileWriter2 = new FileWriter("a.txt",true); }
成员方法
5个write 3 + 2
/* * FileWriter 写数据 * 创建日期:2022/1/18 10:05 * @return void */ @Test public void myTest3() throws IOException{ // 创建输出流对象 FileWriter fileWriter = new FileWriter("a.txt"); // write方法写数据 // write(int c) // write(char [] c) // write(char[] c , int off ,int len) // write(String str) // write(String str, int off ,int len) fileWriter.write("宝,我今天输液了,什么夜,想你的夜"); // flush fileWriter.flush(); // close fileWriter.close(); }
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SnJcRwZq-1642513915147)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118105329370.png)]
构造方法
BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。默认缓冲区大小16KB |
---|
BufferedWriter(Writer out, int sz) 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。 |
@Test public void myTest6() throws IOException { //| BufferedWriter(Writer out) // 创建一个使用默认大小输出缓冲区的缓冲字符输出流。默认缓冲区大小16KB | BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("a.txt"))); BufferedWriter bw2 = new BufferedWriter(new FileWriter("a.txt")); //| BufferedWriter(Writer out, int sz) // 创建一个使用给定大小输出缓冲区的新缓冲字符输出流。 | BufferedWriter bw3 = new BufferedWriter(new FileWriter("a.txt"), 1024); }
成员方法
5个write方法 3 +2
独有的方法
void | newLine() 写入一个行分隔符。 |
---|---|
/* * BufferedWriter 方法 * 创建日期:2022/1/18 11:12 * @return void */ @Test public void myTest7() throws IOException{ // 创建输出流对象 BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt")); // write方法写数据 bw.write("哈哈哈哈哈"); // 独有的方法 newLine() bw.newLine(); bw.write("呵呵呵呵呵"); // flush bw.flush(); // close bw.close(); }
用于读取字符流的抽象类
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bvbuvLSM-1642513915148)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117172439471.png)]
成员方法
int | read() 读取单个字符。 |
---|---|
int | read(char[] cbuf) 将字符读入数组。 |
abstract int | read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。 |
注意
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset
读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ndgFl8o-1642513915150)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220117173045555.png)]
构造方法
InputStreamReader(InputStream in) 创建一个使用默认字符集的 InputStreamReader。 |
---|
InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的 InputStreamReader。 |
/* * InputStreamReader 构造方法 * 创建日期:2022/1/17 17:32 * @return void */ @Test public void myTest6() throws IOException{ //| InputStreamReader(InputStream in) // 创建一个使用默认字符集的 InputStreamReader。 | InputStreamReader in = new InputStreamReader(new FileInputStream("a.txt")); //| InputStreamReader(InputStream in, String charsetName) // 创建使用指定字符集的 InputStreamReader。 | InputStreamReader in2 = new InputStreamReader(new FileInputStream("a.txt"), "utf-8"); }
成员方法
int | read() 读取单个字符。 |
---|---|
int | read(char[] cbuf) 将字符读入数组。 |
abstract int | read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。 |
/* * InputStreamRead 读取数据 * 创建日期:2022/1/17 17:34 * @return void */ @Test public void myTest7() throws IOException{ // 创建输入流对象 InputStreamReader in = new InputStreamReader(new FileInputStream("a.txt")); // read方法读取数据 // read() 读取单个字符 // 代表了读取到的字符值 // readSingle(in); // read(char []) char[] chars = new char[1024]; // readMulti(in, chars); // read(char [], int off ,int len) in.read(chars, 1, 10); // close in.close(); } private void readMulti(InputStreamReader in, char[] chars) throws IOException { // 表示的是读取到的字符的个数 int readCount = in.read(chars); System.out.println(new String(chars,0,readCount)); } private void readSingle(InputStreamReader in) throws IOException { int readData = in.read(); System.out.println(((char) readData)); }
使用指定字符集
@Test public void myTest8() throws IOException{ // 读取gbk编码的数据 // 创建输入流对象 InputStreamReader in = new InputStreamReader(new FileInputStream("b.txt"),"gbk"); // read char[] chars = new char[1024]; int readCount = in.read(chars); System.out.println(new String(chars,0,readCount)); // close in.close(); }
用来读取字符文件的便捷类
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qrzkp0hY-1642513915151)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118101015508.png)]
构造方法
FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。 |
---|
FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader。 |
成员方法
3个read方法
/* * FileReader 读取数据 * 创建日期:2022/1/18 10:11 * @return void */ @Test public void myTest4() throws IOException{ // 创建输入流对象 FileReader reader = new FileReader("a.txt"); // read() //readSingle(reader); // read(char[] c) char[] chars = new char[1024]; //readMulti(reader, chars); // read(char[] c, int off ,int len) int readCount = reader.read(chars, 1, 10); // close reader.close(); } private void readMulti(FileReader reader, char[] chars) throws IOException { int readCount = reader.read(chars); System.out.println(new String(chars,0,readCount)); } private void readSingle(FileReader reader) throws IOException { // 代表读取的字符值 int readData = reader.read(); System.out.println(((char) readData)); }
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oeGs2ARp-1642513915151)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118111721721.png)]
构造方法
BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。默认缓冲区16KB |
---|
BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流。 |
成员方法
3个read方法
String | readLine() 读取一个文本行 |
---|---|
包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null |
/* * BufferedReader 方法 * 创建日期:2022/1/18 11:21 * @return void */ @Test public void myTest8() throws IOException { // 创建输入流对象那个 BufferedReader br = new BufferedReader(new FileReader("a.txt")); // read读取数据 //readSingle2(br); // readMulti2(br); // 自己独有的方法readLine() 一次读一行数据 //String s = br.readLine(); //System.out.println(s); //String s2 = br.readLine(); //System.out.println(s2); //String s3 = br.readLine(); //System.out.println(s3); // readLine循环读取数据 String line; while ((line = br.readLine()) != null) { System.out.println(line); } // close br.close(); } private void readMulti2(BufferedReader br) throws IOException { char[] chars = new char[1024]; int readCount = br.read(chars); System.out.println(new String(chars,0,readCount)); } private void readSingle2(BufferedReader br) throws IOException { int readData = br.read(); System.out.println(((char) readData)); }
文本文件 : 没有问题
非文本文件: 有问题
所以用的时候字符流只针对文本文件
/* * 字符流复制文件 * 创建日期:2022/1/18 9:48 * @return void */ @Test public void myTest1() throws IOException { // 文本文件 // 创建输入流对象 InputStreamReader in = new InputStreamReader(new FileInputStream("D:\\aa.mp4")); // 创建输出流对象 OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("copy_aa.mp4")); // 边读边写 char[] chars = new char[1024]; int readCount; while ((readCount = in.read(chars)) != -1) { out.write(chars, 0, readCount); } // flush out.flush(); // close out.close(); in.close(); }
字节流向文件中写个1000, 写个3.14
@Test public void myTest1() throws IOException { // 创建输出流对象 FileOutputStream out = new FileOutputStream("b.txt"); // write方法写数据 //out.write(1000); //out.write(3.14); // close out.close(); }
数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XXUSXrHw-1642513915152)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118143607610.png)]
构造方法
DataOutputStream(OutputStream out) 创建一个新的数据输出流,将数据写入指定基础输出流。
成员方法
每一种java基本数据类型都有1个write方法与之对应
比如 writeInt(int i)…
/* * 向文件中写入整数1000 * 创建日期:2022/1/18 14:38 * @return void */ @Test public void myTest2() throws IOException{ // writeData(); // 使用数据输入流去读取 // 创建输入流对象 DataInputStream in = new DataInputStream(new FileInputStream("b.txt")); // readInt() readDouble() int i = in.readInt(); System.out.println("i = " + i); double v = in.readDouble(); System.out.println("v = " + v); // close in.close(); } private void writeData() throws IOException { // DataOutputStream(OutputStream out) // 创建一个新的数据输出流,将数据写入指定基础输出流。 // 创建输出流对象 DataOutputStream out = new DataOutputStream(new FileOutputStream("b.txt")); // writeInt out.writeInt(1000); out.writeDouble(3.14); // close out.close(); }
public static void main(String[] args) throws IOException { write(); read(); } private static void read() throws FileNotFoundException, IOException { DataInputStream dis = new DataInputStream( new FileInputStream("dos.txt")); byte b = dis.readByte(); System.out.println(b); short s = dis.readShort(); System.out.println(s); int i = dis.readInt(); System.out.println(i); long l = dis.readLong(); System.out.println(l); float f = dis.readFloat(); System.out.println(f); double d = dis.readDouble(); System.out.println(d); char ch = dis.readChar(); System.out.println(ch); boolean bb = dis.readBoolean(); System.out.println(bb); dis.close(); } private static void write() throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream( "dos.txt")); dos.writeByte(1); dos.writeShort(20); dos.writeInt(300); dos.writeLong(4000); dos.writeFloat(12.34f); dos.writeDouble(12.56); dos.writeChar('a'); dos.writeBoolean(true); dos.close(); }
数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aSuRtP5u-1642513915154)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118144425838.png)]
构造方法
DataInputStream(InputStream in) 使用指定的底层 InputStream 创建一个 DataInputStream。
成员方法
每一个java基本数据类型都有1个与之相对应的read方法
比如
readInt()…
注意
按照怎么样的方式去写, 就要按照相同的方式去读取数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-In5R4gbx-1642513915155)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118145528223.png)]
打印流的核心思想
练习:
定义1个Printer类
定义4个方法
成员变量
package com.cskaoyan._02otherstream; import java.io.IOException; import java.io.OutputStream; /** * @description: * @date: 2022/1/18 15:12 **/ /* 需求: 定义1个Printer类 定义4个方法 - printInt(int i) 专门打印int类型的数据,输出到文件中 - printIntLn(int i) 专门打印int类型的数据,输出到文件中,并且换行 - printDouble(double d) 专门打印double类型的数据,输出到文件中 - printDoubleLn(double d) 专门打印double类型的数据,输出到文件中,并且换行 成员变量 - 输出流对象 */ public class Printer { // 定义成员变量 OutputStream out; public Printer(OutputStream out) { this.out = out; } // 定义成员方法 // - printInt(int i) 专门打印int类型的数据,输出到文件中 public void printInt(int i) throws IOException { String s = String.valueOf(i); out.write(s.getBytes()); } //printIntLn(int i) 专门打印int类型的数据,输出到文件中,并且换行 public void printIntLn(int i) throws IOException { String s = String.valueOf(i); out.write(s.getBytes()); out.write(System.lineSeparator().getBytes()); } // - printDouble(double d) 专门打印double类型的数据,输出到文件中 public void printDouble(double d) throws IOException{ String s = String.valueOf(d); out.write(s.getBytes()); } // - printDoubleLn(double d) 专门打印double类型的数据,输出到文件中,并且换行 public void printDoubleLn(double d) throws IOException{ String s = String.valueOf(d); out.write(s.getBytes()); out.write(System.lineSeparator().getBytes()); } // close 关闭资源 public void close() throws IOException { out.close(); } } /* * Printer 测试 * 创建日期:2022/1/18 15:22 * @return void * @author 景天 */ @Test public void myTest3() throws IOException{ // 创建Printer对象 Printer printer = new Printer(new FileOutputStream("a.txt")); // 调用Printer方法 // printInt printer.printIntLn(999); // printDouble printer.printDouble(6.28); // close 调用Printer的close printer.close(); }
PrintStream
为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CUB7ZcFJ-1642513915156)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118150102139.png)]
构造方法
PrintStream(File file) 创建具有指定文件且不带自动行刷新的新打印流。 |
---|
PrintStream(OutputStream out) 创建新的打印流。 |
PrintStream(OutputStream out, boolean autoFlush) 创建新的打印流。 |
PrintStream(String fileName) 创建具有指定文件名称且不带自动行刷新的新打印流。 |
成员方法
每一个java基本数据类型都有1个与之相对应的print方法
比如: print(int i)
print(double d)…
向文本输出流打印对象的格式化表示形式
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q3dUsYx5-1642513915157)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118150610615.png)]
构造方法
PrintWriter(File file) 使用指定文件创建不具有自动行刷新的新 PrintWriter。 |
---|
PrintWriter(OutputStream out) 根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。 |
PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter。 |
PrintWriter(String fileName) 创建具有指定文件名称且不带自动行刷新的新 PrintWriter。 |
PrintWriter(Writer out) 创建不带自动行刷新的新 PrintWriter。 |
PrintWriter(Writer out, boolean autoFlush) 创建新 PrintWriter。 |
成员方法
每一个java基本数据类型都有1个与之相对应的print方法
比如: print(int i)
print(double d)…
打印流的特点
标准输入流
标准输出流
练习:
利用System.in 完成Scanner的nextLine()的功能。
分析:
nextLine() 接收键盘输入 一行字符串
System.in 是1个普通字节输入流
想到BufferedReader当中的readLine()
/* *利用System.in 完成Scanner的nextLine()的功能。 分析: nextLine() 接收键盘输入 一行字符串 System.in 是1个普通字节输入流 想到BufferedReader当中的readLine() * 创建日期:2022/1/18 16:12 * @return void */ @Test public void myTest6() throws IOException{ // 创建BufferedReader对象 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 完成Scanner的nextLine() // readLine() // readOneLine(br); // 实现多次输入 // 当我们输入的值是 gun 终止程序结束 String line; while ((line = br.readLine()) != null) { if ("gun".equals(line)) { break; } System.out.println(line); } br.close(); } private void readOneLine(BufferedReader br) throws IOException { System.out.println("before"); String s = br.readLine(); System.out.println("after"); System.out.println(s); }
为什么有?
Student s = new Student("zs",20)
序列化
把对象数据转化为二进制数据,持久化保存
反序列化
把二进制数据还原回对象数据
ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储
只能将支持 java.io.Serializable 接口的对象写入流中。每个 serializable 对象的类都被编码
writeObject 方法用于将对象写入流中。所有对象(包括 String 和数组)都可以通过 writeObject 写入。可将多个对象或基元写入流中。必须使用与写入对象时相同的类型和顺序从相应 ObjectInputstream 中读回对象。
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TmnHTRI5-1642513915160)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118164212189.png)]
构造方法
ObjectOutputStream(OutputStream out) 创建写入指定 OutputStream 的 ObjectOutputStream。
成员方法
void | writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。 |
---|---|
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化
继承关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m1JosnLq-1642513915162)(https://gitee.com/uncleTao/picture-bed/raw/master/img/image-20220118164300414.png)]
构造方法
ObjectInputStream(InputStream in) 创建从指定 InputStream 读取的 ObjectInputStream。
成员方法
Object | readObject() 从 ObjectInputStream 读取对象 |
---|---|
/* * 序列化 反序列化 * 创建日期:2022/1/18 16:34 * @return void */ @Test public void myTest7() throws IOException, ClassNotFoundException { // 序列化操作 // writeObj(); // 反序列化操作 // 创建输入流对象 ObjectInputStream in = new ObjectInputStream(new FileInputStream("b.txt")); // readObject() Object object = in.readObject(); System.out.println(object); // close in.close(); } private void writeObj() throws IOException { // 创建输出流对象 ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("b.txt")); // 创建1个学生对象 Student student = new Student("张三", 20); // writeObject(Object o) out.writeObject(student); // close out.close(); }
注意事项
类型 | 字节输出流 | 字节输入流 | 字符输出流 | 字符输入流 |
---|---|---|---|---|
抽象基类 | OutputStream | InputStream | Writer | Reader |
文件相关 | FileOutputStream | FileInputStream | FileWriter | FileReader |
缓冲相关 | BufferedOutputStream | BufferedInputStream | BufferedWriter | BufferedReader |
转换想关 | OutputStreamWriter | InputStreamReader | ||
数据相关 | DataOutputStream | DataInputStream | ||
打印相关 | PrintStream | PrintWriter | ||
对象相关 | ObjectOutputStream | ObjectInputStream |