【JavaSE】IO流学习笔记
IO流
-文件
-
什么是文件
文件,对我们并不陌生,文件是保存数据的地方,比如大家经常使用的word文档,txt文件,excel文件…都是文件。它既可以保存一张图片,也可以保持视频,声音…
-
文件流
文件在程序中是以流的形式来操作的
- 流:数据在数据源(文件)和程序(内存)之间经历的路径
- 输入流:数据从数据源(文件)到程序(内存)的路径
- 输出流:数据从程序(内存)到数据源(文件)的路径
-常用文件操作
-
创建文件对象相关构造器和方法
相关方法
new File(String pathname)//根据路径构建一个File对象
new File(File parent,String child)//根据父目录文件+子路径构建
new File(String parent,String child) //根据父目录+子路径构建
createNewFile 创建新文件
package com.xijie.create;import org.junit.jupiter.api.Test;import java.io.File;
import java.io.IOException;/*** new File(String pathname)//根据路径构建一个File对象* new File(File parent,String child)//根据父目录文件+子路径构建* new File(String parent,String child) //根据父目录+子路径构建* createNewFile 创建新文件*/
public class CreateFile {@Testpublic void createFileTest() {//在D盘下用三种方式新建文件File file1=new File("D:\\file01.txt");try {file1.createNewFile();System.out.println("创建file01.txt成功");} catch (IOException e) {throw new RuntimeException(e);}//第二种方式File parentFile=new File("D:\\");File file2=new File(parentFile,"file02.txt");try {file2.createNewFile();System.out.println("创建file02.txt成功");} catch (IOException e) {throw new RuntimeException(e);}//第三种方式String parentFileName="D:\\";File file3=new File(parentFileName,"file03.txt");try {file3.createNewFile();System.out.println("创建file03.txt成功");} catch (IOException e) {throw new RuntimeException(e);}}
}
-
获取文件相关信息
getName
getAbsolutePath
getParent
length
exists
isFile
isDirectory
package com.xijie.info;import java.io.File;/*** 用D:\\Temp\\file01.txt测试* getName* getAbsolutePath* getParent* length* exists* isFile* isDirectory*/ public class FileInfoTest {public static void main(String[] args) {File file01=new File("D:\\Temp\\file01.txt");System.out.println("获取文件名称:"+file01.getName());System.out.println("获取文件绝对路径:"+file01.getAbsolutePath());System.out.println("获取文件父目录:"+file01.getParent());System.out.println("获取文件大小:"+file01.length());//9System.out.println("判断文件是否存在:"+file01.exists());//trueSystem.out.println("判断是否是文件:"+file01.isFile());//trueSystem.out.println("判断是否是文件夹:"+file01.isDirectory());//false} }
-
目录操作和文件删除
mkdir创建一级目录
mkdirs创建多级目录
delete删除空目录或文件
应用案例:
package com.xijie.deleteMkdir;import org.junit.jupiter.api.Test;import java.io.File;/*** 判断 d:\\Temp\\news1.txt 文件是否存在,如果存在就删除* 判断 D:\\Temp\\demo02 目录是否存在,存在就删除,否则提示不存在,* 判断 D:\\Temp\\a\\b\\c 目录是否存在,如果存在就提示已经存在,否则就创建*/ public class DeleteMkdir {@Test//判断 d:\\Temp\\news1.txt 文件是否存在,如果存在就删除public void deleteTest() {File file=new File("d:\\Temp\\news1.txt");if(!file.exists()){System.out.println("File "+file.getPath()+" not exists");return;}if(file.delete()){System.out.println("File "+file.getPath()+" deleted");}else{System.out.println("File "+file.getPath()+" delete failed");}}@Test//判断 D:\\Temp\\demo02 目录是否存在,存在就删除,否则提示不存在,public void deleteDirTest() {File file=new File("D:\\Temp\\demo02");if(!file.exists()){System.out.println("dir "+file.getPath()+" not exists");return;}if(file.delete()){System.out.println("dir "+file.getPath()+" deleted");}else{System.out.println("dir "+file.getPath()+" delete failed");}}@Test//判断 D:\\Temp\\a\\b\\c 目录是否存在,如果存在就提示已经存在,否则就创建public void mkDirsTest() {File file=new File("D:\\Temp\\a\\b\\c");if(file.exists()){System.out.println("dir "+file.getPath()+" already exists");return;}if(file.mkdirs()){System.out.println("dir "+file.getPath()+" created");}else{System.out.println("dir "+file.getPath()+" create failed");}} }
-IO流原理及分类
-
Java IO流原理
- I/0是Input/Output的缩写,,I/O技术是非常实用的技术,用于处理数据传输如读/写文件,网络通讯等。
- Java程序中,对于数据的输入/输出操作以”流(stream)”的方式进行。
- java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
- 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
- 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中
-
流的分类
- 按操作数据单位不同分为:字节流(8 bit)二进制文件,字符流(按字符)文本文件
- 按数据流的流向不同分为:输入流,输出流
- 按流的角色的不同分为:节点流,处理流/包装流
抽象基类 | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
Java的IO流共涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生的
由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。
-
IO流体系图
-IO流常用的类
-
InputStream:字节输入流
InputStream抽象类是所有类字节输入流的超类
InputStream 常用的子类- FilelnputStream: 文件输入流
- BufferedlnputStream: 缓冲字节输入流
- ObjectlnputStream:对象字节输入流
-
FIleInputStream介绍
-
FIleInputStream读取文件案例
package com.xijie.fileinputstream;import org.junit.jupiter.api.Test;import java.io.FileInputStream;
import java.io.IOException;/*** 使用FileInputStream读取D:\\Temp\\hello.txt中的内容并输出到控制台*/
public class FISTest {@Test//测试FIS的字节读取public void bitRead(){String path="D:\\Temp\\hello.txt";FileInputStream fis=null;try{fis=new FileInputStream(path);if(fis==null){System.out.println("文件输入流获取失败");return;}int b=0;while((b=fis.read())!=-1){System.out.print((char) b);}}catch (IOException e){e.printStackTrace();}finally {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}@Test//测试FIS的数组读取public void arrayRead() {String path="D:\\Temp\\hello.txt";FileInputStream fis=null;byte[] bArray=new byte[5];try{fis=new FileInputStream(path);if(fis==null){System.out.println("文件输入流获取失败");return;}int n=0;while((n=fis.read(bArray,0,bArray.length))!=-1){System.out.print(new String(bArray,0,n));}}catch (IOException e){e.printStackTrace();}finally {try {fis.close();} catch (IOException e) {e.printStackTrace();}}}
}
-
FileOutputStream介绍
-
FileOutputStream案例
package com.xijie.fileoutputstream;import org.junit.jupiter.api.Test;import java.io.FileOutputStream; import java.io.IOException;public class FOStest {@Testpublic void test() {String path="D:\\Temp\\hello.txt";FileOutputStream fos = null;try {//构造方法中只有路径,就会覆盖;后加true表示追加//若没有文件就会创建文件,前提是目录存在fos=new FileOutputStream(path,true);String str="Hello World";//可以写入字符或字符数组fos.write('X');fos.write(99+'A'-'a');fos.write('J');fos.write(str.getBytes());} catch (IOException e) {System.out.println("文件写入出错了");}finally {try {fos.close();} catch (IOException e) {System.out.println("文件关闭出错了");}}} }
-
文件复制案例
package com.xijie.fileoutputstream;import org.junit.jupiter.api.Test;import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException;/*** 实现图片的复制*/ public class Copy {@Testpublic void test() {String sourcePath="D:\\Temp\\down.jpeg";String targetPath="D:\\Temp\\downCopy.jpeg";FileInputStream fis = null;FileOutputStream fos = null;try{fis=new FileInputStream(sourcePath);fos=new FileOutputStream(targetPath);byte[] buffer=new byte[100];int len;while((len=fis.read(buffer))!=-1){fos.write(buffer,0,len);}}catch(IOException e){System.out.println("出错了");}finally {try {fis.close();} catch (IOException e) {System.out.println("fis文件关闭失败");}try {fos.close();} catch (IOException e) {System.out.println("fos文件关闭失败");}}} }
-
FIleReader和FileWriter介绍
FileReader和FileWriter是字符流,即按照字符来操作IO
-
FileReader相关方法:
-
new FileReader(File/String)
-
read:每次读取单个字符,返回该字符,如果到文件未尾返回-1
-
read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
相关API:
-
new String(char[]):将char[]转换成String
-
new String(char[l,off,len):将char[]的指定部分转换成String
-
-
FileWriter常用方法
-
new FileWriter(File/String):覆盖模式,相当于流的指针在首端
-
new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
-
write(int):写入单个字符
-
write(char[]):写入指定数组4)
-
write(char[],off,len):写入指定数组的指定部分
-
write(string):写入整个字符串
-
write(string,off,len):写入字符串的指定部分
相关APl:String类:toCharArray:将String转换成char[]>
注意:FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!
-
-
FIleReader和FileWriter案例
package com.xijie.filereaderwriter;import org.junit.jupiter.api.Test;import java.io.FileReader; import java.io.FileWriter; import java.io.IOException;/*** 测试FileReader和FileWriter*/ public class FileReaderWriterTest {/*** 把一段代码写到"D:\\Temp\\Code.java"里*/@Testpublic void WriteTest() {FileWriter fw = null;try {fw=new FileWriter("D:\\Temp\\Code.java");fw.write("package com.xijie.info;\n" +"\n" +"import java.io.File;\n" +"\n" +"public class FileInfoTest {\n" +" public static void main(String[] args) {\n" +" File file01=new File(\"D:\\\\Temp\\\\file01.txt\");\n" +" System.out.println(\"获取文件名称:\"+file01.getName());\n" +" System.out.println(\"获取文件绝对路径:\"+file01.getAbsolutePath());\n" +" System.out.println(\"获取文件父目录:\"+file01.getParent());\n" +" System.out.println(\"获取文件大小:\"+file01.length());//9\n" +" System.out.println(\"判断文件是否存在:\"+file01.exists());//true\n" +" System.out.println(\"判断是否是文件:\"+file01.isFile());//true\n" +" System.out.println(\"判断是否是文件夹:\"+file01.isDirectory());//false\n" +" }\n" +"}");System.out.println("Write Finished");} catch (IOException e) {throw new RuntimeException(e);}finally {try {fw.close();} catch (IOException e) {throw new RuntimeException(e);}}}/*** 读取代码文件并输出到控制台*/@Testpublic void ReadTest() {FileReader fr = null;char[] carr = new char[20];int len;try {fr=new FileReader("D:\\Temp\\Code.java");while((len=fr.read(carr,0,carr.length))!=-1){System.out.print(new String(carr,0,len));}} catch (IOException e) {throw new RuntimeException(e);}finally {try {fr.close();} catch (IOException e) {throw new RuntimeException(e);}}} }
-节点流和处理流
-
基本介绍
- 节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter
- 为程序提供处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,更为强大的读写功能,如BufferedReader、BufferedWriter
-
节点流和处理流一览图
-
节点流和处理流的区别和联系
- 节点流是底层流/低级流,直接跟数据源相接,
- 处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。[源码理解]
- 处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连[模拟修饰器设计模式]
-
处理流的功能主要体现在以下两方面
- 性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
- 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
-
处理流-BufferedReader和BufferedWriter
- BufferedReader 和 BufferedWriter 属于字符流,是按照字符来读取数据的
- 关闭时,只需要关闭外层流即可
案例:
package com.xijie.bufferedRWCopy;import org.junit.jupiter.api.Test;import java.io.*;public class BufferedReaderWriterCopy {/*** 写入一段代码到一个文件,然后复制到另一个文件*/@Testpublic void testBufferedReaderWriterCopy() {String targetFilePath="D:\\Temp\\hello.java";String copyFilePath="D:\\Temp\\helloCopy.java";BufferedWriter bufferedWriter = null;BufferedReader bufferedReader = null;//创建文件try {bufferedWriter = new BufferedWriter(new FileWriter(targetFilePath));bufferedWriter.write("package com.xijie.info;\n" +"\n" +"import java.io.File;\n" +"\n" +"/**\n" +" * 用D:\\\\Temp\\\\file01.txt测试\n" +" * getName\n" +" * getAbsolutePath\n" +" * getParent\n" +" * length\n" +" * exists\n" +" * isFile\n" +" * isDirectory\n" +" */\n" +"public class FileInfoTest {\n" +" public static void main(String[] args) {\n" +" File file01=new File(\"D:\\\\Temp\\\\file01.txt\");\n" +" System.out.println(\"获取文件名称:\"+file01.getName());\n" +" System.out.println(\"获取文件绝对路径:\"+file01.getAbsolutePath());\n" +" System.out.println(\"获取文件父目录:\"+file01.getParent());\n" +" System.out.println(\"获取文件大小:\"+file01.length());//9\n" +" System.out.println(\"判断文件是否存在:\"+file01.exists());//true\n" +" System.out.println(\"判断是否是文件:\"+file01.isFile());//true\n" +" System.out.println(\"判断是否是文件夹:\"+file01.isDirectory());//false\n" +" }\n" +"}\n");bufferedWriter.flush();System.out.println("创建文件完成");} catch (IOException e) {throw new RuntimeException(e);}finally {try {bufferedWriter.close();} catch (IOException e) {throw new RuntimeException(e);}}//复制文件try {bufferedWriter = new BufferedWriter(new FileWriter(copyFilePath));bufferedReader = new BufferedReader(new FileReader(targetFilePath));System.out.println("开始读取并复制文件");char[] carray = new char[20];int len;while((len=bufferedReader.read(carray,0,carray.length))!=-1){System.out.print(String.valueOf(carray,0,len));bufferedWriter.write(carray,0,len);}System.out.println("读取与复制完成");} catch (IOException e) {throw new RuntimeException(e);}finally {try {bufferedWriter.close();} catch (IOException e) {throw new RuntimeException(e);}try {bufferedReader.close();} catch (IOException e) {throw new RuntimeException(e);}}} }
-
对象流-ObjectInputStream和ObjectOutputStream
看一个需求
- 将int num = 100 这个 int 数据保存到文件中,注意不是 100 数字,而是 int 100,并且,能够从文件中直接恢复 int 100
- 将 Dog dog = new Dog(“小黄”, 3) 这个 dog对象 保存到 文件中,并且能够从文件恢复.
- 上面的要求,就是 能够将 基本数据类型 或者 对象 进行 序列化 和 反序列化操作
序列化和反序列化
- 序列化就是在保存数据时,保存数据的值和数据类型
- 反序列化就是在恢复数据时,恢复数据的值和数据类型
- 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:>Serializable //这是一个标记接口Externalizable
-
基本介绍
- 功能:提供了对基本类型或对象类型的序列化和反序列化的方法
- ObjectOutputStream 提供 序列化功能
- ObjectInputStream 提供 反序列化功能
-
序列化案例
package com.xijie.objectStream;import org.junit.jupiter.api.Test;import java.io.*;/*** 在一个文件里保存:* 一个整数、一个bool、一个浮点数、一个字符、一个字符串、一个自定义Dog对象** 然后读取这个文件里保存的对象*/ public class ObjectInputOutputStream {@Testpublic void objectOutputTest() throws IOException {String filePath="D:\\Temp\\data.dat";ObjectOutputStream oos = null;oos=new ObjectOutputStream(new FileOutputStream(filePath));//一个整数int i=100;oos.writeInt(i);// 一个boolboolean b=true;oos.writeBoolean(b);// 一个浮点数double d=3.1415926;oos.writeDouble(d);// 一个字符char c='a';oos.writeChar(c);// 一个字符串String str="hello world";oos.writeUTF(str);// 一个自定义Dog对象Dog dog=new Dog(10,"lala");oos.writeObject(dog);oos.close();}@Testpublic void objectInputTest() throws IOException, ClassNotFoundException {String filePath="D:\\Temp\\data.dat";ObjectInputStream ois = null;ois=new ObjectInputStream(new FileInputStream(filePath));//一个整数int i=ois.readInt();System.out.println("读取整数:"+i);// 一个boolboolean b=ois.readBoolean();System.out.println("读取布尔:"+b);// 一个浮点数double d=ois.readDouble();System.out.println("读取浮点:"+d);// 一个字符char c=ois.readChar();System.out.println("读取字符:"+c);// 一个字符串String str=ois.readUTF();System.out.println("读取字符串:"+str);// 一个自定义Dog对象Dog dog=(Dog)(ois.readObject());System.out.println("读取自定义对象:"+dog);ois.close();} }class Dog implements Serializable {int age;String name;public Dog(int age, String name) {this.age = age;this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Dog{" +"age=" + age +", name='" + name + '\'' +'}';} }
-
序列化流注意事项和细节说明
- 读写顺序要一致
- 要求实现序列化或反序列化对象 ,需要 实现 Serializable
- 序列化的类中建议添加SerialVersionUlD,为了提高版本的兼容性
- 席列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
- 序列化对象时,要求里面属性的类型也需要实现序列化接口
- 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
-
标准输入输出流
类型 默认设备 System.in 标准输入 InputStream 键盘 System.out 标准输出 OutputStream 显示器 -
转换流InputStreamReader和OutputStreamWriter
转换流可以使用规定的编码,把字节流转换为字符流,因此可以以初始化流的编码来读取或写入特定编码的文档。
package com.xijie.inputstreamreaderoutputstreamwriter;import org.junit.jupiter.api.Test;import java.io.*; import java.nio.charset.StandardCharsets;/*** 测试转换流:InputStreamReader和OutputStreamWriter*/ public class ConvertStreamTest {/*** windows记事本默认存储格式为utf8* 我们首先以GBK格式存储一个文档,然后再用GBK格式读取*/@Testpublic void test() throws IOException {String path="D:\\Temp\\HelloConvert.txt";String content="这是一份GBK格式的文档";//以GBK格式存储一个文档OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(path),"GBK");osw.write(content);osw.close();//尝试以UTF8格式读取文档看效果InputStreamReader isr = new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8);BufferedReader br = new BufferedReader(isr);System.out.println("用UTF8格式读取GBK文档的内容(显然是乱码):"+br.readLine());br.close();//尝试以正确的编码读取文档isr=new InputStreamReader(new FileInputStream(path), "GBK");br = new BufferedReader(isr);System.out.println("以GBK编码读取GBK文档的结果:"+br.readLine());} }
-
打印流-PrintStream 和 PrintWriter
打印流只有输出流没有输入流
package com.xijie.printstreamprintwriter;import org.junit.jupiter.api.Test;import java.io.*;/*** 测试用PrintStream 和 PrintWriter写数据到控制台和文件*/ public class PrintStreamPrintWriterTest {@Testpublic void test() throws IOException {PrintStream ps = new PrintStream(System.out);ps.println("hello,用printstream输出到控制台");//不关闭也可以输出//ps.close();PrintWriter pw = new PrintWriter(System.out);pw.println("hello,用printswriter输出到控制台");//必须关闭才能输出pw.close();ps=new PrintStream(new FileOutputStream("D:\\Temp\\Hello.txt"));ps.println("hello,用printstream输出到文件");ps.close();pw = new PrintWriter(new FileWriter("D:\\Temp\\Hello.txt",true));pw.println("hello,用printswriter输出到文件");//必须关闭才能输出pw.close();} }
-Properties类
-
基本介绍
专门用于读写配置文件的集合类
-
配置文件的格式:
键=值
键=值 -
注意:键值对不需要有空格,值不需要用引号一起来。默认类型是String
-
Properties的常见方法
load:加载配置文件的键值对到Properties对象
Iist:将数据显示到指定设备
getProperty(key):根据键获取值
setProperty(key,value):设置键值对到Properties对象
store:将Properties中的键值对存储到配置文件,在idea 中,保存信息到配置文件,如果含有中文,会存储为unicode码
package com.xijie.properties;import org.junit.jupiter.api.Test;import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Properties;/*** 储存ip、user、pwd到配置文件mysql.properties* 读取配置文件内容并输出到控制台*/ public class PropertiesTest {@Testpublic void test() throws IOException {Properties p = new Properties();p.setProperty("ip", "127.0.0.1");p.setProperty("user", "root");p.setProperty("pwd", "abc111");p.store(new FileWriter(".\\mysql.properties"), null);System.out.println("保存完毕");Properties p2 = new Properties();p2.load(Files.newBufferedReader(Paths.get(".\\mysql.properties")));for (Object key : p2.keySet()) {System.out.println(key + "=" + p2.get(key));}} }
-