(遇见异常直接抛,默认采用alt+enter提示的第一种方式处理异常)
什么是I/O流:存储和读取数据的解决方案
按照流向区分:
其他设备
上读取到内存
中的流。内存
中写出到其他设备
上的流。按照操作文件的类型分:
用windows系统自带的记事本打开且能读懂的文件为纯本文文件,包括txt文件,md文件,xml文件,lrc文件,等等…
FileOutStream:字节输出流
FileOutStream:可以把程序中的数据写到本地文件上,是字节流的基本流。
创建字节输出流对象
细节1:参数是字符串表示的路径或者是File对象都是可以的
细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的。
细节3:如果文件已经存在,则会清空文件.
(如果文件已经存在内容,则会清空文件原有内容,然后写入的新内容)
写数据
write方法的参数是整数,但是实际上写到本地文件中的是整数在ASCII上对应的字符
释放资源
每次使用完流之后都要释放资源,解除占用
方法名 | 说明 |
---|---|
void write(int b) | 一次写一个字节数据 |
void write(byte[] b) | 一次写一个字节数组数据 |
void write(byte[] b, int off, int len) | 一次写一个字节数组的部分数 |
import java.io.FileOutputStream;
import java.io.IOException;
public class Test01 {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("code_java02\\kwh.txt");
byte[] bytes = {97,98,99};
fos.write(97);// a
fos.write(bytes);// a b c
fos.write(bytes,0,2);// a b
fos.close();
}
}
import java.io.FileOutputStream;
import java.io.IOException;
public class Test02 {
public static void main(String[] args) throws IOException {
//默认false:关闭续写,会清空文件
// true:打开续写开关,不会清空文件
FileOutputStream fos = new FileOutputStream("code_java02\\kwh.txt",true);
String str = "nihao";
// 将字符串编程字节数组
byte[] bytes1 = str.getBytes();
fos.write(bytes1);
// 换行
String str2 = "\r\n";
byte[] bytes2 = str2.getBytes();
fos.write(bytes2);
String str3 = "tianqihenhao";
byte[] bytes3 = str3.getBytes();
fos.write(bytes3,0,bytes3.length);
fos.close();
}
}
FileInputStream:字节输入流
操作本地的字节输入流,把本地文件的数据读取到程序中。
创建字节输入流对象
如果文件不存在,就直接报错。
读数据
一次读一个字节,读出来的是数据在ASCII上对应的数字
读到文件末尾处没有数据,read方法返回-1
释放资源
import java.io.FileInputStream;
import java.io.IOException;
public class Test03 {
public static void main(String[] args) throws IOException {
// 创建字节输入流对象; kwh.txt里有abc
FileInputStream fis = new FileInputStream("code_java02\\kwh.txt");
// 读数据
int read = fis.read();
System.out.println(read);//97
fis.close();
}
}
一次循环读取一个字节
import java.io.FileInputStream;
import java.io.IOException;
public class Test04 {
public static void main(String[] args) throws IOException {
// 创建对象 kwh.txt里有abc
FileInputStream fls = new FileInputStream("code_java02\\kwh.txt");
// 定义变量,记录读取的数据
int b ;
// b =fls.read();
// System.out.println(b);//97
// 循环读取
//read :表示读取数据,而且是读取一个数据就移动一次指针
while ((b =fls.read()) != -1){
System.out.print((char) b);
}
// 释放资源
fls.close();
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test05 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("E:\\software\\ideak\\ideapro\\kwhcode\\code_java02\\kkk.txt");
FileOutputStream fos = new FileOutputStream("code_java02\\www.txt");
// 定义变量,记录读取的数据
int b;
// 边读边写
//一次读写一个字节
while ((b= fis.read()) != -1){
fos.write(b);
}
// 释放资源
fis.close();
fos.close();
}
}
方法 | 说明 |
---|---|
public in read() | 一次读取一个字节 |
public int read(byte[] buffer) | 一次读一个字节数组数据 |
import java.io.FileInputStream;
import java.io.IOException;
public class Test06 {
public static void main(String[] args) throws IOException {
// kwh.txtl里有abc
FileInputStream fis = new FileInputStream("code_java02\\kwh.txt");
// 定义一个长度为2的字符数组,表示每次读取2个字节
//将读到的数据再返回到数组bytes中
byte[] bytes = new byte[2];
//一次读取多个字节数据,具体读多少,跟数组的长度有关
//返回值:本次读取到了多少个字节数据
int len1 = fis.read(bytes);
System.out.println(len1);//2
//将bytes数组从0索引开始,一共把len1个字节变成字符串
String str1 = new String(bytes,0,len1);
System.out.println(str1);//ab
int len2 = fis.read(bytes);
System.out.println(len2);// 1
String str2 = new String(bytes,0,len2);
System.out.println(str2);//c
// int len3 = fis.read(bytes);
// System.out.println(len3);//-1
// String str3 = new String(bytes);
// System.out.println(str3);//cb
fis.close();
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test07 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("E:\\software\\ideak\\ideapro\\kwhcode\\code_java02\\hhh.txt");
FileOutputStream fos = new FileOutputStream("code_java02\\hhh02.txt");
byte[] bytes = new byte[1024 * 1024 * 5];
// 定义要读取的数据的长度,即字节数
int len;
while ((len = fis.read(bytes)) != -1){
// 都多少写多少
fos.write(bytes,0 ,len);
}
//释放资源
fos.close();
fis.close();
}
}
FileReader:字符输入流
使用场景:对纯文本文件进行读写操作。
字符流的底层就是字节流
字符流 = 字节流+字符集
特点:
创建字符输入流对象
构造方法 | 说明 |
---|---|
public FileReader(File file) | 创建字符输入流关联本地文件 |
public FileReader(String Path) | 创建字符输入流关联本地文件 |
如果文件不存在,就直接报错。
读取数据
成员方法 | 说明 |
---|---|
public int read() | 读取数据,读到末尾返回-1 |
public int read(char[] buffer) | 读取多个数据,读到末尾返回-1 |
细节1: 按照字节进行读取,遇到中文,一次读多个字节。读取后解 码。返回一个整数。
细节2: 读到文件末尾,read方法返回-1
释放资源
import java.io.FileReader;
import java.io.IOException;
public class Test09 {
public static void main(String[] args) throws IOException {
// 创建字符输入流对象
FileReader fr = new FileReader("code_java02\\a.txt");
// 定义读取的字节数
// // 记录读取的汉字解码后的十进制数
int ch;
//2.读取数据 read()
//字符流的底层也是字节流,默认也是一个字节一个字节的读取的。
//如果遇到中文就会一次读取多个,GBK一次读两个字节,UTF-8一次读三个字节
//read()细节:
//1.read():默认也是一个字节一个字节的读取的,如果遇到中文就会一次读取多个
//2.在读取之后,方法的底层还会进行解码并转成十进制。
// 最终把这个十进制作为返回值
// 这个十进制的数据也表示在字符集上的数字
// 英文:文件里面二进制数据 0110 0001
// read方法进行读取,解码并转成十进制97
// 中文:文件里面的二进制数据 11100110 10110001 10001001
// read方法进行读取,解码并转成十进制27721
// 想看到中文汉字,就是把这些十进制数据,再进行强转就可以了
// 循环读取
while ((ch = fr.read()) != -1){
// System.out.println(ch);十进制数
//把解码出的十进制数强转成对应的字符
System.out.print((char) ch);
}
// 释放资源
fr.close();
}
}
import java.io.FileReader;
import java.io.IOException;
public class Test10 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("code_java02\\a.txt");
// 记录读取的个数
int len;
// 一次读取两个,并把数据返回到chars数组里
char[] chars = new char[2];
//read(chars):读取数据,解码,强转三步合并了,把强转之后的字符放到数组当中
//相当于空参的read + 强转类型转换
while ((len = fr.read(chars)) != -1){
// System.out.println(len);//2
// 将读取的数据放到chars数组后变成字符串输出
System.out.print(new String(chars));
}
fr.close();
}
}
FileWriter:字节输出流
构造方法 | 说明 |
---|---|
public FileWriter(File file) | 创建字符输出流关联本地文件 |
public FileWriter(String pathname) | 创建字符输出流关联本地文件 |
public FileWriter(File file, boolean append) | 创建字符输出流关联本地文件,续写 |
public FileWriter(String pathname, boolean append) | 创建字符输出流关联本地文件,续写 |
成员方法 | 说明 |
---|---|
void write(int c) | 写出一个字符 |
void write(String str) | 写出一个字符串 |
void write(String str, int off, int len) | 写出一个字符串的一部分 |
void write(char[] cbuf) | 写出一个字符数组 |
void write(char[] cbuf, int off, int len) | 写出字符数组的一部分 |
import java.io.FileWriter;
import java.io.IOException;
public class Test11 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("code_java02\\a.txt",true);
//根据字符集进行编码,编码成三个字节写入文件
fw.write(25105);
fw.write("你好");
char[] chars = {'今','天','好'};
fw.write(chars);
fw.write(chars,0,1);
fw.write(chars,1,2);
String str = "苹果葡萄";
fw.write(str,0,2);
fw.close();
}
}
高级流
原理:底层自带了长度为8192的缓冲区提高性能。
方法名称 | 说明 | |
---|---|---|
public BufferedInputStream(InputStream is) | 把基本流包装成高级流,提高数去数据性能 | |
public BufferedOutputStream(OutputStream os) | 把基本流包装成高级流,提高数去数据性能 | |
字节缓冲输入流的构造方法:
public BufferedInputStream(InputStream is)
字节缓冲输出流的构造方法:
public BufferedOutputStream(OutputStream os)
一次读写一个字节
import java.io.*;
public class Test01 {
public static void main(String[] args) throws IOException {
//利用字节缓冲流拷贝文件
//将a.txt里的内容写到aa.txt,aa.txt不存在
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("code_java02\\filedemo\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("code_java02\\filedemo\\aa.txt"));
// 记录读取的数据,一次读写一个字节
int b;
// 循环读取,读取的是缓冲区中数据,一次性读取8192个字节数据
while ((b= bis.read()) != -1){
// 将读取的数据再写入目的地
bos.write(b);
}
// 关闭流
bos.close();
bis.close();
}
}
一次读写多个字节
package bufferedstreamdemo;
import java.io.*;
public class Test02 {
public static void main(String[] args) throws IOException {
// 创建缓冲流对象
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("code_java02\\filedemo\\a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("code_java02\\filedemo\\a2.txt"));
// 定义数组,将读取的数据存入字节数组
//一次读取多个字节
byte[] bytes = new byte[1024];
//记录读取的数据(字节)
int len;
// 循环将读取的字节数据写入字节数组
while ((len = bis.read(bytes)) != -1){
// 写入目的文件,一次写一个字节数组
bos.write(bytes,0,len);
}
// 关闭流
bos.close();
bis.close();
}
}
构造方法
方法名称 | 说明 | |
---|---|---|
public BufferedReader(Reader r) | 把基本流变成高级流 | |
public BufferedWriter(Writer r) | 把基本流变成高级流 | |
构造方法:
public BufferedReader(Reader r)
特有方法:
public String readLine() 读一整行
package bufferedstreamdemo;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Test03 {
public static void main(String[] args) throws IOException {
// 创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(
new FileReader("code_java02\\filedemo\\a.txt"));
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
// 释放资源
br.close();
}
}
构造方法:
public BufferedWriter(Writer r)
特有方法:
public void newLine() 跨平台的换行
package bufferedstreamdemo;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Test04 {
public static void main(String[] args) throws IOException {
// 创建字符输出流对象
//a3.txt 不存在则会直接创建
FileWriter fw = new FileWriter("code_java02\\filedemo\\a3.txt",true);
BufferedWriter bw = new BufferedWriter(fw);
// 写入内容
bw.write("数风流人物,还看今朝。");
// 换行
bw.newLine();
bw.write("俱往矣");
// 释放资源
bw.close();
}
}
高级流
字符转换输入流:InputStreamReader
字符转换输出流:OutputStreamWriter
是字符流和字节流之间的桥梁。
将字节流转换成字符流就可以拥有字符流的特性,同时字节流可以使用字符流中的方法。
字符流特性,比如:
示意图:
27.9.2.1test01
利用转换流按照指定字符编码读取
package convertstream;
import java.io.*;
public class Test01 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream( "code_java02\\filedemo\\gbkfile.txt");
// 创建转换流对象
InputStreamReader isr = new InputStreamReader(fis,"GBK");
int b;
while ((b = isr.read()) != -1){
System.out.print((char) b);
}
isr.close();
}
}
利用转换流按照指定字符编码写出
package convertstream;
import java.io.*;
public class Test03 {
public static void main(String[] args) throws IOException {
// gbkfile02.txt 不存在则创建
FileOutputStream fos = new FileOutputStream("code_java02\\filedemo\\gbkfile02.txt",true);
// 创建转换流对象
OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
osw.write("吃了么");
osw.close();
}
}
将本地文件中的GBK文件,转成UTF-8
package convertstream;
import java.io.*;
public class Test04 {
public static void main(String[] args) throws IOException {
// gbkfile03.txt 不存在 则创建
// 创建转换流读出
FileInputStream fis = new FileInputStream("code_java02\\filedemo\\gbkfile.txt");
InputStreamReader isr = new InputStreamReader(fis,"GBK");
// 创建转换流写入
FileOutputStream fos = new FileOutputStream("code_java02\\filedemo\\gbkfile03.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
//一次读写一个字节
// int b;
// while ((b=isr.read()) != -1){
// osw.write(b);
// }
//一次读写多个字节
char[] chars = new char[2];
int b;
while ((b = isr.read(chars)) != -1){
osw.write(chars);
}
osw.close();
isr.close();
}
}
利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码
package convertstream;
import java.io.*;
public class Test05 {
public static void main(String[] args) throws IOException {
/*
利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码
1.字节流在读取中文的时候,是会出现乱码的,但是字符流可以搞定
2.字节流里面是没有读一整行的方法的,只有字符缓冲流才能搞定
*/
// 创建字节流对象
FileInputStream fis = new FileInputStream("code_java02\\filedemo\\a.txt");
// 将字节流转换成字符流
InputStreamReader isr = new InputStreamReader(fis);
// 将字符流包装成字符缓冲流
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null){
System.out.println(line);
}
// 释放资源
br.close();
}
}
也叫 对象操作输出流
可以把Java中的对象写到本地文件中
高级流,也是用来包装基本流的
构造方法:
public ObjectOutputStream(OutputStream out)
把基本流变成高级流
成员方法:
public final void writeObject(Object obj) 把对象序列化(写出)到文件中去
//Student的标准JavaBean类
// Student实现Serializable接口
//Serializable接口里面是没有抽象方法,标记型接口一旦实现了这个接口,那 么就表示当前的Student类可以被序列化
//属性:学生姓名,学生年龄
=================================================
//测试类
package objectstream.test01;
import java.io.*;
public class StudentTest {
public static void main(String[] args) throws IOException {
// 创建学生对象
Student stu1 = new Student("小明",18);
// 创建序列化流的对象
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("code_java02\\filedemo\\objfile.txt"));
// 写出数据
oos.writeObject(stu1);
// 释放资源
oos.close();
}
}
也叫对象操作输入流,把序列化到本地文件中的对象读取到程序中。
构造方法:
public ObjectInputStream(InputStream out)
把基本流变成高级流
成员方法:
public Object readObject()
把序列化到本地文件中的对象,读取到程序中来
//同27.10中的JavaBean类
=================================================
package objectstream.test01;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class StudentTest02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 创建反序列流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("code_java02\\filedemo\\objfile.txt"));
// 读出数据
// Object o = ois.readObject();
//想看到真正的对象需要强转
Student stu = (Student) ois.readObject();
// 打印对象
System.out.println(o);
// 释放资源
ois.close();
}
}
化到本地文件中的对象读取到程序中。
构造方法:
public ObjectInputStream(InputStream out)
把基本流变成高级流
成员方法:
public Object readObject()
把序列化到本地文件中的对象,读取到程序中来
//同27.10中的JavaBean类
=================================================
package objectstream.test01;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class StudentTest02 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 创建反序列流对象
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("code_java02\\filedemo\\objfile.txt"));
// 读出数据
// Object o = ois.readObject();
//想看到真正的对象需要强转
Student stu = (Student) ois.readObject();
// 打印对象
System.out.println(o);
// 释放资源
ois.close();
}
}