PS:大部分来源于参考资料的原话,总结的很好我就没改。
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
java
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读取值是字节数量,读取不到返回-1
System.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 {
// 失败与否都要关闭io
if(inputStream != null){ // 判断文件是否为null
try{
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
InputStreamReader
就是有这么一种写法。
将字节输入流转换字符输入流。
java
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 {
// 失败与否都要关闭io
if(inputStreamReader != null){
try{ // 流的关闭要区分顺序,先关闭外层也就是包装那一层
inputStreamReader.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileReader
文件字符读取的形式
java
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
自带缓存的字符输入流。构造参数是一个字符输入流。
java
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
反序列化对象
java
// 反序列化
ObjectInputStream oin = new ObjectInputStream(new FileInputStream("conf1.txt"));
Object o = oin.readObject();
System.out.println(o);
6.输出流
FileOutputStream
java
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(); // 先刷新在关闭,否则可能有bug
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
OutputStreamWriter
java
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
java
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
java
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对象)
java
PrintStream printStream = new PrintStream(new FileOutputStream("conf.txt"));
printStream.println("\n121212"); // 输出到conf.txt
System.setOut(printStream); // 改变流的输出方向
System.out.println("\n完了数"); // 输出到conf.txt了
System.out.println("121212");
ObjectOutputStream
对新手感觉用处不大
要被序列化的对象必须实现 Serializable 接口
java
// 序列化
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 (): 清除所有装载的 键 - 值对。该方法在基类中提供。
配置文件读取
java
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));
}
配置文件设置
java
/**
* 配置文件设置
*
* @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对象表示文件、目录的抽象表示形式。
案例:递归实现遍历文件目录
java
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
}
}
}
}