什么是IO流?
-
-
O: Output
-
通过IO流可以完成硬盘的读写操作
IO流的分类
-
按照流的方向进行分类
-
按读取方式进行分类
-
字节流: 按字节方式,一次读取1个字节(8个二进制位),这种流是万能的,能读文本,视频,音乐等
-
字符流: 按照字符方式读取数据,一次读取1个字符,这种流只能读取文本文件
综上所述,流分为:
Java的四大流
-
-
OutputStream 字节输出流
-
FileReader 字符输入流
-
FileWriter 字符输出流
-
所有的流都是可关闭的,都实现了Closeable接口,都有close()方法
-
所有的输出流都是刷新的,都实现了Flushable接口,都有flush()方法
package Demo1;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Test02 {
public static void main(String[] args) {
FileInputStream fis = null;
StringBuffer sb = new StringBuffer(16);
try {
//一次读取4个字节
byte[] bytes = new byte[5];
//创建输入字节流
fis = new FileInputStream("name");
//获取未读取的字节数量
System.out.println("未读取的字节数: " + fis.available());
//可以这样读取,不适合大数据量
/*
* byte[] readAll = new byte[fis.available()]; fis.read(readAll);
* System.out.println("一次性读取: " + new String(readAll));
*/
//返回的是读入的字节个数,如果没有读到返回-1
int i = 0;
while((i = fis.read(bytes)) != -1) {
//将有效部分转换为string
sb.append(new String(bytes,0,i));
}
System.out.println(sb);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
FileOutputStream
package Demo1;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileoutputStreamTest {
public static void main(String[] args) {
FileOutputStream fos = null;
FileOutputStream fos1 = null;
try {
//以覆盖的方式将byte数组写入
fos = new FileOutputStream("name");
//byte数组
byte[] file = {97,98,99,100,101};
//将byte数组写入
fos.write(file);
//刷新
fos.flush();
//以追加的方式写入
fos1 = new FileOutputStream("name1",true);
//String
String country = "我是一个中国人,我骄傲 !";
//将String转换为byte数组
byte[] stringvalue = country.getBytes();
//将byte数组写入
fos1.write(stringvalue);
//刷新
fos1.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
字节流copy文件
package Demo1;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopy {
public static void main(String[] args) {
copy();
}
public static void copy() {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//创建字节输入流
fis = new FileInputStream("C:\\Users\\28229\\Pictures\\ip.JPG");
fos = new FileOutputStream("C:\\Users\\28229\\Desktop\\a.jpg",true);
//读入字节输入流
int count = 0;
//byte数组
byte[] bytes = new byte[10];
//读取
while((count = fis.read(bytes)) != -1) {
//写入
fos.write(bytes, 0, count);
fos.flush();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
字符流copy文件
package DemoFileRW;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyRW {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
//创建字符输入流
fr = new FileReader("b.txt");
fw = new FileWriter("C:\\Users\\28229\\Desktop\\file.txt");
//读入文件
char[] chars = new char[10];
int count = 0;
while((count = fr.read(chars)) != -1) {
//写
fw.write(chars,0,count);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
字符缓冲流
package Buffer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderTest {
public static void main(String[] args) throws IOException {
//创建字符缓冲流
BufferedReader br = new BufferedReader(new FileReader("01.java"));
//读取一行
String line = null;
while((line = br.readLine()) != null) {
//读取的数据是不带换行符的
System.out.println(line);
}
if (br != null) {
br.close();
}
}
}
转换流
package Buffer;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class Convert {
public static void main(String[] args) throws IOException {
/*
* //字节输入流 FileInputStream fis = new FileInputStream("01.java");
*
* //将字节输入流转换为字符输入流 InputStreamReader isr = new InputStreamReader(fis);
*
* //字符缓冲流 BufferedReader br = new BufferedReader(isr);
*/
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("01.java")));
String line = null;
while((line = br.readLine()) != null) {
System.out.println(line);
}
//关闭最外层
br.close();
}
}
标准输出流
package PrintStreamDemo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Logger {
public static void log(String message) {
try {
//创建标准输出流,指向log.txt
PrintStream ps = new PrintStream(new FileOutputStream("log.txt",true));
//改变输出方向
System.setOut(ps);
//输出
ps.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()) + message);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package PrintStreamDemo;
public class PrintStreamTest {
public static void main(String[] args) {
Logger.log("登录失败!");
Logger.log("调用xxx方法");
}
}
序列化与反序列化
-
当一个类去实现Serializable接口,jvm会自动生成一个序列号,序列号是用来区分类的
-
Java是如何区分类的?
-
自动生成的序列号有什么缺点?
-
后续无法更改代码,因为重新编译会生成新的序列号,此时jvm会认为这是新的一个类
-
所以建议实现Serializable接口的类,手动初始化序列号
-
如果之前序列化了一个类,没有手动初始化序列号,那麽后续改代码后会生成新的序列号,导致无法重写反序列化
package Serialize;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class Test {
/*
* 参与序列化的类,必须实现Serializable标识接口
*/
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
//创建student对象
Student s = new Student("张三",18);
Student s1 = new Student("lisi",20);
List<Student> students = new ArrayList<>();
students.add(s);
students.add(s1);
//序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students"));
//序列化
oos.writeObject(students);
oos.flush();
oos.close();
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("students"));
Object objs = ois.readObject();
if (objs instanceof List) {
objs = (List<Student>)objs;
/*
* Student [name=张三, age=18]
Student [name=lisi, age=20]
*/
for (Student student : students) {
System.out.println(student);
}
}
ois.close();
}
}
package Serialize;
import java.io.Serializable;
public class Student implements Serializable{
//手动初始化序列号
private static final long serialVersionUID = -546546465465465465L;
//transient: 标识修饰的属性不参与序列化操作
private transient String name;
private int age;
public Student() {}
public Student(String name, int age) {
super();
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 + "]";
}
}