IO流
-
什么是io流
存储和读取数据的解决方案
I:input O:output
-
io流的作用
用于读写数据(本地文件,网络)
-
io流按照流向可以分类哪两种流
输出流:程序---->文件
输入流:文件---->程序
-
io流按照操作文件的类型可以分类哪两种流
字节流:可以操作所有类型的文件
字符流:只能操作纯文本文件
1.FileOutputStream流(本地字节输出流)
创建字节输出流对象:
- 参数是字符串表示的路径或者File对象都可以
- 如果文件不存在会创建一个新文件,但是要保证父级路径存在
- 如果文件已经存在,会清空文件
package com.zhang.ioStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo01 {
public static void main(String[] args) throws IOException {
//后面加上true会续写文件,不会清空文件。
FileOutputStream fods = new FileOutputStream("src\\com\\zhang\\ioStream\\a.txt");
byte[] bytes = {97,98,99,100,101};
//写出数组
fods.write(bytes);
//换行操作
String wap = "\r\n";
byte[] bytes1 = wap.getBytes();
fods.write(bytes1);
//写出单个字符
fods.write(34);
//数组,起始位置,写出长度
fods.write(bytes,1,2);
//写出任意字符串
String str = "dafffdsfaf";
byte[] bytes2 = str.getBytes();
fods.write(bytes2);
//释放资源
fods.close();
}
}
2.FileInputStream(字节输入流)
package com.zhang.ioStream;
import java.io.FileInputStream;
import java.io.IOException;
public class Demo02 {
public static void main(String[] args) throws IOException {
FileInputStream fie = new FileInputStream("src\\com\\zhang\\ioStream\\a.txt");
int b;
//不能把b删了,把(char)b换成(char)fie.read(),因为用一次会读取一个数据,移动一次指针,造成数据缺失
while((b=fie.read())!=-1){
System.out.println((char)b);
}
fie.close();
}
}
小文件拷贝
package com.zhang.ioStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo03 {
public static void main(String[] args) throws IOException {
FileInputStream fie = new FileInputStream("数据源");
FileOutputStream fos = new FileOutputStream("目的地");
//拷贝核心思想:边读边写
int b;
while((b = fie.read())!=-1){
fos.write(b);
}
//先开的最后关闭
fos.close();
fie.close();
}
}
大文件拷贝
package com.zhang.ioStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo03 {
public static void main(String[] args) throws IOException {
FileInputStream fie = new FileInputStream("文件所在路径");
FileOutputStream fos = new FileOutputStream("拷贝的路径");
//拷贝核心思想:边读边写
int len;
byte[] bytes = new byte[1024*1024*5];
while((len = fie.read())!=-1){
fos.write(bytes,0,len);
}
//先开的最后关闭
fos.close();
fie.close();
}
}
字符集详解(ASCII GBK)
- 计算机中最小的存储单元是一个字节
- ASCII字符集中,一个英文占一个字节
- 简体中文版Windows,默认使用GBK字符集
- GBK字符集完全兼容ASCII字符集:一个英文占一个字节,二进制第一位是0;一个中文占两个字节,二进制高位字节的第一位是1
Unicode字符集的UTF-8编码格式
一个英文占一个字节,二进制第一位是0,转成十进制是正数
一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数。
如何不产生乱码
- 不要用字节流读取文本文件
- 编码解码时使用同一个码表,同一个编码方式。
编码和解码代码的实现
package com.zhang.ioStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class Demo04 {
public static void main(String[] args) throws UnsupportedEncodingException {
//编码
String str = "ai你哈";
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));//[97, 105, -28, -67, -96, -27, -109, -120]
byte[] bytes1 = str.getBytes("GBK");
System.out.println(Arrays.toString(bytes1));//[97, 105, -60, -29, -71, -2]
//解码
String str2 = new String(bytes,"GBK");
System.out.println(str2); //ai浣犲搱
String str3 = new String(bytes1,"UTF-8"); //因为是GBK类型的,解码成UTF-8会出现乱码
System.out.println(str3); //ai���
}
}
3.FileReader
package com.zhang.ioStream;
import java.io.FileReader;
import java.io.FilterReader;
import java.io.IOException;
public class Demo05 {
public static void main(String[] args) throws IOException {
FileReader fre = new FileReader("a.txt");
char[] chars = new char[2];
int len;
while((len = fre.read(chars))!= -1){
System.out.print(new String(chars,0,len));
}
fre.close();
}
}
空参的read();默认是一个字节一个字节读取,遇到中文会一次读取多个。在读取之后,方法的底层会进行解码转成十进制作为返回值,这个数据表示在字符集上的数字,要想看到中文,进行强制转换就可以了(char)..
有参read():读取数据,解码,强转三步合并,把强转的字符放到数组当中。
4.FileWriter
package com.zhang.ioStream;
import java.io.FileWriter;
import java.io.IOException;
public class Demo06 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("a.txt");
fw.write("真的很好呀");
fw.close();
}
}
拷贝文件夹
package com.zhang.ioStream;
import java.io.*;
public class Demo06 {
public static void main(String[] args) throws IOException {
File src = new File("E:\\项目练习plus\\src");//数据源
File dest = new File("E:\\项目练习plus\\dest");//目的地
copdir(src,dest);
}
private static void copdir(File src, File dest) throws IOException {
//dest不存在,创建文件夹dest
dest.mkdir();
//进入数据源
File[] files = src.listFiles();
//遍历数组
for (File file : files) {
//判断文件 拷贝
if (file.isFile()){
FileInputStream fie = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(new File(dest,file.getName()));
byte[] bytes = new byte[1024];
int len;
while ((len=fie.read(bytes))!=-1){
fos.write(bytes,0,len);
}
fos.close();
fie.close();
}else{
//判断文件夹 递归
copdir(file,new File(dest,file.getName()));
}
}
}
}
加密解密文件
package com.zhang.ioStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo07 { //解密的话把文件路径换下
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("源文件路径");
FileOutputStream fos = new FileOutputStream("加密之后路径");
//加密处理
int len;
while ((len = fis.read())!=-1){
//异或运算,异或相同的数两次还是本身
fos.write(len^2);
}
fos.close();
fis.close();
}
}
文件中由以下数据:2-1-9-4-7-8 将文件中的数据进行排序,变成以下数据:1-2-4-7-8-9
package com.zhang.ioStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
public class Demo08 {
public static void main(String[] args) throws IOException {
FileReader fis = new FileReader("a.txt");
StringBuilder sb = new StringBuilder();
int ch;
while((ch=fis.read())!=-1){
sb.append((char)ch);
}
fis.close();
System.out.println(sb);
//排序
Integer[] arr = Arrays.stream(sb.toString()
.split("-"))
.map(Integer::parseInt)
.sorted()
.toArray(Integer[]::new);
System.out.println(Arrays.toString(arr));
//写出
FileWriter fw = new FileWriter("a.txt");
String s = Arrays.toString(arr).replace(",","-");
String result = s.substring(1,s.length()-1);
fw.write(result);
fw.close();
}
}
5.BufferedInputStream和BufferedOutputStream(字节缓冲流)**
package com.zhang.ioStream;
import java.io.*;
public class Demo09 {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.txt"));
int b;
while((b=bis.read())!=-1){
bos.write(b);
}
bos.close();
bis.close();
}
}
一次读写一个字符数组
package com.zhang.ioStream;
import java.io.*;
public class Demo10 {
public static void main(String[] args) throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy1.txt"));
byte[] bytes = new byte[1024];
int len;
while ((len = bis.read(bytes))!=-1){
bos.write(bytes,0,len);
}
bos.close();
bis.close();
}
}
6.BufferedReader和BufferedWriter(字符缓冲输入流和字符缓冲输出流)
package com.zhang.ioStream;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Demo11 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String line;
while ((line = br.readLine())!=null){
System.out.println(line);
}
br.close();
}
}
package com.zhang.ioStream;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Demo12 {
public static void main(String[] args) throws IOException {
BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt",true));
bw.write("爱你过绝望");
//换行
bw.newLine();
bw.write("库一样");
bw.newLine();
bw.close();
}
}
缓冲流为什么能提高性能
- 缓冲流自带长度为8192的缓冲区
- 可以显著提高字节流的读写性能
- 对于字符流提升不明显,对于字符缓冲流而言关键有两个特有的方法
- BufferedReader:readLine();一次读一行数据
- BufferedWriter:newLine();换行
恢复文本中的顺序
package com.zhang.ioStream;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Demo13 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String line;
ArrayList<String> arr = new ArrayList();
while ((line = br.readLine())!=null){
arr.add(line);
}
//排序
Collections.sort(arr, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
int i1 = Integer.parseInt(o1.split("\\.")[0]);
int i2 = Integer.parseInt(o2.split("\\.")[0]);
return i1-i2;
}
});
//写出
BufferedWriter bw = new BufferedWriter(new FileWriter("result.txt"));
for (String str : arr) {
bw.write(str);
bw.newLine();
}
bw.close();
}
}
第二种方法
package com.zhang.ioStream;
import java.io.*;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Demo14 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
String line;
TreeMap<Integer,String> tm = new TreeMap<>();
while ((line = br.readLine())!=null){
String[] arr = line.split("\\.");
tm.put(Integer.parseInt(arr[0]),line);
}
br.close();
//写出数据
BufferedWriter bw = new BufferedWriter(new FileWriter("result1.txt"));
Set<Map.Entry<Integer,String>> entries = tm.entrySet();
for (Map.Entry<Integer, String> entry : entries) {
String value = entry.getValue();
bw.write(value);
bw.newLine();
}
bw.close();
}
}
7.InputStreamReader,OutputStreamWriter(字符转换输入流和字符转换输出流)
package com.zhang.ioStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
//利用字节流读取文件中的数据,每次读一整行,而且不能有乱码
public class Demo16 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("");//文件是UTF-8形式的,用字符流读取
InputStreamReader isr = new InputStreamReader(fis);//把字符流转换成字节流
BufferedReader br = new BufferedReader(isr);//缓冲流里面有读一整行的方法
String str = br.readLine();//读一整行
System.out.println(str);
br.close();
//第二种方法
BufferedReader br1 = new BufferedReader(new InputStreamReader(new FileInputStream("")));
String line;
while((line = br1.readLine())!=null){
System.out.println(line);
}
br1.close();
}
}
转换流作用:字节流想要使用字符流中的方法
8.ObjectOutputStream (序列化流)
public class Student implements Serializable{}
//Serializable接口里面没有抽象方法,标记接口。一旦实现这个接口,表示当前的Student类可以被序列化
package com.zhang.ioStream;
import com.zhang.oop.Obct.Student;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Demo17 {
public static void main(String[] args) throws IOException {
Student stu = new Student("张三",23);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("copy.txt"));
oos.writeObject(stu);
oos.close();
}
}
9.ObjeInputStream(反序列化流)
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("copy.txt"));
Object o = ois.readObject();
System.out.println(o);
ois.close();
-
使用序列化流将对象写到文件时,需要让Javabean类实现Serializable接口。否则,会出现NotSerializableException异常
-
序列化流写到文件中的数据是不能修改的,一旦修改无法再次读回来。
-
序列化对象后,修改了Javabean类,再次反序列化,会抛出InvalidClassException异常
解决方案:给Javabean类添加serialVersionUID(序列号,版本号)
-
一个对象中的某个成员变量的值不想被序列化
解决方案:给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程。
读写多个对象
package com.zhang.ioStream;
import com.zhang.oop.Obct.Student;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class Demo18 {
public static void main(String[] args) throws IOException {
Student s1 = new Student("张三",12);
Student s2 = new Student("李四",22);
Student s3 = new Student("王五",33);
ArrayList<Student> list = new ArrayList<>();
list.add(s1);
list.add(s2);
list.add(s3);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("copy.txt"));
oos.writeObject(list);
oos.close();
}
}
package com.zhang.ioStream;
import com.zhang.oop.Obct.Student;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
public class Demo19 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("copy.txt"));
ArrayList<Student> list = (ArrayList<Student>) ois.readObject();
for (Student student : list) {
System.out.println(student);
}
}
}
10.PrintStream字节打印流
package com.zhang.ioStream;
import java.io.FileNotFoundException;
import java.io.PrintStream;
public class Demo20 {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = new PrintStream("copy1.txt");
ps.println(97);//写出+自动刷新+自动换行
ps.print(true);
ps.printf("%s爱上了%s","阿珍","阿强");
ps.close();
}
}
11.PrintWriter字符打印流
package com.zhang.ioStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class Demo21 {
public static void main(String[] args) throws IOException {
PrintWriter pw = new PrintWriter(new FileWriter("copy1.txt"));
pw.println("谢谢你,张三");
pw.print("你好你好");
pw.printf("%s爱你%s","zhang","san");
pw.close();
}
}