【Java高级编程】IO流学习笔记
目录
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);
}
}
[运行结果]