Input 输入 Output输出
一.文件(File可以用来代表不存在的目录或文件,可以创建)
java.io.File 它是对应着实际的文件或者目录
New File(String 文件路径)
可以用/或者\\作为文件分隔符,不过为了通用可以使用File.separator获取不同操作系统的分隔符
文件的常用方法
isFile(); 判断是否是一个文件
isDirectory(); 判断文件是否是一个目录
mkdir(); 创建一个不存在的目录
mkdirs(); 创建多级目录
exists(); 用来判断一个文件是否存在
listFiles(); 得到一个目录下的所有子目录和文件
delete(); 理解删除文件
deleteOnExit(); 程序运行结束后删除文件
renameTo(); 重命名和移动
getAbsoluteFile(); 获得文件的绝对路径
二.IO流
Input 输入流: 从文件读取内容,文件对我就是输入流
Output 输出流:向文件中写入内容,文件对我就是输出流
InputStream 抽象类 –> FileInputStream 问价输入流
OutputStream 抽象类 ->FileOutputStream 文件输出流
字节流
InputStream
(*) FileInputStream 从文件读取字节
(*) BufferedInputStream 加入缓冲功能,提高文件的读取效率
ByteArrayInputStream 从字节数组变成输入流
OutputStream
(*) FileOutputStream 向文件写入字节
(*) BufferedOutputStream 加入缓冲功能, 提高文件的写入效率
ByteArrayOutputStream 把流的内容写入字节数组
PrintStream 实际上就是 System.out
字符流
Reader
(*) InputStreamReader 转换字节流为字符流
(*) BufferedReader 功能增强,以行为单位读取数据 (装饰器模式)
FileReader 是InputStreamReader子类,将字符编码固定为操作系统的默认编码,不能手工改动
Writer
(*) OutputStreamWriter 转换字节流为字符流
(*) PrintWriter 以行为单位写入数据
write 当成字符写入
print print就是将参数转为字符串后写入
FileWriter 是OutputStreamWriter的子类,也是固定了字符编码
文件的读取
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
//测试文件输入流,读取外部文件内容
public class FileInputStreamTest1 {
public static void main(String[] args) throws IOException {
//打开文件
File f = new File("F:\\学习练习\\javasePrac\\西部开源\\IO流\\src\\day16\\abc.txt");
//创建文件输入流对象
FileInputStream fis = new FileInputStream(f);
// 方式一:一个字节一个字节的读取
// while(true) {
// int r = fis.read();
// if(-1 == r) { //当文件读到尾时,跳出循环
// break;
// }
//
// System.out.print((char) r + " ");
// }
// 方式二:将读入的内容转为数组,然后输出
while(true) {
byte[] by = new byte[100];
int r = fis.read(by);
if(-1 == r) {
break;
}
System.out.println(Arrays.toString(by));
}
}
}
文件的写入
1.创建输出流
FileOutputStream fos = new FileOutputStream(“文件名”);
2.向输出流中写入数据
fos.write(97);;
3.关闭输出流
fos.close();
文件的复制
import java.io.*;
public class Test
{
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("1.txt");
FileOutputStream fos = new FileOutputStream("3.txt");
while(true) {
byte[] buf = new byte[1024];
int len = fis.read(buf);
if(len == -1) {
break;
}
fos.write(buf, 0, len); // 实际读到len个字节,就写入len个字节
}
fis.close();
fos.close();
}
}
2.用Files的copy方法,参数1是被拷贝的文件,参数2 是拷贝后的文件
三.字符流
以字符为单位处理流的内容
Reader 字符输出流, InputStreamReader
Writer 字符输出流 OutputStreamWriter
- 先创建字节流文件
- 将字节流文件转为字符流
- 读取(注意转成char类型)
- 关闭,只需要关闭外层的流即可,内部会帮我们关掉内层的
import java.io.*;
import java.util.*;
public class Test
{
public static void main(String[] args) throws IOException {
// 1. 将字节流转换为字符流
FileInputStream fis = new FileInputStream("1.txt");
// 注意:实际文件编码要与读取时的文件编码一致
InputStreamReader reader = new InputStreamReader(fis, "utf-8");
// 2. 读取
/*while(true) {
int c = reader.read();
if(c == - 1) {
break;
}
System.out.println((char)c);
}*/
while(true) {
char[] buf = new char[1024];
int len = reader.read(buf);
if(len == -1) {
break;
}
System.out.println(Arrays.toString(buf));
}
// 3. 关闭, 只需要关闭外层的流, 内部会帮我们关掉内层的流
reader.close();
}
}
BufferedReader是在InputStreamReader的基础上以行为单位处理字符流,两者之间是平级关系,父类都是Reader(装饰者模式)
import java.io.*;
import java.util.*;
public class Test
{
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("1.txt");
InputStreamReader reader = new InputStreamReader(fis, "utf-8");
BufferedReader reader2 = new BufferedReader(reader);
/*System.out.println(reader2.readLine()); // 以行为单位读取数据
System.out.println(reader2.readLine()); // 以行为单位读取数据
System.out.println(reader2.readLine()); // 以行为单位读取数据*/
while(true) {
String line = reader2.readLine();
if(line == null) {
break;
}
System.out.println(line);
}
reader2.close();
}
}
装饰者模式:
装饰者与被装饰者需要有一个共同的父类
装饰者和被装饰者之间体现的是组合的关系,而不是继承的关系,目的是为了更加灵活
装饰者会对被装饰者做功能上的增强
四.java中的序列化和反序列化
序列化
将对象中的信息永久保存
1.将对象信息存入数据库
2.java中提供的序列化方式来永久保存数据
import java.io.*;
//如果没有实现Serializable接口,会出现NotSerializableException异常
class Student implements Serializable{
private int id;
private String name;
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 class Test
{
public static void main(String[] args) throws Exception {
Student student = new Student();
student.setId(1);
student.setName("张三");
// 序列化就是将对象变为输出字节流
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("d:\\student.obj"));
os.writeObject(student);
os.close();
}
}
注意:
要求对象中的所有属性也都是可以序列化
如果某个属性不想序列化,可以在属性上加"transient"关键字
反序列化
把字节内容读取进来,还原为java对象
ObjectInputStream用来读取字节内容,还原(反序列化)为java对象
import java.io.*;
class Student implements Serializable{
private int id;
private String name;
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 class Test
{
public static void main(String[] args) throws Exception {
ObjectInputStream is = new ObjectInputStream(new FileInputStream("d:\\student.obj"));
Student s = (Student)is.readObject();
System.out.println(s.getId());
System.out.println(s.getName());
System.out.println(s.getAddress());
}
}
除了可以写入和读取对象以外,还可以写入和读取基本类型(int,long,boolean...) ,读取和写入的顺序要保持一致
如果不一致,出现EOFException
如果没有更多内容,也会出现EOFException
建议在写入时最后一个对象使用null,这样读取时就可以根据null来判断是否读取完毕