先给各位读者致歉 笔者因身体抱恙 未能及时更新 以后会按时更新 和大家一起学习探究~
第15章 IO流
15.1 文件
文件就是保存数据的地方
文件流
15.2 常用文件操作
创建文件对象构造器和方法
import org.junit.Test; import java.io.File; import java.io.IOException; public class CreateFile { public static void main(String[] args) { CreateFile file=new CreateFile(); file.method1(); file.method2(); file.method3(); } @Test//file(String path) public void method1(){ String filePath="D:\\JavaProject\\test1129\\news1.txt"; File file=new File(filePath); try { file.createNewFile(); System.out.println("method1 success"); } catch (IOException e) { e.printStackTrace(); } } @Test//file(File parentFilePath,String filePath) public void method2(){ String parentFilePath="D:\\JavaProject\\test1129\\"; File parentFile=new File(parentFilePath); String filePath="news2.txt"; File file=new File(parentFile,filePath); try { file.createNewFile(); System.out.println("method2 success"); } catch (IOException e) { e.printStackTrace(); } } @Test//file(String parentFilePath,String filePath) public void method3(){ String parentfilePath="D:\\JavaProject\\test1129\\"; String filePath="news3.txt"; File file=new File(parentfilePath,filePath); try { file.createNewFile(); System.out.println("method3 success"); } catch (IOException e) { e.printStackTrace(); } } }
获取文件相关信息
import org.junit.Test; import java.io.File; public class FileInformation { public static void main(String[] args) { FileInformation file=new FileInformation(); file.info(); } //获取文件的信息 @Test public void info() { //先创建文件对象 File file = new File("e:\\news1.txt"); //注意,这里没有用createNewFile方法,因为这并不是在创建文件,而是创建这个已经存在的文件的一个对象,来对这个文件进行一些操作 //调用相应的方法,得到对应信息 System.out.println("文件名字=" + file.getName()); //getName、getAbsolutePath、getParent、length、exists、isFile、isDirectory System.out.println("文件绝对路径=" + file.getAbsolutePath()); System.out.println("文件父级目录=" + file.getParent()); System.out.println("文件大小(字节)=" + file.length()); System.out.println("文件是否存在=" + file.exists());//T System.out.println("是不是一个文件=" + file.isFile());//T System.out.println("是不是一个目录=" + file.isDirectory());//F } }
目录的操作和文件删除
import org.junit.jupiter.api.Test; import java.io.File; import java.io.InputStream; import java.io.OutputStream; public class Directory_ { public static void main(String[] args) {} //判断 d:\\news1.txt 是否存在,如果存在就删除 @Test public void m1() { String filePath = "e:\\news1.txt"; File file = new File(filePath); if (file.exists()) { if (file.delete()) { System.out.println(filePath + "删除成功"); } else { System.out.println(filePath + "删除失败"); } } else { System.out.println("该文件不存在..."); } } //判断 D:\\demo02 是否存在,存在就删除,否则提示不存在 //这里我们需要体会到,在java编程中,目录也被当做文件 @Test public void m2() { String filePath = "D:\\demo02"; File file = new File(filePath); if (file.exists()) { if (file.delete()) { System.out.println(filePath + "删除成功"); } else { System.out.println(filePath + "删除失败"); } } else { System.out.println("该目录不存在..."); } } //判断 D:\\demo\\a\\b\\c 目录是否存在,如果存在就提示已经存在,否则就创建 @Test public void m3() { String directoryPath = "D:\\demo\\a\\b\\c"; File file = new File(directoryPath); if (file.exists()) { System.out.println(directoryPath + "存在.."); } else { if (file.mkdirs()) { //创建一级目录使用mkdir() ,创建多级目录使用mkdirs() System.out.println(directoryPath + "创建成功.."); } else { System.out.println(directoryPath + "创建失败..."); } } } }
15.3 IO流原理 流的分类
15.4 IO流体系图 常用类
InputStream
import org.junit.jupiter.api.Test; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; /** * 演示FileInputStream的使用(字节输入流 文件--> 程序) */ public class FileInputStream_ { public static void main(String[] args) {} /** * 演示读取文件... * 单个字节的读取,效率比较低 * -> 使用 read(byte[] b) */ @Test public void readFile01() { String filePath = "D:\\JavaProject\\test1129\\news1.txt"; int readData = 0; FileInputStream fileInputStream = null; try { //创建 FileInputStream 对象,用于读取 文件 fileInputStream = new FileInputStream(filePath); //从该输入流读取一个字节的数据。 如果没有输入可用,此方法将阻止。 //如果返回-1 , 表示读取完毕 while ((readData = fileInputStream.read()) != -1) { System.out.print((char)readData);//转成char显示 } } catch (IOException e) { e.printStackTrace(); } finally { //关闭文件流,释放资源. try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 使用 read(byte[] b) 读取文件,提高效率 */ @Test public void readFile02() { String filePath = "D:\\JavaProject\\test1129\\news1.txt"; //字节数组 byte[] buf = new byte[8]; //一次读取8个字节. int readLen = 0; FileInputStream fileInputStream = null; try { //创建 FileInputStream 对象,用于读取 文件 fileInputStream = new FileInputStream(filePath); //从该输入流读取最多b.length字节的数据到字节数组。 此方法将阻塞,直到某些输入可用。 //如果返回-1 , 表示读取完毕 //如果读取正常, 返回实际读取的字节数 while ((readLen = fileInputStream.read(buf)) != -1) { System.out.print(new String(buf, 0, readLen));//显示 } } catch (IOException e) { e.printStackTrace(); } finally { //关闭文件流,释放资源. try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
FileOutputStream
import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class FileOutputStream01 { public static void main(String[] args) {} /** * 演示使用FileOutputStream 将数据写到文件中, * 如果该文件不存在,则创建该文件 */ @Test public void writeFile() { //创建 FileOutputStream对象 String filePath = "D:\\JavaProject\\test1129\\news2.txt"; FileOutputStream fileOutputStream = null; try { //得到 FileOutputStream对象 对象 //说明 //1. new FileOutputStream(filePath) 创建方式,当写入内容时,会覆盖原来的内容 //2. new FileOutputStream(filePath, true) 创建方式,当写入内容时,是追加到文件后面 //不带 append 时:1.不论创建文件字节输出流前磁盘上是否有该文件,最终都会通过当前字节文件输出流在磁盘上创建文件 2.覆盖的不是内容,而是直接替换文件。简而言之,如果不带 append 就是在磁盘上面新创建一个文件(不论是否已存在)然后打开操作,覆盖是发生在文件层面,而不是文件里面的内容;如果 true 就是打开磁盘上已有的文件在其内容末尾进行操作 fileOutputStream = new FileOutputStream(filePath, true); //写入一个字节 //fileOutputStream.write('H');// //写入字符串 String str = "byx,world!"; //str.getBytes() 可以把 字符串-> 字节数组 //fileOutputStream.write(str.getBytes()); /* write(byte[] b, int off, int len) 将 len字节从位于偏移量 off的指定字节数组写入此文件输出流 */ fileOutputStream.write(str.getBytes(), 0, 3); } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
import java.io.*; public class FileCopy { public static void main(String[] args) { //完成 文件拷贝,将 e:\\Koala.jpg 拷贝 c:\\ //思路分析 //1. 创建文件的输入流 , 将文件读入到程序 //2. 创建文件的输出流, 将读取到的文件数据,写入到指定的文件. String srcFilePath = "D:\\JavaProject\\test1129\\news1.txt"; String destFilePath = "D:\\JavaProject\\test1129\\news2.txt"; FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(srcFilePath); fileOutputStream = new FileOutputStream(destFilePath); //定义一个字节数组,提高读取效果 byte[] buf = new byte[1024]; int readLen = 0; while ((readLen = fileInputStream.read(buf)) != -1) { //读取到后,就写入到文件 通过 fileOutputStream //即,是一边读,一边写 fileOutputStream.write(buf, 0, readLen);//一定要使用这个方法 //这里写入并不会覆盖,因为没有关闭输出流 } System.out.println("拷贝ok~"); } catch (IOException e) { e.printStackTrace(); } finally { try { //关闭输入流和输出流,释放资源 if (fileInputStream != null) { fileInputStream.close(); } if (fileOutputStream != null) { fileOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
FileReader
import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class FileReader_ { public static void main(String[] args) {} /** * 单个字符读取文件 */ @Test public void readFile01() { String filePath = "D:\\JavaProject\\test1129\\news1.txt"; FileReader fileReader = null; int data = 0; //1. 创建FileReader对象 try { fileReader = new FileReader(filePath); //循环读取 使用read, 单个字符读取 while ((data = fileReader.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (fileReader != null) { fileReader.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 字符数组读取文件 */ @Test public void readFile02() { System.out.println("~~~readFile02 ~~~"); String filePath = "D:\\JavaProject\\test1129\\news1.txt"; FileReader fileReader = null; int readLen = 0; char[] buf = new char[8]; //1. 创建FileReader对象 try { fileReader = new FileReader(filePath); //循环读取 使用read(buf), 返回的是实际读取到的字符数 //如果返回-1, 说明到文件结束 while ((readLen = fileReader.read(buf)) != -1) { System.out.print(new String(buf, 0, readLen)); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (fileReader != null) { fileReader.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
FileWriter
import java.io.FileWriter; import java.io.IOException; public class FileWriter_ { public static void main(String[] args) { String filePath = "D:\\JavaProject\\test1129\\new1.txt"; //创建FileWriter对象 FileWriter fileWriter = null; char[] chars = {'a', 'b', 'c'}; try { fileWriter = new FileWriter(filePath);//默认是覆盖写入 // 3) write(int):写入单个字符 fileWriter.write('H'); // 4) write(char[]):写入指定数组 fileWriter.write(chars); // 5) write(char[],off,len):写入指定数组的指定部分 fileWriter.write("byx".toCharArray(), 0, 3); // 6) write(string):写入整个字符串 fileWriter.write(" 你好北京~"); fileWriter.write("风雨之后,定见彩虹"); // 7) write(string,off,len):写入字符串的指定部分 fileWriter.write("上海天津", 0, 2); //在数据量大的情况下,可以使用循环操作. } catch (IOException e) { e.printStackTrace(); } finally { //对应FileWriter , 一定要关闭流,或者flush才能真正的把数据写入到文件 //老韩看源码就知道原因. /* 看看源码 private void writeBytes() throws IOException { this.bb.flip(); int var1 = this.bb.limit(); int var2 = this.bb.position(); assert var2 <= var1; int var3 = var2 <= var1 ? var1 - var2 : 0; if (var3 > 0) { if (this.ch != null) { assert this.ch.write(this.bb) == var3 : var3; } else { this.out.write(this.bb.array(), this.bb.arrayOffset() + var2, var3); } } this.bb.clear(); } */ try { //fileWriter.flush(); //关闭文件流,等价 flush() + 关闭 fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println("程序结束..."); } }
15.5 节点流和处理流
节点流和处理流的区别和联系
BufferedReader
import java.io.FileNotFoundException; import java.io.FileReader; import java.io.BufferedReader; import java.io.IOException; class BufferedReader_{ public static void main(String[] args) throws IOException { String filePath="D:\\JavaProject\\test1129\\news1.txt"; BufferedReader br=new BufferedReader(new FileReader(filePath)); String line; while((line= br.readLine())!=null){ System.out.println(line); } br.close(); } }
BufferedWriter
import java.io.*; class BufferedReader_{ public static void main(String[] args) throws IOException { String filePath="D:\\JavaProject\\test1129\\news1.txt"; //创建BufferedWriter //说明: //1. new FileWriter(filePath, true) 表示以追加的方式写入 //2. new FileWriter(filePath) , 表示以覆盖的方式写入 BufferedWriter br=new BufferedWriter(new FileWriter(filePath)); br.write("hello,byx!"); br.newLine();//插入一个当前系统(windows、Linux等)对应的换行符 br.write("hello2, byx!"); br.newLine(); br.write("hello3, byx!"); br.newLine(); br.close(); } }
import java.io.*; class BufferedReader_{ public static void main(String[] args) throws IOException { String br_filePath="D:\\JavaProject\\test1129\\news1.txt"; String bw_filePath="D:\\JavaProject\\test1129\\news2.txt"; //创建BufferedWriter //说明: //1. new FileWriter(filePath, true) 表示以追加的方式写入 //2. new FileWriter(filePath) , 表示以覆盖的方式写入 BufferedReader br=null; BufferedWriter bw=null; String line=null; try{ bw=new BufferedWriter(new FileWriter(bw_filePath)); br=new BufferedReader(new FileReader(br_filePath)); while((line=br.readLine())!=null){ bw.write(line); bw.newLine(); } }catch(IOException e){ e.printStackTrace(); }finally{ //关闭流 try{ if(br!=null){ br.close(); } if(bw!=null){ bw.close(); } }catch(IOException e){ e.printStackTrace(); } } } }
BufferedInputStream
BufferedOutputStream
import java.io.*; /** * 演示使用BufferedOutputStream 和 BufferedInputStream使用 * 使用他们,可以完成二进制文件拷贝. * 思考:字节流可以操作二进制文件,可以操作文本文件吗?当然可以 */ public class BufferedCopy02 { public static void main(String[] args) { // String srcFilePath = "e:\\Koala.jpg"; // String destFilePath = "e:\\hsp.jpg"; // String srcFilePath = "e:\\0245_韩顺平零基础学Java_引出this.avi"; // String destFilePath = "e:\\hsp.avi"; String srcFilePath = "e:\\a.java"; String destFilePath = "e:\\a3.java"; //创建BufferedOutputStream对象BufferedInputStream对象 BufferedInputStream bis = null; BufferedOutputStream bos = null; try { //因为 FileInputStream 是 InputStream 子类 bis = new BufferedInputStream(new FileInputStream(srcFilePath)); bos = new BufferedOutputStream(new FileOutputStream(destFilePath)); //循环的读取文件,并写入到 destFilePath byte[] buff = new byte[1024]; int readLen = 0; //当返回 -1 时,就表示文件读取完毕 while ((readLen = bis.read(buff)) != -1) { bos.write(buff, 0, readLen); } System.out.println("文件拷贝完毕~~~"); } catch (IOException e) { e.printStackTrace(); } finally { //关闭流 , 关闭外层的处理流即可,底层会去关闭节点流 try { if(bis != null) { bis.close(); } if(bos != null) { bos.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
对象流
package com.hspedu.outputstream_;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 演示ObjectOutputStream的使用, 完成数据的序列化
*/
public class ObjectOutStream_ {
public static void main(String[] args) throws Exception {
//序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
String filePath = "e:\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到 e:\data.dat
oos.writeInt(100);// int -> Integer (实现了 Serializable)
oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
oos.writeChar('a');// char -> Character (实现了 Serializable)
oos.writeDouble(9.5);// double -> Double (实现了 Serializable)
oos.writeUTF("韩顺平教育");//String
//保存一个dog对象
oos.writeObject(new Dog("旺财", 10, "日本", "白色"));
oos.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
package com.hspedu.inputstream_;
import com.hspedu.outputstream_.Dog;
import java.io.*;
public class ObjectInputStream_ {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//指定反序列化的文件
String filePath = "e:\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//读取
//老师解读
//1. 读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致
//2. 否则会出现异常
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());
//dog 的编译类型是 Object , dog 的运行类型是 Dog
Object dog = ois.readObject();
System.out.println("运行类型=" + dog.getClass());
System.out.println("dog信息=" + dog);//底层 Object -> Dog//这里是特别重要的细节:
//1. 如果我们希望调用Dog的方法, 需要向下转型
//2. 需要我们将Dog类的定义放在可以引用的位置
Dog dog2 = (Dog)dog;
System.out.println(dog2.getName()); //旺财..
//关闭流, 关闭外层流即可,底层会关闭 FileInputStream 流
ois.close();
}
}
package com.hspedu.outputstream_;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* 演示ObjectOutputStream的使用, 完成数据的序列化
*/
public class ObjectOutStream_ {
public static void main(String[] args) throws Exception {
//序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
String filePath = "e:\\data.dat";
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到 e:\data.dat
oos.writeInt(100);// int -> Integer (实现了 Serializable)
oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
oos.writeChar('a');// char -> Character (实现了 Serializable)
oos.writeDouble(9.5);// double -> Double (实现了 Serializable)
oos.writeUTF("韩顺平教育");//String
//保存一个dog对象
oos.writeObject(new Dog("旺财", 10, "日本", "白色"));
oos.close();
System.out.println("数据保存完毕(序列化形式)");
}
}
标准输入输出流
转换流-InputStreamReader/OutputStreamWriter
a.txt默认是UTF-8编码,但如果改成其它编码(例如:ANSI(国标码,在中国windows系统下一般是GBK))后,运行程序输出的数据就会乱码
打印流 printstream/printwriter
package com.fsl; import java.io.IOException; import java.io.PrintStream; /** * 演示PrintStream (字节打印流/输出流) */ public class PrintStream_ { public static void main(String[] args) throws IOException { PrintStream out = System.out; //在默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器 /* public void print(String s) { if (s == null) { s = "null"; } write(s); } */ out.print("john, hello"); //因为print底层使用的是write , 所以我们可以直接调用write进行打印/输出,本质是一样的 out.write("你好".getBytes()); out.close(); //我们可以去修改打印流输出的位置/设备 //1. 输出修改成到 "e:\\f1.txt" //2. "hello, 韩顺平教育~" 就会输出到 e:\f1.txt //3. public static void setOut(PrintStream out) { // checkIO(); // setOut0(out); // native 方法,修改了out // } System.setOut(new PrintStream("e:\\f1.txt")); System.out.println("hello, 教育~"); } }
package com.hspedu.transformation; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; /** * 演示 PrintWriter 使用方式 */ public class PrintWriter_ { public static void main(String[] args) throws IOException { //PrintWriter printWriter = new PrintWriter(System.out); PrintWriter printWriter = new PrintWriter(new FileWriter("e:\\f2.txt")); printWriter.print("hi, 北京你好~~~~"); printWriter.close();//flush + 关闭流, 才会将数据写入到文件.. } }
15.6 Properties类 加载配置文件