知识点
- I/O流的基本知识
- I/O流中常用流的关系
- I/O流之FileInputSrteam,FileOutputStream
- I/O流之FileReader,FileWriter
- I/O流之InputStreamReader,OutputStreamWriter
- I/O流之BufferedReader,BufferedWriter
- I/O流之DataOutputStream,DataInputStream
- I/O流之ObjectOutputStream,ObjectInputStream
一、I/O流的基本知识
1.1 java中的流是对于内存而言的,分为: 输入流,输出流
- 输入流:将数据从磁盘读取到内存中的为输入流
- 输出流:将数据从内存中写入到磁盘中的位输出流
1.2 而根据流的读取方式又可以分为:字节流,字符流
字节流
定义:字节流是按照字节的方式读取数据
作用:字节流适合读取视频,音乐,图片等二进制文件
特点:java语言中所有的字节流都以stream结尾字符流
定义:字符流是按照字符的方式读取数据,也就是一次读取2个字节,java中一个字符占2个字节
作用:字符流适合读纯文本文件(不包括文件格式)
特点:java语言中所有的字符流都以Reader/Writer结尾
二、I/O流中常用流的关系
2.1 常用流主要由如下类:
FileInputStream
FileOutInputStream
FileReade
FileWriter
BufferedInputStream
BufferedOutStream
BufferedReader
BufferedWriter
DateInputStream
DateOutputStream
ObjectInputStream
ObjectOutputStream
InputStreamReader
OutStreamWriter
PrintWriter
PrintStream
2.2常用类的继承关系:
字节流:
字符流:
三、I/O流之FileInputSrteam,FileOutputStream
3.1 FileInputSrteam
FileInputSrteam的构造方法:
//参数为 文件地址
FileInputStream(String name)
FileInputSrteam的常用方法:
//从输入流中读取一个字节,范围数据为读取到的字节数,若读取不到数据返回-1(该方式不适合用于读取长文本)
int read();
//从次此输入流中读取b.length个字节,范围类型为读取的字节个数,若读取不到数据返回-1
int read(byte[] b);
//从此输入流中将最多len个字节的数据读入到一个byte数组中
int read(byte[] b,int off,int len);
//返回下一次对此输入流可以读取到的估计剩余字节数
int available();
//从输入流中跳过并丢弃n个字节数据
long skip(long n);
使用栗子
有一个abcdefg文件,里面记录有abcdefg几个字母
public static void main(String[] args){
FileInputStream fileInputStream=null;
try {
fileInputStream=new FileInputStream("abcdefg.txt");
System.out.println("available="+fileInputStream.available());
System.out.println("read()="+fileInputStream.read());
byte[] bytes=new byte[2];
int temp=fileInputStream.read(bytes);
System.out.println("read(byte[] b)="+new String(bytes,0,temp));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if(fileInputStream!=null){
fileInputStream.close();
}
}
}
//输出结果
available=7
read()=97
read(byte[] b)=bc
3.1 FileOutputSrteam
FileOutputSrteam和FileInputStream是相对的,所以使用方式也是类似
FileOutputSrteam的构造方法
//文件路径
**FileOutputSrteam(String name)**
/*
*@parem name 文件路径
*@parem append 是否追加内容
*/
FileOutputStream(String name,boolean append)
第一个方法创建的输出流每次写入到磁盘文件都会进行内容覆盖,而第二创建的输出流则根据传入的参数判断是否是追加写入
FileOutputStream的常用方法:
//将b.length个字节从指定的byte数组写入到此文件输出流中
void write(byte[] b)
//将指定的byte[]数组中从偏移量off开始的len个字节写入到此文件输出流中
void write(byte[] b ,int off ,int len)
//将指定的字节写入此文件输出流中
void write(int b )
使用例子:
public static void main(String[] args){
FileOutputStream fos=null;
try {
fos=new FileOutputStream("abcdefg.txt");
String msg="Hellworld";
byte[] b=msg.getBytes();
fos.write(b);
//强制写入
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
if( fos!=null){
fos.close();
}
}
四、I/O流之FileReader,FileWriter
其实FileReader和FileWriter,和上面FileInputStream,FileOutputStream的用法基本一致的,只是从字节流变换成了字符流,而使用字符流的好处就是在读取文字的时候可以确保读取到完整的一个汉字(java中一个汉字占2个字节=一个字符),就避免了出现乱码的情况
由于用法差不多,这里就不在做细说,直接上个栗子吧
4.1 文件复制栗子
public static void main(String[] args){
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("E:myClass.java");
fw = new FileWriter("C:\\test\\myClass1.java", true);
char[] chars = new char[512]; //1kb
int temp;
while ((temp = fr.read(chars)) != -1) {
fw.write(chars, 0, temp);
}
//强制写入
fw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fr != null) {
fr.close();
}
if (fw != null) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
熟悉了第三部分的字节流,那么这里的字符流也同样熟悉了
五、I/O流之InputStreamReader,OutputStreamWriter
InputStreamReader,OutputStreamWriter是比较有用的,因为他们是负责转换的,也叫转换流,这两个类可以将字节流转换成字符流
5.1 InputStreamReader
构造方法:
//构造方法返回一个InputStreamReade继承至Reader,字符输入流的用法前面FileReader已经讲解,这里用法是类似的
InputStreamReader(InputStream var1);
InputStreamReader(InputStream var1, String var2)
5.2 OutputStreamWriter
构造方法:
//构造方法返回一个OutputStreamWriter继承至Writer,字符输出流的用法前面FileWriter已经讲解,这里用法是类似的
OutputStreamWriter(OutputStream var1);
OutputStreamWriter(OutputStream var1, String var2);
六、I/O流之BufferedReader,BufferedWriter
buffered类型的流是指带有缓冲区的流类型,其有个很方便的方法就是可以直接读写一行数据
6.1 BufferedReader
构造方法:
BufferedReader(Reader reader);
BufferedReader(Reader reader,int size);
常用方法:
//readLine读取的数据是不会带末尾的换行符
String BufferedReader.readLine();
6.2 BufferedWriter
构造方法:
BufferedWriter(Writer writer);
BufferedWriter(Writer writer,int size);
常用方法:
void writer(char [],int off,int len);
void writer(int c);
void writer(String s,int off,int len);
void newLine();
七、I/O流之DataOutputStream,DataInputStream
data类型的字节流,可以将内存中的数据包括该数据的类型一起写入到文件中,在读取的时候也可以直接读取某个类型的数据,比如 int a=10; 它就会把int的类型的10写入到文件中,而不是单纯的写个10字符进去
7.1 DataOutputStream
构造方法:
DataoutputSteam (OutputSteam out);
常用方法:
void writeByte(byte b);
void writeShort(short s);
void writeInt(int t);
void writeLong(long l);
void writeFloat(float f);
void writeDouble(double b);
void writeBoolean(boolean b);
void writeChar(char c);
注意:由于dataoutputstream在写入数据的时候带上了数据类型,所以对于写入的文件是写入了二进制类型的数据,直接打开文件是看不懂的,必须使用对应的dataintputstream来读取文件数据
7.2 DataIntpuStream
构造方法:
DataInputSteam(InputStream is);
常用方法:
byte readByte(byte b);
short readShort(short s);
int readInt(int t);
long readLong(long l);
float readFloat(float f);
double readDouble(double b);
boolean readBoolean(boolean b);
char readChar(char c);
注意:在读取数据的时候,必须提前知道文件存储的格式,顺序,读取的顺序必须和写入的数据一致,不然无法读取数据
八、I/O流之ObjectOutputStream,ObjectInputStream
Objec的字节流类型其实相当于我们常说的,类的序列化和反序列化,其作用就是把java类对象写入到文件中,或者从文件中读取一个类对象的信息
8.1 ObjectOutputStream
相当于对对象实现序列化写入文件中,但前提该类对象实现了Serializable接口
构造方法:
ObjectOutputStream();
ObjectOutputStream(OutputStream out);
常用方法:
void writeObject(object obj);
8.2 ObjectInputStream
读取文件中的类信息,就是常说的反序列化
构造方法:
ObjectInputStream();
ObjectInputStream(InputStream in);
常用方法:
Object readObject();
注意:在反序列的时候,jvm会识别一个序列化ID,该ID的在我们做序列化的时候因为实现了serializable接口,所以jvm会自动帮我们的类对象加上一个static final long serialVersionUID;
的属性,而该属性的作用是在反序列的时候,jvm会对比当前反序列化文件中的UID和当前序列化对象的class中的UID是否一致,如果不一致则会报异常
通常可以直接在实现序列化接口的时候自行定义一个serialVersionUID的成员变量,这样jvm就不会再覆写一个UID,保证了在序列化和反序列的时候使用了同一个UID
总结
I/O流在日常开发逻辑中可能用得不是很多,但是I/O流在做数据持久化中是必不可少的知识,理解清楚常用流的作用以及它们之间的关系,可以在做数据写入和读取的时候更加得心应手。