IO流
I(input)O(output)。
流的分类:
- 按照读写方向,分为输入流和输出流。(在程序角度分析)
- 按照读写内容单位而言,分为字节流和字符流
- 按照流的功能不同,分为节点流和处理流
- 字节流:直接连接在文件上
- 处理流:嵌套在其它流上
流的家族体系
- | 输入 | 输出 |
字节流 | InputStream | OutputStream |
字符流 | Reader | Writer |
上面四个都是抽象类
对应文件流:
- 文件字节输入流 FileInputStream
- 文本字节输出流FileOutputStream
- 字符输入流:FileReader
- 字符输入流:FileWriter
File类
表示操作系统中的文件或者文件夹。
- 文件路径
- 绝对路径
- 相对路径
文件/文件夹基础操作
package eg01_file; import java.io.File; import java.io.IOException; public class Test1 { public static void main(String[] args) { boolean result = false; File file = new File("test01.txt"); // 该文件可有可无 try { result = file.createNewFile();//create a file. create file not folder System.out.println("文件创建"+ (result ?"成功":"失败")); System.out.println(file.getParent());// 拿到上一级文件夹路径 System.out.println(file.getParentFile());//拿到上一级文件夹的文件对象 file.mkdir();//创建单个文件夹。 file.mkdirs();//支持同时创建多级目录 result = file.renameTo(new File("test01_change.txt")); System.out.println("文件修改名称"+ (result ?"成功":"失败")); //查看相关 System.out.println(file.exists());//文件是否存在 System.out.println(file.isAbsolute());//是否是绝对路径 System.out.println(file.isDirectory());//是否是文件夹 System.out.println(file.isFile());//是否是文件夹 System.out.println(file.length());//查看文件大小 } catch (IOException e) { e.printStackTrace();//查看文件是否存在 } } }
创建文件的完整步骤
package eg01_file; import java.io.File; public class Test2 { public static void main(String[] args) { try{ File file = new File("abc/test2.txt"); //判断上层文件夹是否存在 File parentFile = file.getParentFile(); if(!parentFile.exists()){ //上层文件夹不存在,先创建 parentFile.mkdirs(); } //创建文件 file.createNewFile(); }catch (Exception e){ e.printStackTrace(); } } }
IO流 - 节点流
读入文件一个字节(一个字节)
不能读取中文。中文是2个字节一个字
package eg02_io; import java.io.FileInputStream; import java.io.InputStream; public class TestFileInputStream { public static void main(String[] args) { //创建流 try { InputStream fis = new FileInputStream("test01.txt"); //---------------------------------------------- int result = fis.read();//读出来的是字符ASCII码 System.out.println((char) result);//强制转换 //---------------------------------------------- } catch (Exception e) { e.printStackTrace(); } } }
[FileInputStream]字节数组的方式读取(读取全部内容)
package eg02_io; import java.io.FileInputStream; import java.io.InputStream; public class TestFileInputStream { public static void main(String[] args) { //创建流 try { InputStream fis = new FileInputStream("test01.txt"); byte[] bs = new byte[1024];//一次读kb int len = fis.read(bs);//读出来的是字节数组。返回值为读取的字节数量。 System.out.println(new String(bs, 0, len));//字节数组转为字符 } catch (Exception e) { e.printStackTrace(); } } }
[FileInputStream]读取文件最重要的一套写法
package eg02_io; import java.io.FileInputStream; import java.io.InputStream; public class TestFileInputStream { public static void main(String[] args) { //创建流 try { InputStream fis = new FileInputStream("test01.txt"); byte[] bs = new byte[1024];//一次读kb int len = 0; while ((len = fis.read(bs)) != -1) {// 不等于-1表示没读完,便继续读取。 //该写法仅限于IO流使用,其他地方不要用。 String s = new String(bs, 0, len); System.out.println(s); } //关流 fis.close(); } catch (Exception e) { e.printStackTrace(); } } }
[FileoutputStream]向文件写入内容
package eg02_io; import java.io.File; import java.io.FileOutputStream; public class TestFileOutputStream { public static void main(String[] args) { try { FileOutputStream fos = new FileOutputStream(new File("test01.txt"), true);//true追加。则不会清空原有数据 fos.write("牛啊牛啊,醉酒的向日狼".getBytes()); fos.flush(); fos.close(); } catch (Exception e) { e.printStackTrace(); } } }
[FileReader]读入文件一个字符(两个字节)
package eg02_io; import java.io.File; import java.io.FileReader; public class TestFileReader { public static void main(String[] args) { try { FileReader fr = new FileReader(new File("test01.txt")); int i = fr.read();//以字符为单位。 System.out.println((char) i); } catch (Exception e) { e.printStackTrace(); } } }
[FileReader]读入文件所有字符
package eg02_io; import java.io.File; import java.io.FileReader; public class TestFileReader { public static void main(String[] args) { try { FileReader fr = new FileReader(new File("test01.txt")); char[] cs = new char[1024]; int len = fr.read(cs); System.out.println(new String(cs, 0, len)); } catch (Exception e) { e.printStackTrace(); } } }
对于存在大量内容需要读取时的写法
package eg02_io; import java.io.File; import java.io.FileReader; public class TestFileReader { public static void main(String[] args) { try { FileReader fr = new FileReader(new File("test01.txt")); char[] cs = new char[1024]; int len = 0; while ((len = fr.read(cs)) != -1) { System.out.println(new String(cs, 0, len)); } fr.close(); } catch (Exception e) { e.printStackTrace(); } } }
[FileWriter]向文件写入内容
package eg02_io; import java.io.File; import java.io.FileWriter; public class TestFileWriter { public static void main(String[] args) { try { FileWriter fw = new FileWriter(new File("test01.txt"), true);//追写则true fw.write("刑啊,太刑了。"); fw.flush(); fw.close(); } catch (Exception e) { e.printStackTrace(); } } }
如何选择流?
字节流:常用于读取非文本文件
字符流:常用于读取文件中的文字信息
IO流练习:复制图片操作
选择的流:字节流
package eg03_copypic; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class test3 { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream(new File("1.jpg")); FileOutputStream fos = new FileOutputStream(new File("2.jpg"),true); byte[] bs = new byte[1024]; int len = 0; while ((len = fis.read(bs))!=-1){ fos.write(bs,0,len); } fis.close(); fos.flush(); fos.close(); } }
如果不是复制,而是剪切
package eg03_copypic; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class test3 { public static void main(String[] args) throws IOException { File file = new File("2.jpg"); FileInputStream fis = new FileInputStream(file); FileOutputStream fos = new FileOutputStream(new File("3.jpg"),true); byte[] bs = new byte[1024]; int len = 0; while ((len = fis.read(bs))!=-1){ fos.write(bs,0,len); } fis.close(); fos.flush(); fos.close(); file.delete(); } }
IO流 - 处理流
缓冲流
缓冲流:带有缓冲区的数据流
重点是BufferedReader ,这是读取文本文件最好的方式
- BufferedInputStream
- BufferedOutputStream
- BufferedReader
- BufferedWirter
package eg04.buffer; import java.io.*; public class test04 { public static void main(String[] args) throws IOException { // BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("test01.txt"))); //一般不用 BufferedReader br = new BufferedReader(new FileReader(new File("test01.txt"))); // System.out.println(br.readLine()); //读取文本文件最好用的方法。 // System.out.println(br.readLine()); String str = ""; while ((str= br.readLine())!=null){ //读取内容 System.out.println(str); } br.close(); } }
转换流
字节流 ==> 字符流 :
- [输入] InputStreamReader
- [输出] OutputStreamWriter
package eg05_convert; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; public class test_out { public static void main(String[] args) throws IOException { // System.out.println(); Writer writer = new OutputStreamWriter(System.out); writer.write("abc路人甲"); writer.flush(); //writer.close();//有时候流不可以关,如果这里关了,后面的 System.out.println(); 也不会输出。 System.out.println("关闭了流"); } }
对象流
- ObjectInputStream
- ObjectOutputStream
[对象] Person.java
package eg06_obj; public class Person { private int id; private String name; private int age; public Person(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
[测试] test06.java
package eg06_obj; import java.io.*; public class test06 { public static void main(String[] args) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("person.data"))); Person p = new Person(1,"萌狼蓝天",18); oos.writeObject(p); oos.flush(); oos.close(); } }
[运行结果]报错
序列化:把一个对象转化为字节的过程
反序列化:把字节转化成对象
解决方案:在Java中只需要给类添加一个实现,Serialable。这样这个类就可以被序列化了。过程是全自动的。(实质:让数据可以进行序列化)
更改 Person.java
package eg06_obj; import java.io.Serializable; public class Person implements Serializable { private int id; private String name; private int age; public Person(int id, String name, int age) { this.id = id; this.name = name; this.age = age; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
此时运行,便不会报错。
那么如何读取呢?(反序列化)
package eg06_obj; import java.io.*; public class Test07 { public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("person.data"))); Object obj = ois.readObject(); Person p = (Person) obj; System.out.println(p.getName()); } }
文件修改操作
思路:偷梁换柱。逐行读取文件内容,将内容进行替换,将替换结果记录在一个新文件中,直到数据写入完毕,把源文件删除。
把新文件的名字改成源文件的名字
代码如下
package eg07_update; import java.io.*; import java.nio.Buffer; public class test7 { public static void main(String[] args) throws Exception { File res = new File("test.txt"); //没有test.txt需要先手动创建,内容如下 /** * 记录生活的博客:萌狼蓝天の小世界 - 萌狼蓝天 (mllt.cc) * * 记录学习笔记的博客:萌狼蓝天 - 博客园 (cnblogs.com) * * 分享信息技术相关内容的哔哩哔哩账号:萌狼蓝天的个人空间_哔哩哔哩_bilibili * * 分享个人生活的哔哩哔哩账号:醉酒的向日狼的个人空间_哔哩哔哩_bilibili * * 这四个网站是我主要活跃的网站 * * 其中,mllt.cc这个网站是搭建在我自己服务器的,也许我会因为续费不起服务器而在2023年的时候关闭这个网站。 * * 如果你想获取我的学习笔记,应该去看我的博客园 * * 如果你想观看我录制的计算机相关知识视频,应该去看萌狼蓝天的个人空间_哔哩哔哩_bilibili */ File new_res = new File("副本_test.txt"); BufferedReader br = new BufferedReader(new FileReader(res)); BufferedWriter bw = new BufferedWriter(new FileWriter(new_res)); String line = ""; while((line = br.readLine())!=null){ line = line.replace("萌狼蓝天","易水千"); bw.write(line); bw.newLine();//另起一行(换行) } br.close(); bw.flush(); bw.close(); //删除源文件 res.delete(); //重命名新文件 new_res.renameTo(res); } }
[运行结果]