1.IO流
1.1IO流概念及其分类
1.1.1IO流概念
IO流用于处理设备之间的数据传输。
JAVA对数据的操作是通过流的方式。
JAVA用于操作流的对象都在IO包中。
1.1.2IO流分类
a.按照数据流向
输入流 读入数据
输出流 读出数据
b.按照数据类型
字节流 可以读写任何类型的文件
字符流 只能读写文本文件
不清楚该用什么,就用字节流。
1.2IO流基本类和FileOutoutStream
1.2.1IO流基本类概念
a.字节流的抽象类
InputStream ,OutputStream。
b.字符流的抽象基类
Reader , Writer。
注意:
由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
案例:
往一个文本文件中写一串数据 Hello,IO
因为我们要写数据,所以我们应该使用字节流中输出流 OutputStream
package westos;
import java.io.*;
public class MyTest1 {
//往一个文本文件中写一串数据 Hello,IO
public static void main(String[] args) throws IOException{
FileOutputStream out = new FileOutputStream("a.txt");
out.write("HELLO IO".getBytes());
out.close();
}
}
结果:
1.2.2FileOutputStream的三个write()方法以及换行和追加写入
package westos;
import java.io.*;
public class MyTest1 {
public static void main(String[] args) throws IOException{
FileOutputStream out = new FileOutputStream("a.txt",true);\\true的作用是实现数据的追加写入
out.write("\r\n".getBytes());\\windows下的换行符是 \r\n( Linux下的换行符是\n,Mac下的换行符是\r)
out.write(97);//写一个字节 超过一个字节 砍掉前面的字节
out.write(98);
out.write(99);
/*......................................*/
out.write("\r\n".getBytes());
out.write(new byte[]{65,66,67});//写一个字节数组
/*......................................*/
out.write("\r\n如果没有见过光明,我本可以忍受黑暗".getBytes(),0,26);//写一个字节数组的一部分
out.write("\r\n如果没有见过光明,我本可以忍受黑暗".getBytes(),0,53);
out.close();
}
}
结果:
1.2.3写出数据加入异常处理
package westos;
import java.io.*;
public class MyTest1 {
public static void main(String[] args) {
FileOutputStream out = null;
try {
out = new FileOutputStream("a.txt",true);
out.write(97);
out.write(98);
out.write(99);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
1.3FileInputStream
1.3.1读取数据一次一个字节和读取数据一次一个字节数组
package westos;
import java.io.*;
public class MyTest1 {
public static void main(String[] args) throws IOException{
FileOutputStream out = new FileOutputStream("a.txt");
out.write("a如果没有见过光明,我本可以忍受黑暗".getBytes());
out.close();
FileInputStream in = new FileInputStream(new File("a.txt"));;
int a = in.read();//一次读取一个字节
System.out.println(a);//如果没有数据返回的就是-1
byte[] b = new byte[1024];//把文件中的数据,读取到容器中,返回值是,读取到的有效字节个数
int c = in.read(b);
System.out.println(c);
String s = new String(b, 0, c);
System.out.println(s);
in.close();
}
}
结果:
97 51 如果没有见过光明,我本可以忍受黑暗
1.4字节流复制
1.4.1复制文件
package westos;
import java.io.*;
public class MyTest1 {
public static void main(String[] args) throws IOException{
FileInputStream in = new FileInputStream("a.txt");
//关联目标文件
FileOutputStream out = new FileOutputStream("F:\\Test 3\\a2.txt");
//循环的读写
int len=0;
while ((len=in.read())!=-1){
out.write(len);
out.flush();//刷新
}
//释放资源
in.close();
out.close();
}
}
1.4.2复制MP3
package westos;
import java.io.*;
public class MyTest1 {
public static void main(String[] args) throws IOException{
//我们读取一个字节,写入一个字节,来复制音频文件
FileInputStream in = new FileInputStream("F:\\Test1\\城府.mp3");
FileOutputStream out = new FileOutputStream("F:\\Test 3\\城府1.mp3");
int len=0;//定义一个变量,记录读取到的字节
//循环读写
while ((len=in.read())!=-1){
out.write(len);
out.flush();
}
//释放资源
in.close();
out.close();
}
}
1.4.3结果
1.5BufferedInputStream读取数据
package westos;
import java.io.*;
public class MyTest1 {
public static void main(String[] args) throws IOException{
BufferedInputStream b = new BufferedInputStream(new FileInputStream("a.txt"));
byte[] bytes = new byte[52];
int q=0;
while ((q=b.read(bytes))!=-1){
b.read(bytes,0,q);\\
高效的字符输入流
//高效的字符输出流: BufferedWriter }
System.out.println(new String(bytes));
}
}
结果:
a如果没有见过光明,我本可以忍受黑暗
1.6练习
1.6.1把集合中的数据存储到文本文件
package westos;
import java.io.*;
import java.util.ArrayList;
public class MyTest1 {
public static void main(String[] args) throws IOException{
ArrayList<String> list = new ArrayList<>();
list.add("李一 ");
list.add("张三");
list.add("宁一");
list.add("徐四");
list.add("刘五");
list.add("李二 ");
list.add("张四");
list.add("宁二");
list.add("徐五");
list.add("刘六");
//遍历集合,取出数据写入文本文件
BufferedWriter writer = new BufferedWriter(new FileWriter("a.txt"));
for (String s : list) {
writer.write(s);
writer.newLine();
writer.flush();
}
writer.close();
}
}
结果:
1.6.2随机获取文本文件中的姓名
package westos;
import java.io.*;
import java.util.ArrayList;
import java.util.Random;
public class MyTest1 {
public static void main(String[] args) throws IOException{
BufferedReader bfr = new BufferedReader(new FileReader("a.txt"));
ArrayList<String> list = new ArrayList<>();
while (true) {
String s = bfr.readLine();
if (s != null) {
list.add(s);
} else {
break;
}
}
// System.out.println(list);\\输出[李一 , 张三, 宁一, 徐四, 刘五, 李二 , 张四, 宁二, 徐五, 刘六]
Random random = new Random();
//生成一个随机索引
int index = random.nextInt(list.size());
String s = list.get(index);
System.out.println(s);//随机输出
}
}
结果:
在“a.txt”中随机输出一个名字
1.6.3复制指定目录下指定后缀名的文件并修改名称
package westos;
import java.io.*;
public class MyTest1 {
public static void main(String[] args) throws IOException {
File f1 = new File("F:\\Test 2\\fff");
File[] f2 = f1.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
//System.out.println(pathname);
if (pathname.isFile() && pathname.getName().endsWith(".png")) {
return true;
} else {
return false;
}//筛选出后缀为".png"的文件
}
});
FileInputStream in = null;
FileOutputStream out= null;
for (File j : f2) {
String str1 = j.getName();
String str2 = j.getName().replace(".png", ".jpg");
//File f3 = new File("F:\\Test 2\\fff\\" + str2);
in = new FileInputStream("F:\\Test 2\\fff\\" + str1);
out = new FileOutputStream("F:\\Test 3\\"+ str2);
int len = 0;//定义一个变量,记录读取到的字节
//循环读写
while ((len = in.read()) != -1) {
out.write(len);
out.flush();
}
}
//释放资源
in.close();
out.close();
}
}
要复制照片:
复制完成:
1.6.4键盘录入学生信息按照总分排序并写入文本文件
package Asd;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.Scanner;
import java.util.TreeSet;
public class MyTest {
public static void main(String[] args) throws IOException {
TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//按照总分来排序
int num = s1.getTotalScore() - s2.getTotalScore();
int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
return -num2;
}
});
for (int i = 1; i <= 3; i++) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第" + i + "个学生的姓名");
String name = sc.nextLine();
Student student = new Student();
student.setName(name);
System.out.println("请输入第" + i + "个学生的语文成绩");
int yw = sc.nextInt();
student.setChineseScore(yw);
System.out.println("请输入第" + i + "个学生的数学成绩");
int sx = sc.nextInt();
student.setMathScore(sx);
System.out.println("请输入第" + i + "个学生的英语成绩");
int yy = sc.nextInt();
student.setEnglishScore(yy);
//把学生添加到集合里面
treeSet.add(student);
}
//把集合中的数据存到文本文件中存起来
long time = System.currentTimeMillis();
Date date = new Date(time);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");//获取现在的时间
String s = simpleDateFormat.format(date);
BufferedWriter bfw = new BufferedWriter(new FileWriter(s+".txt",true));
bfw.write("序号 姓名 语文成绩 数学成绩 英语成绩 总分");
bfw.newLine();
bfw.flush();
//遍历
int index = 1;
for (Student student : treeSet) {
bfw.write(index + " " + student.getName() + " " + student.getChineseScore() + " " + student.getMathScore() + " " + student.getEnglishScore() + " " + student.getTotalScore());
bfw.newLine();
bfw.flush();
index++;
}
bfw.close();
System.out.println("学生成绩录入完成");
}
}
package Asd;
public class Student {
private String name;
private int chineseScore;
private int mathScore;
private int englishScore;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChineseScore() {
return chineseScore;
}
public void setChineseScore(int chineseScore) {
this.chineseScore = chineseScore;
}
public int getMathScore() {
return mathScore;
}
public void setMathScore(int mathScore) {
this.mathScore = mathScore;
}
public int getEnglishScore() {
return englishScore;
}
public void setEnglishScore(int englishScore) {
this.englishScore = englishScore;
}
//获取总分的方法
public int getTotalScore() {
return chineseScore + mathScore + englishScore;
}
}
键盘录入:
请输入第1个学生的姓名 qaz 请输入第1个学生的语文成绩 34 请输入第1个学生的数学成绩 45 请输入第1个学生的英语成绩 56 请输入第2个学生的姓名 wsx 请输入第2个学生的语文成绩 67 请输入第2个学生的数学成绩 78 请输入第2个学生的英语成绩 89 请输入第3个学生的姓名 edc 请输入第3个学生的语文成绩 12 请输入第3个学生的数学成绩 34 请输入第3个学生的英语成绩 56 学生成绩录入完成
存入文本:
1.7序列化流和反序列化流的概述和问题
1.7.1序列化流和反序列化流的概述
所谓的序列化:就是把对象通过流的方式存储到文件中。
注意:此对象 要重写Serializable 接口才能被序列化。
反序列化:就是把文件中存储的对象以流的方式还原成对象
序列化流: ObjectOutputStream
反序列化流: ObjectInputStream
一个对象可以被序列化的前提是这个对象对应的类必须实现Serializable接口
1.7.2序列化流时的黄色警告线问题
我们的一个类可以被序列化的前提是需要这个类实现Serializable接口,就需要给这个类添加一个标记.
在完成序列化以后,序列化文件中还存在一个标记,然后在进行反序列化的时候, 会验证这个标记和序列化前的标记是否一致,如果一致就正常进行反序列化,如果 不一致就报错了. 而现在我们把这个类做了修改,将相当于更改了标记,而导致这两个标记不一致,就报错了.
解决问题: 只要让这个两个标记一致,就不会报错了