Java IO流(小结)
程序员文章站
2022-04-03 19:35:53
...
Java IO流
IO流
IO流概述
可以将这种数据传输的操作,看做一种数据的流动 ,按照流动的方向分为输入Input 和输出Output
Java中的IO操作主要指的是 java.io 包下的一些常用类的使用。通过这些常用类对数据进行读取(输入Input)和写出(输出Output)
IO流的分类
按照流的方向来分,可以分为:输入流和输出流
按照流动的数据类型来分,可以分为:字节流和字符流
字节流
- 输入流:InputStream (读取)
- 输出流:OutputStream (写入)
字符流
- 输入流:Reader (读取)
- 输出流:Writer (写入)
一切皆字节:
计算机中的任何数据(文本,图片,视频,音乐等等)都是以二进制的形式存储的。
在数据传输时也都是以二进制的形式存储的。
后续学习的任何流,在传输时底层都是二进制。
java.io.FileOutputStream
文件输出流是用于将数据写入File
或FileDescriptor
的输出流。
public static void main(String[] args) throws IOException {
/**
* 参数
* name - 与系统相关的文件名
* append - 如果是 true ,那么字节将被写入文件的末尾而不是开头(追加模式)
* 不写 则在流重新创建时会清除源文件内容并重新写入
*/
FileOutputStream fos = new FileOutputStream("c://a.txt",true);
// 方式一:写入ABCD
byte[] bytes1 = {65,66,67,68};
fos.write(bytes1);
// 方式二:getBytes()方法:将字符串 变成 字节数组
byte[] bytes2 = "ABCDE".getBytes();
fos.write(bytes2);
// 记得关闭流
fos.close();
System.out.println("已经写出");
}
java.io.FileInputStream
文件字节输入流,意思指对文件数据以字节的形式进行读取操作,如读取图片、视频等。
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("c://a.txt");
// 一次读取一个字节
while(true){
byte b = (byte) fis.read();
// -1即为流读取完毕
if(b == -1){
break;
}
System.out.println((char)b);
}
// 一次读取一组字节(可以以 1M(1024*1024 byte)为单位读取)
// 创建一个大小为10的数组,将读取到的内容放进数组里(每次读10个字节)
byte[] bytes = new byte[10];
int len = fis.read(bytes);
// 当我们不知道文件内容大小的情况下,用 len 表示每次读取的字节数
System.out.println(new String(bytes,0,len));
len = fis.read(bytes);
System.out.println(new String(bytes,0,len));
len = fis.read(bytes);
System.out.println(len);
fis.close();
}
文件加密和解密工具
public static void main(String[] args) throws Exception {
System.out.println("请输入文件存储的全路径:");
Scanner input = new Scanner(System.in);
String fileName = input.nextLine();
// 原文件: a.png
File oldFile = new File(fileName);
// 加密存储的新文件 a-encryption.png (encryption加密)
File newFile = new File(oldFile.getParentFile(), oldFile.getName() + "-encryption");
FileInputStream fis = new FileInputStream(oldFile);
FileOutputStream fos = new FileOutputStream(newFile);
while(true) {
int b = fis.read();
// 读取完毕,跳出循环
if(b == -1) {
break;
}
// 加密方式:任何数据^相同的数字 两次结果就是其本身
fos.write(b^10);
}
System.out.println("加密或解密完成");
}
字符输出流(FileWriter)
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("c://b.txt");
fw.append("锄禾日当午").append(",").append("汗滴禾下土");
// flush刷新管道,每次输出一段内容都要刷新一次
fw.flush();
// close在调用时,会刷新一次内容
fw.close();
}
字符输入流(FileReader)
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("b.txt");
char[] chars = new char[100];
int len = fr.read(chars);
String text = new String(chars,0,len);
System.out.println(text);
System.out.println(text.length());
fr.close();
}
字节流转换字符流
InputStreamReader
OutputStreanWriter
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("c://a. txt");
// 将字节输入流,转换为字符输入流
InputStreamReader isr = new InputStreamReader(fis, "gbk");
while(true){
int c = isr.read();
if(c == -1){
break;
}
System.out.println((char)c);
}
FileOutputStream fos = new FileOutputStream("c://a. txt");
// 将字节输出流,转换为字符输出流
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write("床前明月光");
osw.flush();
osw.close();
}
Print(打印流)与BufferedReader(缓存读取流)
public static void main(String[] args) throws IOException {
// PrintStream(打印流) — 自动刷新
PrintStream ps = new PrintStream("c://c.txt");
ps.println("锄禾日当午,汗滴禾下土1");
ps.println("锄禾日当午,汗滴禾下土2");
ps.println("锄禾日当午,汗滴禾下土3");
// PrintWriter(打印流) - 需要刷新管道 (更好用)
PrintWriter pw = new PrintWriter("c://c.txt");
pw.println("锄禾日当午,汗滴禾下土1");
pw.println("锄禾日当午,汗滴禾下土2");
pw.println("锄禾日当午,汗滴禾下土3");
pw.flush();
//缓存读取流,将字符输入流转换为带有缓存可以一次读取一行的缓存字符读取流
FileReader fr = new FileReader("c://c.txt");
BufferedReader br = new BufferedReader(fr);
String text = br.readLine();
System.out.println(text);
}
收集异常日志
public static void main(String[] args) throws FileNotFoundException {
try{
String s = null;
s.toString();
}catch(Exception e){
PrintWriter pw = new PrintWriter("c://bug.txt");
SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm");
pw.println(sdf.format(new Date()));
e.printStackTrace(pw);
// 关闭流
pw.close();
}
}
序列化与反序列化
实现序列化和反序列化时,类要实现 Serializable 标记接口(无抽象方法)
public class Demo3 {
/**
* 序列化和反序列化的定义
* Java序列化就是指把Java对象转换为字节序列的过程
* Java反序列化就是指把字节序列恢复为Java对象的过程
*
* 序列化的作用
* 在传递和保存对象时,保证对象的完整性和可传递性。对象转换为有序字节流,以便在网络上传输或者保存在本地文件中。
* 反序列化的作用
* 根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。
*
* 序列化优点:
* 1、将对象转为字节流存储到硬盘上,当下一次JVM启动,把序列化的对象,通过反序列化为原来的对象,并且序列化的二进制序列能够减少存储空间(永久性保存对象)。
* 2、序列化成字节流形式的对象可以进行网络传输(二进制形式),方便了网络传输。
* 3、通过序列化可以在进程间传递对象。
*/
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 序列化
Person p = new Person("张三",18);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"));
oos.writeObject(p);
oos.close();
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"));
Object o = ois.readObject();
System.out.println(o);
// 也可以类型强转
//Person o = (Person) ois.readObject();
//System.out.println(o.getName());
}
static class Person implements Serializable {
private String name;
private int age;
public Person() {}
public Person(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 "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';java
}
}
}
下一篇: IO流(自用小结笔记)