io概述(掌握)
什么是io
- input 输入
- output 输出
为什么学习io
- 在操作系统中,数据想要存储都是以文件的形式进行存储到外部设备
- 内存有限,需要跟外部设备有交互
java中如何实现io
通过流模型(通过创建输入流,输出流去实现的)
io的分类
按照流向分(以内存为参数)
- 输入流 :外设→内存
- 输出流: 内存→外设
按照数据类型分
- 字节流: 一连串的01二进制数据,0000 0000 , 单位是字节 1B
- 字符流:一连串的字符序列(理解为一种文化符号,你好,abc,の)
4个抽象基类
字节输出流:OutputStream
字节输入流:InputStream
字符输出流:Writer
字符输入流:Reader
由这4个抽象基类派生出的子类都已其父类名字作为后缀的
FileOutputStream
FileInputStream
什么时候应该用什么流
一般对于文本数据,采用字符流.
字节流是万能的(在不知道什么样的数据格式的时候)
字节流(重点)
字节输出流
抽象基类OutputStream
此抽象类是表示输出字节流的所有类的超类
继承关系
成员方法
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 个高位将被忽略
具体子类
FileOutputStream字节文件输出流
文件输出流是用于将数据写入 File
继承关系
构造方法
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);
}
注意事项
-
当我们创建字节输出流的时候,发生了什么?
- 在创建之前,jvm会向操作系统中找这个文件是否存在
- 如果不存在,帮我们创建
- 如果存在,覆盖原来已有的,重新写入
-
如果实现文件内容追加?
-
利用构造方法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 */ @Test public void myTest8(){ try (A a = new A()){ // 执行func方法 a.func(); } catch (Exception e) { e.printStackTrace(); } }
-
-
-
为什么要close?
- io资源属于操作系统资源,不属于jvm资源,不能够进行垃圾回收,只能显式的通过close方法去释放
- 只有不属于jvm资源,都需要释放,一般都叫close
字节输入流
抽象基类InputStream
象类是表示字节输入流的所有类的超类
继承关系
成员方法
abstract int | read() 从输入流中读取数据的下一个字节。 |
---|---|
int | read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。 |
int | read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。 |
注意事项
- read() 从输入流中读取数据的下一个字节。返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。 readData
- read(byte[] b) 读入缓冲区的总字节数;如果因为已经到达流末尾而不再有数据可用,则返回 -1。readCount
具体子类
FileInputStream字节文件输入流
FileInputStream
从文件系统中的某个文件中获得输入字节
继承关系
构造方法
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);
}