1. IO 流能干什么
通过IO我们能对硬盘文件进行读和写。(网络数据的传输也涉及到io)。
2. IO流的分类
按照 流的方向 进行分类:分为输入、输出流。
往内存中去:叫做输入(Input)。或者叫做读(Read)。
从内存中出来:叫做输出(Output)。或者叫做写(Write)。
按照 读取数据方式 不同进行分类:
按照 字节 的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。
这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件 等…
按照 字符 的方式读取数据的,一次读取一个字符.
这种流是为了方便读取 普通文本文件 而存在的,这种流不能读取:图片、声音、视频等文件。只能读取 纯文本文件,连word文件都无法读取。
注意:
纯文本文件,不单单是.txt文件,还包括 .java、.ini、.py 。总之只要 能用记事本打开 的文件都是普通文本文件。
3.IO流的顶层父类
- 字节输入流:顶层父类:InputStream --> 抽象类 常见子类:FileInputStream
- 字节输出流:顶层父类:OutputStream --> 抽象类 常见子类:FileOutputStream
- 字符输入流:顶层父类:Reader --> 抽象类 常见子类:FileReader
- 字符输出流:顶层父类:Writer --> 抽象类 常见子类:FileWriter
4.Java要掌握的流(16个)
1.文件专属:
- java.io.FileInputStream(掌握)
- java.io.FileOutputStream(掌握)
- java.io.FileReader
- java.io.FileWriter
2.转换流:(将字节流转换成字符流)
- java.io.InputStreamReader
- java.io.OutputStreamWriter
3.缓冲流专属:
- java.io.BufferedReader
- java.io.BufferedWriter
- java.io.BufferedInputStream
- java.io.BufferedOutputStream
4.数据流专属:
- java.io.DataInputStream
- java.io.DataOutputStream
5.标准输出流:
- java.io.PrintWriter
- java.io.PrintStream(掌握)
6.对象专属流:
- java.io.ObjectInputStream(掌握)
- java.io.ObjectOutputStream(掌握)
7.File文件类
- java.io.File
5.输入流
PS: 下面很多try,catch 捕获异常,都不是我写的,当然第一次写的话,可以自己敲一下,但是alt + z 直接快捷生成。
另外,就是那几个常用的方法(我自己觉得),其实会写前几个,其实剩余都比较好记住。
我的conf.txt文件和src在同一个目录。
FileInputStream
public class IODemo1 {public static void main(String[] args) {File file = new File("conf.txt");FileInputStream inputStream = null;try {inputStream = new FileInputStream(file);byte[] bytes = new byte[3]; // 做缓存用的,一次最多4个字节int redCount = 0;// inputStream去读取,而每次读取到的字节文件存放到bytes中。while ((redCount = inputStream.read(bytes)) != -1){ // read读取值是字节数量,读取不到返回-1System.out.println("转换后的字符:"+new String(bytes, "UTF-8"));System.out.println("读取字节数量:"+redCount);System.out.println("----------------");}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {// 失败与否都要关闭ioif(inputStream != null){ // 判断文件是否为nulltry{inputStream.close();} catch (IOException e) {e.printStackTrace();}}}}
}
InputStreamReader
就是有这么一种写法。
将字节输入流转换字符输入流。
public class IODemo {public static void main(String[] args) {File file = new File("conf.txt");FileInputStream inputStream = null;InputStreamReader inputStreamReader = null;try {inputStream = new FileInputStream(file);inputStreamReader = new InputStreamReader(inputStream,"UTF-8"); // 转换为为字符输入流byte[] bytes = new byte[3]; // 做缓存用的,一次最多4个字节char[] chars = new char[1];int redCount = 0;// inputStream去读取,每次读取到字节存放到bytes中。//while ((redCount = inputStream.read(bytes)) != -1){ // read读取值是字节数量,读取不到返回-1// System.out.println("转换后的字符:"+new String(bytes, "GBK"));// System.out.println("读取字节数量:"+redCount);//}System.out.println("---------------");// 对一个文件不能同时开2个输入流while ((redCount = inputStreamReader.read(chars)) != -1){System.out.println("读取字符数量:"+redCount);for (char aChar : chars) { // 遍历缓冲字符数组System.out.println(aChar);}System.out.println("将字符数组转换成字符串:"+ new String(chars));System.out.println("---------------");}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {// 失败与否都要关闭ioif(inputStreamReader != null){try{ // 流的关闭要区分顺序,先关闭外层也就是包装那一层inputStreamReader.close();inputStream.close();} catch (IOException e) {e.printStackTrace();}}}}
}
FileReader
文件字符读取的形式
public class FileReaderDemo {public static void main(String[] args) {File file = new File("conf.txt");FileReader fileReader = null;try {char[] chars = new char[4];int readCount = 0;fileReader = new FileReader(file);while ((readCount = fileReader.read(chars)) != -1){System.out.println(new String(chars));}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {if(fileReader != null){try {fileReader.close();} catch (IOException e) {e.printStackTrace();}}}}
}
BufferedReader
自带缓存的字符输入流。构造参数是一个字符输入流。
public class BufferReaderDemo {public static void main(String[] args) throws IOException {FileReader fileReader = new FileReader("conf.txt");// 当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。// 外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。// 像当前这个程序来说:FileReader就是一个节点流。BufferedReader就是包装流/处理流。BufferedReader bufferedReader = new BufferedReader(fileReader);String str = null;while ((str = bufferedReader.readLine()) != null){ // readLine()方法读取一个文本行,但不带换行符。System.out.println(str);}bufferedReader.close(); // 关闭最外层即可}
}
ObjectInputStream
反序列化对象
// 反序列化ObjectInputStream oin = new ObjectInputStream(new FileInputStream("conf1.txt"));Object o = oin.readObject();System.out.println(o);
6.输出流
FileOutputStream
public class IoDemo2 {public static void main(String[] args) {File file = new File("conf.txt");FileOutputStream outputStream = null;try {outputStream = new FileOutputStream(file,true); // 开启文件追加模式String wls = "万乐姝";byte[] bytes = wls.getBytes(StandardCharsets.UTF_8); // 将string转换为字节文件outputStream.write(bytes); // 写入} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {if(outputStream != null){try {outputStream.flush(); // 先刷新在关闭,否则可能有bugoutputStream.close();} catch (IOException e) {e.printStackTrace();}}}}
}
OutputStreamWriter
public class IoDemo2 {public static void main(String[] args) {File file = new File("conf.txt");FileOutputStream outputStream = null;OutputStreamWriter outputStreamWriter = null;try {outputStream = new FileOutputStream(file,true); // 开启文件追加模式outputStreamWriter = new OutputStreamWriter(outputStream);outputStreamWriter.write("万乐姝");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}finally {if(outputStream != null){try {outputStreamWriter.flush(); // 先关闭外层流outputStreamWriter.close();outputStream.flush();outputStream.close();} catch (IOException e) {e.printStackTrace();}}}}
}
FileWriter
public class FileWriterDemo {public static void main(String[] args) {File file = new File("conf.txt");FileWriter fileWriter = null;try {fileWriter = new FileWriter(file,true); // 开启文件追加模式fileWriter.write("卧槽");} catch (IOException e) {e.printStackTrace();}finally {try {fileWriter.flush();fileWriter.close();} catch (IOException e) {e.printStackTrace();}}}
}
BufferedWriter
public class BufferWriterDemo {public static void main(String[] args) throws IOException {FileWriter fileWriter = new FileWriter("conf.txt",true);BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);bufferedWriter.write("qhxxxx");bufferedWriter.close();}
}
PrintStream
我们平时用的控制台打印语句就是PrintStream对象
改变流的输出方向
System.setOut(PrintStream对象)
PrintStream printStream = new PrintStream(new FileOutputStream("conf.txt"));printStream.println("\n121212"); // 输出到conf.txtSystem.setOut(printStream); // 改变流的输出方向System.out.println("\n完了数"); // 输出到conf.txt了System.out.println("121212");
ObjectOutputStream
对新手感觉用处不大
要被序列化的对象必须实现 Serializable 接口
// 序列化ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("conf1.txt"));objectOutputStream.writeObject(new User("qhx","1232323"));objectOutputStream.flush();objectOutputStream.close();
7.配置properties文件的读取和设置
- getProperty ( String key): 用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value。
- load ( InputStream inStream): 从输入流中读取属性列表(键和元素对)。通过对指定的文件(比如说上面的 test.properties 文件)进行装载来获取该文件中的所有键 - 值对。以供 getProperty ( String key) 来搜索。
- setProperty ( String key, String value) : 调用 Hashtable 的方法 put 。他通过调用基类的put方法来设置 键 - 值对。
- store ( OutputStream out, String comments): 以适合使用 load 方法加载到 Properties 表中的格式,将此 Properties 表中的属性列表(键和元素对)写入输出流。与 load 方法相反,该方法将键 - 值对写入到指定的文件中去。
- clear (): 清除所有装载的 键 - 值对。该方法在基类中提供。
配置文件读取
private static String getKey(String key) {Properties properties = new Properties();File file = new File(FILE_NAME);FileInputStream inputStream = null;try {inputStream = new FileInputStream(file); // 配置文件properties.load(inputStream); // 将配置文件对应的key,value映射到properties的map中。} catch (IOException e) {e.printStackTrace();}finally {if(inputStream != null){ // 还是这样关比较好,万一报错就tm关不了try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}}System.out.println(properties.getProperty(key));}
配置文件设置
/*** 配置文件设置** @param key* @param value* @return*/public static boolean setPropertiesKey(String key,String value) {// 判断key是否有重复String key1 = getKey(key);if(key1 == null){return setKey(key,value); }return false;}/*** 配置文件设置** @param key* @param value* @return boolean*/private static boolean setKey(String key, String value) {Properties properties = new Properties();File file = new File(FILE_NAME); // 其实有其他配置可以同意下yaml文件里面配置,然后这里面读取,好统一调配。FileWriter fileWriter = null;try {fileWriter = new FileWriter(file,true);properties.setProperty(key, value); // 存进map里面properties.store(fileWriter,""); // 将map对应的键值对写进输出流。这个comments 最后写入的时候是个注释} catch (IOException e) {// 卧槽我加入设置key,value失败,肯定调到这个逻辑return false;} finally {if (fileWriter != null) { // 还是这样关比较好,万一报错就tm关不了try {fileWriter.flush();fileWriter.close();} catch (IOException e) {e.printStackTrace();}}}return true;}}
8.File
在java中file对象表示文件、目录的抽象表示形式。
案例:递归实现遍历文件目录
public class FileDemo {public static void main(String[] args) {getChildrenFile("src",1);}// 递归则子文件所有目录public static void getChildrenFile(String fileName,int y){ // fileName 文件路径名,y 是目录等级File file = new File(fileName);StringBuffer stb = new StringBuffer();// 根据目录等级追加几条 "-"for (int i = 0; i < y; i++) {stb.append("-");}// 遍历子文件for (String name: file.list()) {System.out.println(stb + name); // 目录等级 + 文件路径名,并且换行String childrenName = fileName + "/"+name;if(new File(childrenName).isDirectory()){ // 判断子文件是否是递归,是的话仍执行getChildrenFile(childrenName,y+1); // 同样下一级目录等级 + 1}}}}
参考资料
Java IO流 详解(字节流、字符流、输入流、输出流、刷新)_输入流 输出流 更新流_肥兄的博客-CSDN博客
Java IO流(超详细!)_一个快乐的野指针~的博客-CSDN博客