为什么称为流?所有数据对于计算机来说都是以细化的小单位存储的,所以让他们一起输入输出就像流水一样,一股数据才是一个整体,比如对于字节流,GKB编码情况下,一个汉字就是两个字节,那么这两个字节就是一个流。
IO流分类:
- 字节流:字节输入流和字节输出流
- 字符流:字符的输入和输出流
- 缓冲流:4字节的输入缓冲流
- 对象流
- ……
首先接触下文件的基础操作:
File f = new File("d:/files/b.txt");
//创建文件,按照上述路径
f.createNewFile();
//判断文件是否存在
System.out.println(f.exists());
System.out.println(f.getName());
//获取文件创建时间
long dt = f.lastModified();
Date date = new Date(dt);
DateFormat df = DateFormat.getDateTimeInstance();
System.out.println(df.format(date));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd H:mm:ss.SSS");
System.out.println(sdf.format(date));
//获取文件长度
System.out.println(f.length());
//删除文件
f.delete();
字节流
//=======简单输入(读)==========
FileInputStream fin = new FileInputStream("d:/files/b.txt");
byte [] b = new byte[fin.available()];
fin.read(b);
String str = new String(b);
System.out.println(str);
fin.close();
//========简单输出(写)========
FileOutputStream fout = new
//这里的false表示覆盖原文件内容,如果是true就是添加内容不覆盖
FileOutputStream("d:/files/b.txt",false);
// fout.write(97);
String s = "ABC";
byte [] b = s.getBytes();
// fout.write(b);
//这里可以选择输出的范围,比如下面的:[0,2)
fout.write(b,0,2);
fout.close();
//=======在输入(读)的时候也可以把字节流的内容转换成字符流再读=======
FileInputStream fin = new FileInputStream("d:/files/b.txt");
InputStreamReader fr = new InputStreamReader(fin);
int temp;
while((temp = fr.read()) != -1) {
System.out.print((char)temp);
}
fin.close();
fr.close();
缓冲流(用来提高效率)
//这里建立了一个缓冲区来传输一个图片。这样相比一个一个字节的传输效率高一点。
FileInputStream fin = new FileInputStream("d:/huaji.jpg");
BufferedInputStream bfin = new BufferedInputStream(fin);
FileOutputStream fout = new FileOutputStream("d:/files/huaji.jpg");
BufferedOutputStream bfout = new BufferedOutputStream(fout);
int temp;
while((temp = bfin.read()) != -1) {
bfout.write(temp);
}
//一定要刷新缓冲区
bfout.flush();
//关闭流
bfin.close();
bfout.close();
数据流
FileOutputStream fout = new FileOutputStream("d:/files/b.txt");
DataOutputStream dfout = new DataOutputStream(fout);
int [] no = {11,22,33};
String [] name = {"aa","bb","cc"};
for(int i = 0; i < no.length; i ++) {
//这里写入文件后会出乱码,这个问题是Data这个流的设计决定的,
//其实用下边的再把这些“乱码”读出来就能正常输出。
//其实他们本身并没有乱码,只是在txt里展示不出来而已。
dfout.writeInt(no[i]);
dfout.writeUTF(name[i]);
}
dfout.close();
FileInputStream fin = new FileInputStream("d:/files/b.txt");
DataInputStream dfin = new DataInputStream(fin);
for(int i = 0 ; i < no.length ; i ++) {
System.out.print(dfin.readInt());
System.out.print(dfin.readUTF());
}
dfin.close();
对象流
对象流其实就是序列化和反序列化的过程。输入的时候(读)就是反序列化,将字节序列变成对象;而 输出的时候(写)就是序列化,把对象存储成字节序列。
这里需要一个自带的接口Serializable,用来做一个标识,告诉程序这个类是一个能创建对象流的类。
class Age implements Serializable{
private int age;
public Age(int age) {
super();
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class Student implements Serializable{
private static final long serialVersionUID = 1L;
private int no;
private String name;
private Age age;
public Student(int no,String name,Age age) {
super();
this.no = no;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [no=" + no + ", name=" + name + ", age=" + age.getAge() + "]";
}
}
public class TestSubThread {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Student guojing = new Student(1,"郭靖",new Age(22));
System.out.println(guojing);
//序列化
File f = new File("d:/files/c.txt");
FileOutputStream fout = new FileOutputStream(f);
ObjectOutputStream objOut = new ObjectOutputStream(fout);
f.createNewFile();
objOut.writeObject(guojing);
objOut.close();
//反序列化
FileInputStream fin = new FileInputStream("d:/files/b.txt");
ObjectInputStream objIn = new ObjectInputStream(fin);
Student stu = (Student)objIn.readObject();
System.out.println(stu.toString());
objIn.close();
}
}
!这里会有人问为什么存到txt的乱码的。那并非乱码。
ObjectOutputStream.writeObject()的作用是把一个实例的对象以文件的形式保存到磁盘上,这个过程就叫Java对象的持久化。
而这个文件是以二进制的形式编写的,当你用文本编辑器将它打开,这些二进制代码与某个字符集映射之后,显示出来的东西就成了乱码。
即使输出的是一个String的对象,也是以该String对象的二进制编码的形式输出,而不是输出String对象的内容。
来源:ObjectOutputStream 用writeObject输出文本是乱码
字符流
只能存储纯文本的东西
字符流的继承关系
网友评论