声明:以下笔记来源于韩顺平视频https://www.bilibili.com/video/BV1fh411y7R8?p=1,笔记为楼主亲手劳动,劳动不易,转载请标明谢谢。
IO 流
创建文件对象相关构造器和方法
new File(String pathname) //根据路径构建一个File对象
new File(File parent,String child) //根据父目录文件+子路径构建
new File(String parent,String child) //根据父目录+子路径构建
public class FileCreate { public static void main(String[] args) { } @Test public void create01() { String filePath = "d:\\test\\news1.txt"; File file = new File(filePath); try { file.createNewFile(); System.out.println("文件创建成功!"); } catch (IOException e) { e.printStackTrace(); } } @Test public void create02() { File parentFile = new File("d:\\test"); String fileName = "news02.txt"; File file = new File(parentFile, fileName); try { file.createNewFile(); System.out.println("文件创建成功!"); } catch (IOException e) { e.printStackTrace(); } } @Test public void create03() { String parentFile = "d:\\test"; // String parentFile = "d:/test"; String fileName = "news02.txt"; File file = new File(parentFile, fileName); try { file.createNewFile(); System.out.println("文件创建成功!"); } catch (IOException e) { e.printStackTrace(); } } }
常用方法
getName、getAbsolutePath, getParent、 length、 exists、 isFile、isDirectory
public class FileInformation { public static void main(String[] args) { } @Test public void info() { //getName、getAbsolutePath, getParent、 length、 exists、 isFile、isDirectory File file = new File("d:\\test\\news1.txt"); System.out.println(file.getName());//获取文件名字 System.out.println(file.getAbsolutePath());//获取文件绝对路径 System.out.println(file.getParent());//获取文件父目录 System.out.println(file.length());//获取文件大小 System.out.println(file.exists());//获取是否存在 System.out.println(file.isFile());//获取是否是文件 System.out.println(file.isDirectory());//获取是否是目录 } }
目录的操作与文件的删除
mkdir
创建一-级目录、mkdirs
创建多级目录、delete删除空目录或文件public class Directory_ { public static void main(String[] args) { } @Test public void m1() { File file = new File("d:\\test\\news1.txt"); if (file.exists()) { if (file.delete()) { System.out.println("文件删除成功"); }else { System.out.println("文件删除失败"); } }else { System.out.println("文件不存在"); } } @Test public void m2() {//目录可以被当做文件 File file = new File("d:\\test"); if (file.exists()) { if (file.delete()) { System.out.println("目录删除成功"); }else { System.out.println("目录删除失败"); } }else { System.out.println("目录不存在"); } } @Test public void m3() {//目录可以被当做文件 String directoryPath = "d:\\test\\demo\\a\\b\\c"; File file = new File(directoryPath); if (file.exists()) {//exists 创建多级目录 exist创建一级目录 d:\test System.out.println(directoryPath + "存在"); }else { if (file.mkdirs()) { System.out.println(directoryPath + "创建成功"); } else { System.out.println(directoryPath + "创建失败"); } } } }
IO 流原理及流的分类
按操作数据单位不同分为:字节流(8 bit)二进制文件,字符流(按字符)文本文件
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流/包装流
(抽象基类) 字节流 字符流 输入流 InputStream Reader 输出流 OutputStream Writer Java的IO流共涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生的。
由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。
FileInputStream
FileInputStream:文件输入流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NikFX9UE-1648481509836)(D:/Typora%20Data/Img/image-20220317185810899.png)]
public class FileInputStream_ { public static void main(String[] args) { } @Test public void readFile01() { String filePath = "d:\\test\\news1.txt"; int readData = 0; FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(filePath); while ((readData = fileInputStream.read()) != -1) { System.out.print((char) readData); } } catch (IOException e) { e.printStackTrace(); }finally { try {//一定要记得释放资源 fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void readFile02() { String filePath = "d:\\test\\news1.txt"; byte[] buf = new byte[8]; int len = 0; FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(filePath); while ((len = fileInputStream.read(buf)) != -1) { System.out.print(new String(buf, 0,len)); } } catch (IOException e) { e.printStackTrace(); }finally { try {//一定要记得释放资源 fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
FileOutputStream
FileOutputStream:文件输出流
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ny4L7OJJ-1648481509842)(D:/Typora%20Data/Img/image-20220318091240284.png)]
public class FileOutputStream_ { public static void main(String[] args) { } @Test public void writeFile() { String filePath = "d:\\test\\news1.txt"; FileOutputStream fileOutputStream = null; try { // fileOutputStream = new FileOutputStream(filePath); fileOutputStream = new FileOutputStream(filePath,true); // fileOutputStream.write('H'); String str = "hello,world"; fileOutputStream.write(str.getBytes(),0,5); } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
节点流与处理流
节点流可以从一个特定的数据源读写数据,如FileReader、 FileWriter (
就是只能处理单个数据源的
)处理流(也叫包装流)是"连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如BufferedReader、BufferedWriter (
修饰器设计模式 ↓
)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KE5Tpmv0-1648481509844)(D:/Typora%20Data/Img/image-20220318102806343.png)]
BufferedReader 测试代码
public class BufferedWriter_ { public static void main(String[] args) throws Exception{ String filePath = "D:\\test\\news1.txt"; BufferedReader reader = new BufferedReader(new FileReader(filePath)); String line; while ((line = reader.readLine()) != null){ System.out.println(line); } reader.close(); } }
BufferedWriter 测试代码
public class BufferWriter_ { public static void main(String[] args) throws Exception{ String filePath = "D:\\test\\news2.txt"; //包装类 BufferedWriter 没有提供 append的构造方法 ,在底层流可以添加 BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true)); bufferedWriter.write("test bufferedWriter!!!"); bufferedWriter.newLine();//根据系统自动插入换行符 bufferedWriter.write("test bufferedWriter!!!"); bufferedWriter.newLine(); bufferedWriter.write("test bufferedWriter!!!"); bufferedWriter.newLine(); bufferedWriter.write("test bufferedWriter!!!"); bufferedWriter.close(); } }
BufferedInputStream:缓冲字节输入流
BufferedInputStream是字节流在创建BufferedInputStream时,会创建一个内部缓冲区数组.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IqT3Miuk-1648481509844)(D:/Typora%20Data/Img/image-20220318160811562.png)]
相关代码
public class BufferedCopy02 { public static void main(String[] args) { String srcPath = "D:\\Program Files\\韩顺平 2021零基础学Java 【软件 资料 代码 笔记】\\资料\\分享资料\\bg.png"; String destPath = "D:\\test\\bg.png"; BufferedInputStream bis = null; BufferedOutputStream bos = null; try { bis = new BufferedInputStream(new FileInputStream(srcPath)); bos = new BufferedOutputStream(new FileOutputStream(destPath)); byte[] data = new byte[1024]; int readLen; while ((readLen = bis.read(data)) != -1) { bos.write(data,0,readLen); } } catch (IOException e) { e.printStackTrace(); } finally { try { bis.close(); bos.close(); } catch (IOException e) { e.printStackTrace(); } } } }
BufferedOutputStream:缓冲字节输出流
BufferedOutputStream是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qF55CrRA-1648481509845)(D:/Typora%20Data/Img/image-20220318160425843.png)]
ObjectInputStream 与 ObjectOutputStream(两个都是包装流)
处理流(包装流)使用了修饰器设计模式
序列化和反序列化
序列化就是在保存数据时,保存数据的值和数据类型
反序列化就是在恢复数据时,恢复数据的值和数据类型
需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之 一 :
- Serializable//这是一个标记接口,没有方法
- Externalizable //该接口有方法需要实现,因此我们一般实现上面的Serializable接口
ObjectOutputStream提供序列化功能
ObjectInputStream提供反序列化功能
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sMMYyPrv-1648481509847)(D:/Typora%20Data/Img/image-20220318170611230.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFyKhz3i-1648481509848)(D:/Typora%20Data/Img/image-20220318170711686.png)]
相关练习代码
public class ObjectOutputStream_ {//写出是序列化 public static void main(String[] args) throws Exception{ String filePath = "d:\\test\\data.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); oos.writeInt(100); oos.writeBoolean(true); oos.writeChar('a'); oos.writeDouble(9.5); oos.writeUTF("UTF 表示一个字符串"); oos.writeObject(new Dog("旺财",5)); oos.close(); System.out.println("序列化保存对象流"); } } class Dog implements Serializable { private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = age; } }
public class ObjectInputStream_ {//读入是反序列化 public static void main(String[] args) throws Exception { String filePath = "d:\\test\\data.dat"; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); //获取要一一对应文件里面的类型 System.out.println(ois.readInt()); System.out.println(ois.readBoolean()); System.out.println(ois.readChar()); System.out.println(ois.readDouble()); System.out.println(ois.readUTF()); Object object = ois.readObject(); System.out.println(object); System.out.println("object 的类型" + object.getClass()); ois.close(); } }
注意事项与细节
读写顺序要一致
要求序列化或反序列化对象,需要实现 Serializable
序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
private static final long serialVersionUID = 1L;
序列化对象时,默认将里面所有属性都进行序列化,但除了
static
或transient
修饰的成员序列化对象时,要求里面属性的类型也需要实现序列化接口.
序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
FileReader
类图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DnTXnOzj-1648481509849)(D:/Typora%20Data/Img/image-20220318091132551.png)]
相关方法
- new FileReader(File/String)
read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
read(char[]):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
new String(char[]):将char[]转换成String
new String(char[],off,len):将char]的指定部分转换成Strin测试代码
public class FileReader_ { public static void main(String[] args) { } @Test public void readerFile02() { String filePath = "D:\\test\\news1.txt"; FileReader fileReader = null; int data ; try { fileReader = new FileReader(filePath); while ((data = fileReader.read()) != -1) { System.out.print((char)data); } } catch (IOException e) { e.printStackTrace(); }finally { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } @Test public void readerFile01() { String filePath = "D:\\test\\news1.txt"; FileReader fileReader = null; char[] data = new char[8]; int readlen; try { fileReader = new FileReader(filePath); while ((readlen = fileReader.read(data)) != -1) { System.out.print(new String(data,0,readlen)); } } catch (IOException e) { e.printStackTrace(); }finally { try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
FileWriter
类图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fhd520Aa-1648481509849)(D:/Typora%20Data/Img/image-20220318091633915.png)]
常用方法
- new FileWriter(File/String):覆盖模式,相当于流的指针在首端
- new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
- write(int):写入单个字符
- write(char[]):写入指定数组
- write(char[],off,len):写入指定数组的指定部分
- write (string) :写入整个字符串
- write(string,of,len):写入字符串的指定部分
- 相关API: String类: toCharArray:将String转换成char[]
FileWriter使用后,必须要关闭(close)或刷新(flush), 否则写入不到指定的文件(应该是包括Writer及其子类都要flush)!
测试代码
public class FileWriter_ { public static void main(String[] args) { } @Test public void writerFile01() { String filePath = "D:\\test\\news1.txt"; FileWriter fileWriter = null; char[] data = {'a','b','c'}; try { fileWriter = new FileWriter(filePath); fileWriter.write('H'); fileWriter.write(data); fileWriter.write("字符窜测试".toCharArray(),0,3); fileWriter.write("霓虹啊"); fileWriter.write("霓虹啊",0,1); } catch (IOException e) { e.printStackTrace(); } finally { try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
标准输入输出流
//System 类的pubLic final static InputStream in = null; // System.in 编译类型 InputStream // System.in 运行类型 BufferedInputStream //表示的是标准输入键盘 System.out.printLn(System.in.getCLass()); //1. System.out pubLic final static PrintStream out = nuLL; //2. 编译类型PrintStream //3. 运行类型PrintStream //4. 表示标准输出显示器 System.out.printLn(System.out.getClass());
转换流 InputStreamReader与 OutputStreamWriter
- InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)
- OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
- 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
- 可以在使用时指定编码格式(比如utf -8, gbk,gb2312, IS08859-1等)
类图
InputStreamReader
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PiEwF6Zg-1648481509850)(D:/Typora%20Data/Img/image-20220319094110901.png)]
OutputStreamWriter
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10zs5VAP-1648481509851)(D:/Typora%20Data/Img/image-20220319094229977.png)]
案例
public class InputStreamReader_ { public static void main(String[] args) throws IOException { String filePath = "d:\\test\\news3.txt"; BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "gbk")); reader.close(); System.out.println("转换流读取=" + reader.readLine()); } }
public class OutputStreamWriter_ { public static void main(String[] args) throws IOException { String filePath = "d:\\test\\news2.txt"; String charSet = "utf8"; OutputStreamWriter isr = new OutputStreamWriter(new FileOutputStream(filePath), charSet); isr.write("hi,输出装换流"); isr.close(); System.out.println(charSet + "转换成功"); } }
打印流 PrintStream 与 PrintWriter
PrintStream 类图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fDBs4amD-1648481509853)(D:/Typora%20Data/Img/image-20220319101151325.png)]
代码
public class PrintStream_ { public static void main(String[] args) throws IOException { String filePath = "d:\\test\\news4.txt"; PrintStream ps = System.out; ps.print("hi,打印流"); System.setOut(new PrintStream(filePath)); ps = System.out; System.out.println("hello01"); ps.print("hello02");//追加方式 } }
PrintWriter 类图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RAaywfYL-1648481509853)(D:/Typora%20Data/Img/image-20220319101320659.png)]
代码
public class PrintWriter_ { public static void main(String[] args) throws FileNotFoundException { String filePath = "d:\\test\\news4.txt"; // PrintWriter printWriter = new PrintWriter(System.out); PrintWriter printWriter = new PrintWriter(filePath); printWriter.print("北京你好~~"); printWriter.close();//关闭流相当于flush + 关闭 } }
练习作业
/** * 在判断e盘下是否有文件夹mytemp ,如果没有就创建myTemp * 在e:\myTemp目录下,创建文件hello.txt * 如果hello.txt已经存在,提示该文件已经存在,就不要再重复创建了 * 并且在hello.txt文件中,写入hello,world~ */ public class HomeWorks01 { public static void main(String[] args) throws IOException { String directPath = "d:\\test\\myTemp"; File file = new File(directPath); if (!file.exists()) { if (file.mkdirs()) { System.out.println(directPath + "文件创建成功"); }else { System.out.println( directPath + "文件创建失败"); } } String filePath = directPath + "\\hello.txt"; file = new File(filePath); BufferedWriter bufferedWriter = null; if (!file.exists()) { if (file.createNewFile()) { System.out.println(filePath + "文件创建成功"); bufferedWriter = new BufferedWriter(new FileWriter(filePath)); bufferedWriter.write("hello,world"); }else { System.out.println("文件创建失败"); } }else { System.out.println(filePath + "文件已经存在"); bufferedWriter = new BufferedWriter(new FileWriter(filePath)); bufferedWriter.write("hello,world"); } bufferedWriter.close(); } }
public class HomeWork02 { /** * 要求:使用BufferedReader读取一个文本文件,为每行加上行号, * 再连同内容一并输出到屏幕上。 */ public static void main(String[] args) { String filePath = "d:\\test\\news1.txt"; BufferedReader br = null; String readLen; int num = 0; try { br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath))); while((readLen = br.readLine()) != null) { System.out.println(num++ + " " + readLen); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (br != null) { br.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
public class HomeWork03 { /** * (1)要编写-个dog.properties * name=tom * age=5 * color= red * (2)编写Dog类(name,age,color)创建一个dog对象, 读取dog.properties 用相应的内容完成属性初始化,并输出 * (3)将创建的Dog对象,序列化到文件dog.dat文件 */ public static void main(String[] args) { } @Test public void m1() throws IOException { String filePath = "C:\\Users\\86152\\IdeaProjects\\kuangshen-study\\baseLearn\\src\\com\\su\\properties_\\dog.properties"; Properties properties = new Properties(); FileReader fr = new FileReader(filePath); properties.load(fr); String name = properties.get("name") + ""; int age = Integer.parseInt(properties.get("age") + ""); String color = properties.get("color") + ""; Dog dog = new Dog(name, age, color); System.out.println("dog的相关信息" + dog); String serFilePath = "d:\\test\\data.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(serFilePath)); oos.writeObject(dog); System.out.println("dog序列化完成"); fr.close(); oos.close(); } @Test public void m2() throws IOException, ClassNotFoundException { String serFilePath = "d:\\test\\data.dat"; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(serFilePath)); Dog dog = (Dog)ois.readObject(); System.out.println(dog); ois.close(); } } class Dog implements Serializable{ private String name; private int age; private String color; public Dog(String name, int age, String color) { this.name = name; this.age = age; this.color = color; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + ", color='" + color + '\'' + '}'; } }