16.IO流(字节流,字符流,数据流、对象流)
I/O框架
1. IO框架介绍
I:input
O:output
流:
按数据流向划分:输入流、输出流
按处理单元划分:字节流,字符流
2. File类
2.1 File类构造方法
File类提供了用于操作文件和获取文件信息的一系列方法
1.File类的构造方法:
File(String pathname) :
File(File parent, String child): 根据父类路径名与子类路径名字字符串创建新的file实例(便于先处理父类路径);
File(String parent, String child): 与上式类似
2.2 File类常用方法(增删改查)
1.创建:
createNewFile()
mkdir() 创建文件夹
mkdirs() 创建多级文件夹,用\\或/隔开
renameTo(File dest) 重命名文件或文件夹,如果目标文件与源文件是在同一个路径下,那么renameTo的作用是重命名,如果目标文件与源文件不是在同一个路径下,那么renameTo的作用就是剪切,而且还不能操作文件夹。
注:
separatorChar:目录分隔符
separator包含一个separatorChar,字符串形式。
均是静态,File类直接调用
new File("C:" + File.separator + "a.txt");
2.删除:
delete() 删除文件或一个空文件夹(非空不能删),有返回值
deleteOnExit() 保证程序异常时创建的临时文件也可以被删除,无返回值,一般用于删除临时文件
3.判断
exists()
isFile()
isDirectory()
isAbsolute() 测试此抽象路径名是否为绝对路径名。
4.获取
getName()
getPath()
getAbsolutePath()
length()
lastModified() 获取最后一次被修改的时间(毫秒值)。
/**
* File类 提供了文件和目录相关的操作的方法
* 位于java.io包
* @author asus
*
*/
public class TestFile {
public static void main(String[] args) {
File file = new File("A");
file.mkdir(); // 创建一个文件夹
File files = new File("B/C/D");
files.mkdirs();
file.delete();
files.delete(); // B 文件夹中有内容 不能删除
File file1 = new File("a.txt"); // 相对路径 相对于我们当前操作的目录而言的路径
File file2 = new File("C:\\Users\\WHD\\Desktop\\test.txt"); // 绝对路径 具体的路径
try {
file1.createNewFile(); // 返回值 true表示创建成功 false表示创建失败
file2.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("a.txt文件是否存在" + file1.exists());
System.out.println("a.txt文件的相对路径" + file1.getPath());
System.out.println("a.txt文件的绝对路径" + file1.getAbsolutePath());
System.out.println("a.txt文件的大小" + file1.length());
System.out.println("a.txt文件的名称" + file1.getName());
System.out.println("a.txt是否是一个文件" + file1.isFile());
System.out.println("a.txt是否是一个文件夹" + file1.isDirectory());
System.out.println("是否删除成功" + file1.delete());
}
}
3.字节流
3.1 FileInputStream
父类abstract InputStream
子类FileInputStream:基于字节的文件输入流
int read():每次读取一个字节,返回值是读取的内容的ascii码
int read(byte[] datas): 可以读取指定数组长度的内容,返回值是每次读取的长度,读取的内容存放在数组中,可以使用String类构造方法来封装为字符串 new String(byte[], int offset, int length);
int available(): 可读取的剩余字节数,即容量
/**
* 字节输入流
* read() 每次读取一个字节
* read(byte[] datas) 读取一个byte数组 返回值是读取的长度
* @author asus
*
*/
public class TestFileInputStream3 {
public static void main(String[] args) throws IOException {
File file = new File("a.txt");
file.createNewFile();
FileInputStream fis = new FileInputStream(file);
System.out.println(fis.available());
// byte [] datas = new byte[100];
byte [] datas = new byte[fis.available()];
int dataCount = -1;
while((dataCount = fis.read(datas)) != -1){
// System.out.println(dataCount);
System.out.println(new String(datas, 0, dataCount));
}
}
}
3.2 FileOutputStream
父类 abstract OutputStream
void write():每次写入一个字节
void write(byte[] datas):写入一个byte数组,可以使用String类的getBytes()方法将字符串转换为byte数组
支持的参数为byte数组和int
flush() :将内容从缓存中刷新到文件中。close会自动调用。字节流中不是必须的,但字符流必须刷新
close():关闭资源
/**
* 字节输出流
* @author asus
*
*/
public class TestFileOutPutStream2 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("c.txt", true);
String str = "床前明月光,疑是地上霜,举头望明月,低头思故乡";
byte [] datas = str.getBytes();
fos.write(97);
fos.write(datas);
fos.flush(); // 将缓存中的内容刷新到文件
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.字符流
字符流若未关闭资源,必须手动调用flush,否则不会写出资源
4.1输入字符流(3种,含缓冲流Bufferedxxx)
父类:abstract Reader
1.子类FileReader:基于字符的文件输入流
int read():每次读取一个字符
int read(char[] datas):每次读取char数组长度的内容,返回值是读取的长度,读取的内容存放在数组中。(若要直接打印,可能出现字节增大,但也可以通过设置数组长度为available避免),最好的方式是new一个新的String来输出。
2.子类:BufferedReader:基于字符的输入缓冲流
在以上方法的基础上还有:
readLine() :每次读取一行
close():关闭资源
3.子类: inputStreamReader:可以指定编码格式的字符输入流
(字节流到字符流的桥梁,BufferedReader创建时需要Reader,InputStreamReader即是Reader的子类,可传它,且InputStreamReader创建时可传字节流) 多态
/**
* 字符读取流 一次读取一个字符 也可以读取一个字符数组
* 字符是16位 unicode编码
* 字节 8位 byte ascii
* @author asus
*/
public class TestFileReader2 {
public static void main(String[] args) {
FileReader fReader = null;
try {
fReader = new FileReader("c.txt");
char [] datas = new char[100];
int dataCount = -1;
while((dataCount = fReader.read(datas)) != -1){
//System.out.println(dataCount);
//System.out.println(datas);//若字符长度设为available即,剩余字节数,可正常打印,
//否则可能打印多余的内容。即最后一次未读满,倒数第二次读的部分内容仍被输出
System.out.println(new String(datas,0,dataCount));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fReader != null){
try {
fReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 带有缓冲流的字符读取流
* 可以读取一个字符 也可以一次读取一行
* readLine()
* @author asus
*
*/
public class TestBufferedReader2 {
public static void main(String[] args) {
FileReader fr = null;
BufferedReader bReader = null;
try {
fr = new FileReader("c.txt");
bReader = new BufferedReader(fr);
int data = -1;
while((data = bReader.read()) != -1){
System.out.println((char)data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(bReader != null){
try {
bReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fr != null){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 乱码出现的原因:
* 编码的方式和解码的方式不一致
* 解决方式:
* 1.统一编码
* 2.可以将出现乱码的内容打散(iso-8859-1) 按照我们自己的编码方式组合
* 常见的编码格式:
* GBK 国标扩展板 简体和繁体
* GB2312 国标版本 只支持简体
* ISO-8859-1 最原始的编码方式 通常用于解决乱码
* UTF-8 unicode万国码 包含世界大多数国家的语言编码
* ANSI 不具体指定某一种编码 因为在不同的操作系统上 表示对应的编码 比如 win10中文版 GBK
* @author asus
*/
public class TestInputStreamReader {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("testCode.txt");
InputStreamReader isr = new InputStreamReader(fis,"GBK");
char []datas = new char[100];
int dataCount = -1;
while((dataCount = isr.read(datas)) != -1) {
System.out.println(new String(datas,0,dataCount));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
// 关闭资源
}
}
}
4.2输出字符流(3种,含缓冲流Bufferedxxx)
父类:abstract writer
1.子类:FileWriter
new实例时末尾添加true,表示在文本末尾追加内容
writer() : 每次写入一个字符
write(char [] datas):每次写入一个char数组
write(String str):每次写入一个字符串
2.子类:BufferedWriter
write():每次写入一个字符
write(char[] datas):每次写入一个char数组
write(String str) 每次写入一个字符串,也可设置起始位置
newLine():换行
3.子类:OutputStreamWriter 可指定编码的字符输出流
(字节流到字符流的桥梁,BufferedWriter创建时需要Writer,OutputStreamWriter即是Writer的子类,可传它,且OutputStreamWriter创建时可传字节流)
write():每次写入一个字符
write(char [] datas):每次写入一个char数组
write(String str):每次写入一个字符串,也可设置起始位置
/**
* 字符缓冲流写入流
* 可以写入一个字符 或者字符串
* 还可以换行
* newLine()
* @author asus
*
*/
public class TestBufferedWritet {
public static void main(String[] args) {
FileWriter fWriter = null;
BufferedWriter bWriter = null;
try {
fWriter = new FileWriter("e.txt",true);
bWriter = new BufferedWriter(fWriter);
bWriter.write("hello word1");
bWriter.newLine();
bWriter.write("hello world2");
bWriter.flush();//与字节流不同。。。不刷新或关闭资源不显示
} catch (IOException e) {
e.printStackTrace();
}finally {
if(bWriter !=null){
try {
bWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fWriter != null){
try {
fWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* @author asus
*/
public class TestFileWriter {
public static void main(String[] args) {
FileWriter fWriter =null;
try {
fWriter = new FileWriter("d.txt", true);
fWriter.write("hello word2\n");
// 将缓存中的内容刷新到文件
fWriter.flush();//与字节流不同,若为关闭资源,必须刷新内容,否则不显示
} catch (IOException e) {
e.printStackTrace();
}finally{
/*if(fWriter != null){
try {
fWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}*/
}
}
}
public class TestOutputStreamWriter {
public static void main(String[] args) {
FileOutputStream fos;
try {
fos = new FileOutputStream("f.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write("hello world");
osw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
5.数据流(二进制,依赖并属于字节流)
数据流属于字节流,用于读取二进制文件,比如图片、音频、视频等。。。。。
DataInputStream:基于字节的二进制文件输入流,读入只有byte存
DataOutputStream:基于字节的二进制文件输出流,输出有byte数组,或字符串,或字符多种形式
/**
* DataInputStream 负责读取二进制文件
* DataOutPutStream 负责写入二进制文件
* @author asus
*/
public class TestDataStream {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
DataInputStream dis = null;
DataOutputStream dos = null;
try {
fis = new FileInputStream("D:\\图片.png");
dis = new DataInputStream(fis);
fos = new FileOutputStream("copy2.png");
dos = new DataOutputStream(fos);
byte [] datas = new byte[fis.available()];
int dataCount = -1;
while((dataCount = dis.read(datas)) != -1){
//dos.write(datas, 0, dataCount);
dos.write(datas);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭资源
}
}
6.对象流(依赖并属于字节流)
对象流属于字节流,用于输入对象和输出对象
ObjectOutputStream-序列化:将对象以二进制的形式存储在文件中 readObject()
ObjectInputStream-反序列化:将保存有对象的二进制文件读取出来转换为对象 writeObject
序列化要求:被序列化的对象必须实现Serializable接口,此接口是空接口,相当于一个标识,实现此接口的类才可以序列化
/**
* ObjectInputStream 对象输入流
* ObjectOutputStream 对象输出流
* 序列化:将对象写入到文件中
* 反序列化:将存有对象的文件读取出来生成对象
* @author asus
*
*/
public class TestObjectStream {
public static void main(String[] args) {
FileOutputStream fos = null;
ObjectOutputStream oos = null;
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fos = new FileOutputStream("stu.txt");
oos = new ObjectOutputStream(fos);
Student stu1 = new Student("赵四", 20);
Student stu2 = new Student("广坤", 21);
Student stu3 = new Student("大拿", 22);
oos.writeObject(stu1);
oos.writeObject(stu2);
oos.writeObject(stu3);
fis = new FileInputStream("stu.txt");
ois = new ObjectInputStream(fis);
while(fis.available() > 0){
Object obj = ois.readObject();
if(obj instanceof Student){
Student stuRead = (Student) obj;
System.out.println(stuRead);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭资源
}
}
/**
* Serializeable 空接口 相当于一个标识 标识此接口的类才能被序列化化
* @author asus
*/
public class Student implements Serializable{
private String name;
private int age;
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;
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
每日问题
1.判断是否是文件
2.判断是否是目录
3.判断是否存在
4.删除文件的方法
5.文件的相对路径
6.文件的绝对路径
7.FileInputStream是什么流?
8.字节写入流是哪个对象?
9.字节流写入的方法是什么,支持参数是什么?
10.FileInputStream如何使每次读取两个字节
11.读取图片应该使用什么对象?
12.BufferedReader独有的读取文件的方法是什么
13.什么是序列化,什么是反序列化,序列化的对象有什么要求
14.实现序列化的步骤是什么
15.写入对象使用哪个对象的哪个方法
16.读取一个对象是什么方法
解答:
1.判断是否是文件 isFile();
2.判断是否是目录 isDirectory();
3.判断是否存在 exists()
4.删除文件的方法 delete();
5.文件的相对路径 getPath();
6.文件的绝对路径 getAbsolutePath();
7.FileInputStream是什么流? 字节读取流
8.字节写入流是哪个对象? FileOutputStream
9.字节流写入的方法是什么,支持参数是什么?
write(); byte数组 int num 显示对应的ascii
10.FileInputStream如何使每次读取两个字节
byte [] datas = new byte[2]; read(byte[] datas); 返回值是每次读取的长度,内容存放在datas数组中
11.读取图片应该使用什么对象? DataInputStream
12.BufferedReader独有的读取文件的方法是什么 readLine();
13.什么是序列化,什么是反序列化,序列化的对象有什么要求
将对象以二进制的形式存储在 文件中 将存储有对象的二进制文件读取出来转化为对象 实现Serializable
14.实现序列化的步骤是什么
先实现Serializable接口,然后使用ObjectOutputStream写入对象,再使用 ObjectInputStream读取对象 15.写入对象使用哪个对象的哪个方法 使用ObjectOutputStream写入对象,writeObject()
16.读取一个对象是什么方法 readObject();
上一篇: Mybatis入门学习笔记1
下一篇: 反射-通过反射来调用方法