IO框架
一.框架介绍
1.I:input:输入
2.o:output:输出
3.流向划分:输入输出
单元划分:字节流,字符流
二.File类
1.File类提供了用于操作文件和获取文件信息的一些列方法,可以直接在main方法中进行定义File类,然后用file调用mkdir方法创建文件夹
2.创建多个文件夹定义是使用有参构造,传入要创建几层,每层叫什么,然后调用mkdirs方法方法,删除使用delete方法,放文件夹内存在内容时无法进行删除,文件夹套文件夹只会删除最里层的文件夹
3.创建文本等内容直接调用File有参构造方法,然后把要创建的文件当作形参直接传入,
4.创建时有两种路劲,绝对路径和相对路径,相对路劲在本文件夹下,绝对路劲值指具体路径
5.使用对象.createNewFile查看文件是否创建成功,
6.exists查看文件是否存在,getPath查看文件相对路径,getAbsouutrPath查看具体路径,length查看文件大小,getName查看文件名称,isFile查看是否为文件,isDirectory查看是否为一个文件夹,以上方法皆用File类创建的对象调用,具体代码如下:
import java.io.File;
import java.io.IOException;
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());
}
}
三.字节流
1.父类abstract InputStream
子类FileinputStream:基于字节的文件读取流
2.int read():每读取一个字节,返回值是读取内容的ascii码值
int read(byte[] datas):可以读取指定数组长度的内容,返回值是每次读取的长度,读取内容存放在数组中,可以使用String类构造方法封装为字符串new String(byte[] b , int , offset ,int ,length);
3.父类acstract OutputStream
子类:FileOutputStream:基于字节的文件写入流
4.void write():每次写入一个字节
void write(byte [] datas):写入一个byte数组,可以使用String类的getBytes()方法将字符串转换为byte数组
flush():内容刷新到文件中
close():关闭资源
字节读取流代码具体代码如下:
package com.qfedu.test2;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 字节读取流
* read() 每次读取一个字节
* read(byte[] datas) 读取一个byte数组 返回值是读取的长度
* 每次读取两个字节 可以读取中文 但是有可能会将中文拆分开 依然会产生乱码
* 解决方法:
* 1.我们可以定义一个长度较大的byte数组
* 2.可以使用字节读取流FileInputStream的一个方法 available()
* @author WHD
*
*/
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));
}
}
}
代码解释:
创建File对像,并调用有参构造,把要读取的文件作为形参,然后把file对象作为形参,传入FileInputStream的又参构造方法,然后用FileInputStream对象调用available方法,获取到文件中一共多少个字符,然后用数组接收,在定义一个参数使其初始值为-1,用while方法进行循环,其中用FileInputStream的对象.read数组遍历出每一个的ascii值,传入参数中,然后用System.out.println(new String(datas, 0, dataCount));进行输出。
字节写入流代码如下:
package com.qfedu.test3;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 字节写入流
* @author WHD
*
*/
public class TestFileOutPutStream2 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("c.txt", true);
String str = "学java 到千锋 郑州千锋找帅栋 23564545";
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();
}
}
}
}
}
代码解释:
先创建FileOutputStream类的有参构造方法,”c.txt“为将要写入的文本,若没有此文本将创建,tur代表继续插入,然后将插入的内容传给String修饰的对象,用String修饰的对象调用grtBytes()方法,将内容传到数组中,然后用FileOutputStream创建的对象调用write将数组内的内容写入文中中,用FileOutputStream修饰的方法调用flush方法,刷新,不然文件中不会显示插入的信息
四.读取流
1.父类abstract Reader
子类FileReader:基于字符的文件读取流
2.int read():每次读取一个字符
int read(char[] datas):每次读取char数组长度的内容,返回值是读取的长度,读取的内容存放在数组中,可以打印
3.子类:BufferedReader基于字符的文件读取缓冲流
在以上方法的基础上还有:readLine()方法,每次读取一行close()关闭资源
子类:InputStreamReader,可以指定编码格式的字符读取流
字符读取流代码如下:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
* 字符读取流 一次读取一个字符 也可以读取一个字符数组 char数组
* 字符是16位 unicode编码
* 字节 8位 byte ascii
* @author WHD
*
*/
public class TestFileReader2 {
public static void main(String[] args) {
FileReader fr = null;
try {
fr = new FileReader("c.txt");
char [] datas = new char[100];
int dataCount = -1;
while((dataCount = fr.read(datas)) != -1) {
System.out.println(dataCount);
System.out.println(datas);
System.out.println(new String(datas, 0, dataCount));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
代码解释:
首先创建FileReader类的有参构造对象,将要读取的文件当作形参传入,然后定义数组,定义形参,然后用FileReader类的有参构造对象调用read(datas)方法,括号中为字符串长度,表示最多可以读取这么长的字符串,将其每个字符都转为相应的ascii值然后进行输出System.out.println(new String(datas, 0, dataCount));输出语句中三个参数的意义为,可以读取的长度,从哪里开始读取,读取什么
带有缓冲流的具体代码:
package com.qfedu.test5;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* 带有缓冲流的字符读取流
* 可以读取一个字符 也可以一次读取一行
* readLine()
* @author WHD
*
*/
public class TestBufferedReader2 {
public static void main(String[] args) {
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader("c.txt");
br = new BufferedReader(fr);
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
// 关闭资源
if(br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
代码解释:
先定义FileReader和BufferedReader修饰的参数,并赋值为空,然后调用FileReader有参构造,将要读取的文件作为形参,BufferedReader有参构造FileReader对象为形参,任何定义参数line,用BufferedReader有参构造对象br调用readLinr()方法进行整行读取输出,并判断Line不能为空,否则结束循环,输出直接输出line即可
4.乱码出现的原因:
编码方式和解码方式不一致,编码方式有:
java文件编码
java文件编码
html文件编码
数据库编码
js文件编码
解决方式:
1.统一编码
2.可以将出现乱码的内容打散(iso-8859-1)按照我们自己的编码方式组合,常见的编码方式
GBK 国标扩展板 简体和繁体
GB2312 国标版本 只支持简体
ISO-8859-1 最原始的编码方式 通常用于解决乱码
UTF-8 unicode万国码 包含世界大多数国家的语言编码
ANSI 不具体指定某一种编码 因为在不同的操作系统上 表示对应的编码 比如 win10中文版 GBK
五.写入流
父类:abstract Writer
子类:FileWriter
write():每次写入一个字符
write(char [] datas):每次写入一个char数组
write(String str):每次写入一个字符串
子类:BufferedWriter
write():每次写入一个字符
write(char [] datas):每次写入一个char数组
newLine():换行
子类:OutputStreamWriter
write():每次写入一个字符
write(char [] datas):每次写入一个char数组
write(String str):每次写入一个字符串
字符写入流具体代码:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
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();
}
}
}
代码解释:
先定义FileOutputStream方法的有参构造对象,即将写入的文件作为行参,若没有文件创建一个,然后定义OutputStreamWriter类的有参构造对象,FileOutputStream定义的对象当作参数传入,用OutputStreamWriter定义的对象调用write()方法进行写入,并且需要调用flush()方法进行刷新,不然写入的数据不显示。
六.数据流
数据流属于字节流,用于读取二进制文件,比如图片,音频,视频等
DataInputStream:基于字节的二进制文件读取流
DataOutputStream:基于字节的二进制文件写入流
具体代码如下:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* DataInputStream 负责读取二进制文件
* DataOutputStream负责写入二进制文件
* @author WHD
*
*/
public class TestDataStream {
public static void main(String[] args) {
FileInputStream fis;
try {
FileOutputStream fos = new FileOutputStream("copyzs.jpg");
fis = new FileInputStream("C:\\Users\\WHD\\Desktop\\zs.jpg");
DataInputStream dis = new DataInputStream(fis);
DataOutputStream dos = new DataOutputStream(fos);
byte [] datas = new byte[fis.available()];
int dataCount = -1;
while((dataCount =dis.read(datas))!= -1) {
// System.out.println(dataCount);
// System.out.println(dataCount);
// dos.write(dataCount);
dos.write(datas);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
// 关闭资源
}
}
}
代码解释:
还是先定义FileInputStream修饰的有参构造对象,将我们将要读取的二进制文件的具体地址当作参数进行传入,然后用DataInputStream类创建有参构造方法,FileInputStream创建的对象作为行参传入,此方法读取的文件不可以直接输出,需要在进行写入,相当于复制,先定义FileOutputStream类的有参构造方法,将要被写入的二进制文件作为行参,若无本文件,自行创建,然后定义DataOutputStream 的有参构造方法,FileOutputStream类定义的对象当作形参进行传入,然后定义数组,数组长度有FileInputStream定义的对象调用fis.available()方法获取,读取文件的长度,当做数组长度,定义形参dataCount将dis.read(datas)遍历到的每一个信息进行对比,若不为-1继续遍历,然后用DataOutputStream定义的方法进行写入,写入为数组内的内容dos.write(datas);
七.对象流
对象流属于字节流,用于读取对象和写入对象
ObjectOutputStream-序列化:将对象以二进制的形式存储在文件中
ObejctInputStream-反序列化:将保存有对象的二进制文件读取出来转换为对象
序列化要求:被序列化的对象必须实现Serializable接口,此接口是空接口,相当于一个标识,实现此接口的类才可以序列化
具体代码实现:
package com.qfedu.test9;
import java.io.Serializable;
/**
* Serializable 空接口 相当于一个标识 标识实现此接口的类才能被序列化
* @author WHD
*
*/
public class Student implements Serializable{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
先定义一个学生类,要实现Serializable类,此类无实现方法,只作为一个标识,可以进行序列化
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* ObjectInputStream 对象读取流
* ObjectOutputStream 对象写入流
* 序列化:将对象写入到文件中
* 反序列化:将存有对象的文件读取出来生成对象
*
* @author WHD
*
*/
public class TestObjectStream {
public static void main(String[] args) {
FileOutputStream fos;
try {
fos = new FileOutputStream("stu.txt");
ObjectOutputStream 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);
FileInputStream fis = new FileInputStream("stu.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
// Student readStu1 = (Student) ois.readObject();
// Student readStu2 = (Student) ois.readObject();
// Student readStu3 = (Student) ois.readObject();
//
// System.out.println(readStu1);
// System.out.println(readStu2);
// System.out.println(readStu3);
while(fis.available() > 0) {
Student readStu1 = (Student) ois.readObject();
System.out.println(readStu1);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
代码解释:
先定义FileOutputStream修饰的有参构造方法将要进行写入的文本为形参,然后定义ObjectOutputStream类,将FileOutputStream定义的对象当作行参传入,然后用Student的有参构造方法定义学生信息,用ObjectOutputStream的对象调用writeObject方法进行信息的写入,然后定义FileInputStream 的有参构造,将要读取的文件作为形参,然后定义ObjectInputStream 的构造方法,将FileInputStream定义的对象当作行参传入,然后进行便利,用fis.available()获取长度,当其大于0继续遍历,ois.readObject()强转成学生类进行输出。