JavaSE(九)I/O流
I/O流
提示:以下是本篇文章正文内容,下面案例可供参考
一、I/O
I/O理解
所有流都实现了Closeable接口,都是可关闭的,都有close()方法
所有输出流都实现来Flushable接口,都是可刷新的,都有flush()方法,清空管道(管道数据强行写入)
图示:
常用流
//文件专属
java.io.FileInputStream
java.io.FileOutputStream
java.io.FileReader
java.io.FileWriter
//转换流(字节流转换成字符流)
java.io.InputStreamReader
java.io.OutputStreamWriter
//缓冲流
java.io.BufferedReader
java.io..BufferedWriter
java.io.BufferedOutputStream
java.io.BufferedInputStream
//数据流专属
java.io.DataInputStream
java.io.DataOutputStream
//标准输出打印流
java.io.PrintWriter
java.io.PrintStream
//对象专属流
java.io.ObjectInputStream
java.io.ObjectOutputStream
1.字符流
(1)FileReader
使用:
reader = new FileReader("./JavaSE/src/jjwb.txt");
// int data = reader.read();//20013 中
char[] chars = new char[4];
int readCount = 0;
while((readCount = reader.read(chars)) != -1){
System.out.println(new String(chars,0,readCount));
}
(2)FileWriter
使用:
writer = new FileWriter("./JavaSE/src/jjwb.txt",true);
char[] chars = {'\t','我','是','中','国','人'};
writer.write(chars);
writer.write(chars,3,3);
writer.write("小江江");
writer.flush();
(3)字符流文件复制
使用:
reader = new FileReader("./JavaSE/src/jjwb.txt");
writer = new FileWriter("./JavaSE/src/newjjwb.txt",true);
char[] chars = new char[1024 * 512];
int readCount = 0;
while((readCount = reader.read(chars)) != -1){
writer.write(chars,0,readCount);
}
writer.flush(); //刷新管道
2.字节流
(1)FileInputStream
常用方法:
1.read()每次读取一个字节,放回读取到的字节的码,读到文件末尾时返回-1
2.read(byte[])每次读入到byte数组里,返回读取到的字节数量,一个都没读到时返回-1
3.available()返回流中剩下还未读取的字节数量。new byte[fis.available()],适用于x小文件
4.skip()跳过几个字节不读
IDEA中当前路径是工程的根
使用基本架构:
public class Test{
public static void main(String[] args){
FileInputStream fis = null;
try {
fis = new FileInputStream("./JavaSE/src/jjwb.txt");
byte[] bytes = new byte[4];
int readCount = 0;
while((readCount = fis.read(bytes)) != -1){
System.out.print(new String(bytes,0,readCount));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if (fis != null) {
try {
fis.close(); //关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
(2)FileOutputStream
基本代码:
FileOutputStream fos = null;
try { //true 追加写入
fos = new FileOutputStream("./JavaSE/src/jjwb.txt",true); // 文件不存时会自动创建
byte[] data = {97,98,99,100,101};
fos.write(data);
fos.flush(); //刷新
}
(3)字节流文件复制
public class Test{
public static void main(String[] args){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("./JavaSE/src/jjwb.txt"); //true 追加写入
fos = new FileOutputStream("./JavaSE/src/newjjwb.txt",true); // 文件不存时会自动创建
byte[] bytes = new byte[1024 * 1024];
int readCount = 0;
while((readCount = fis.read(bytes)) != -1){
fos.write(bytes,0,readCount);
}
fos.flush(); //刷新
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
//分开try 否则其中一个出现异常会影响另一个流的关闭
if (fis != null) {
try {
fis.close(); //关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close(); //关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3.缓冲流与转换流
自带缓冲区,传入的流叫做节点流,外部的流叫做包装流,关闭时只需要关闭包装流(节点流也在源码中关闭了):
方法:
1.readLIne() 不带最后的换行符,到达文件末尾时,返回null
使用:
public class Test{
public static void main(String[] args){
BufferedReader br= null;
try {
br = new BufferedReader(new InputStreamReader(new FileInputStream("./JavaSE/src/jjwb.txt")));
String str;
while ((str = br.readLine()) != null){
System.out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
4.数据流
可以将数据连同数据类型写入文件,所以这个文件不是普通文本,读写顺序要相同才能读
try {
dos = new DataOutputStream(new FileOutputStream("./JavaSE/src/data"));
dis = new DataInputStream(new FileInputStream("./JavaSE/src/data"));
byte b = 100;
boolean sex = false;
char c = 'a';
dos.writeByte(b);
dos.writeBoolean(sex);
dos.writeChar(c);
dos.flush();
byte nb = dis.readByte();
boolean nsex = dis.readBoolean();
char nc = dis.readChar();
System.out.println(nb);
System.out.println(nsex);
System.out.println(c);
}
5.标准输出流
使用:
public static void main(String[] args){
System.out.println("hello world");
PrintStream ps = System.out; // 返回PrintStream //标准的字节输出流,默认输出到控制台
ps.println("hello "); // 标准输出流不需要手动关闭
PrintStream printStream = null;
try{
printStream= new PrintStream(new FileOutputStream("./JavaSE/src/log",true));
System.setOut(printStream); //修改输出方向
System.out.println("今天又胖了");
System.out.println("西瓜味的胖子");
System.out.println("逗逼金鱼");
}catch (IOException e){
e.printStackTrace();
}
}
6.System类
常用方法:
1.System.gc()
2.System.currentTimeMillis()
3.PrintStream ps = System.out
4.System.exit(0)
5.System.arrayCopy()
7.File类
文件和目录路径名的抽象表示形式
常用方法:
1.exists() 判断文件是否存在
2.f.createNewFile(); 以文件的方式创建
3.mkdir() mkdirs() 以目录[多重目录] 的方式创建
4.getParent() getParentFile() 获取父路径[父文件对象]
5.getAbsolutePath() 获取绝对路径
6.getName()
7.isDirectory() isFile()
8.lastModified() 返回最后一次文件修改时间(时间戳)
9.length() 获取文件大小
10.listFiles() 获取当目录下的所有子文件对象(数组)
使用:
File f = new File("D:\\IE down\\newfile");
PrintStream ps = new PrintStream(new FileOutputStream("./JavaSE/src/consoleLog"));
System.setOut(ps);
System.out.println(f.exists());
System.out.println(f.getName());
System.out.println(f.getParent());
System.out.println(f.getParentFile().getAbsolutePath());
8.序列化与反序列化
参与序列化的对象必须实现Serializable(标志接口)接口,被transient(游离的)关键字修饰的属性不参与序列化,JVM会默认提供序列化版本号
建议给手动写固定不变的序列化版本号
理解图:
序列化:
Student s = new Student(111,"xiaojiang");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./JavaSE/src/students"));
oos.writeObject(s);
oos.flush();
oos.close();
反序列化:
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./JavaSE/src/students"));
Object obj = ois.readObject();
System.setOut(new PrintStream(new FileOutputStream("./JavaSE/src/consoleLog")));
System.out.println(obj.toString());
序列化多个对象:
将多个对象放入集合中,参与序列化的集合与集合中的元素都需要实现Serializable接口
List<Student> studentList = new ArrayList<>();
studentList.add(new Student(101,"xiaojiang"));
studentList.add(new Student(102,"xiaoliu"));
studentList.add(new Student(103,"xiaohua"));
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./JavaSE/src/students"));
oos.writeObject(studentList);
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./JavaSE/src/students"));
for(Student s : (List<Student>)ois.readObject()){
System.out.println(s.toString());
}
// System.out.println(obj instanceof List); //true
ois.close();
类区分:
类名,序列化版本号
将该类序列化后,修改了源代码,如果由JVM虚拟机默认生成序列化版本号,将认为这是两个不同的类,不能再反序列化,所以凡是实现了Serializable接口的类,建议给手动写固定不变的序列化版本号;jvm虚拟机才认为时同一个类
private static final long serialVersionUID = 8678952581122892189L;
//Exception in thread "main" java.io.
// InvalidClassException: Student;
// local class incompatible: stream classdesc serialVersionUID = 8678952581122892189,
// local class serialVersionUID = -4554816821284592035
private int no;
private String name;
private int age; //<-----修改处
9.I/O与Properties联合使用
属性配置文件建议以.properties后缀结尾
userinfo文件:
实现:
FileReader reader = new FileReader("./JavaSE/src/userinfo");
Properties pro = new Properties();
//调用Properties对象的load()方法,将文件中的数据加载到Map集合中
pro.load(reader);
for(Map.Entry node: pro.entrySet()){
System.out.println(node.getKey() + " ==> " + node.getValue());
}
结果: