IO流的详解!超详细!
IO流
Java的IO通过java.io包下的类和接口来支持,在java.io包下主要包括输入、输出两种IO流,每种输入、输出流又可以分为字节流和字符流两大类。其中字节流是以字节为单位来处理输入输出的操作,而字符流则是以字符来处理输入输出的操作。除此之外,JavaIO使用了一种装饰器设计模式,又可以将IO流分为底层的节点流和上层的处理流。
流的分类:
1:输入流和输出流
输入流:只能从中读取数据,不能写入数据。
输出流:只能写入数据,而不能读取数据。
Java中的输入流主要是右InputStream和Reader作为基类,而输出流主要是由OutputStream和Writer作为基类。他们都是抽象类,无法创建实例。
2:字节流和字符流
字节流:的操作数据单元是8位字节。
字符流:的操作数据是16位字符。
字节流中 InputStream与OutputStream为字节流的基类,Reader和Writer为字符流的基类。
3:节点流和处理流
节点流:可以向/从 一个特定的IO设备读写数据的流, 节点流连接着数据源和程序。互相关联。
处理流:用于对已经存在的一个流进行连接和封装,通过封装后的流来实现数据的读写功能。程序使用处理流之后并不会直接连接到数据源,使用处理流的好处是,只要使用相同的处理流,程序就可以采用完全相同的输入输出代码访问不同的数据源,随着处理流封装的节点流的变化,程序实际访问的数据源也发生了变化。
流的概念模型
字节流和字符流处理的方式非常的相似,只是输入输出的单位不同而已,输入流使用隐式指针来记录从哪个位置开去读取,每当InputStream或者Reader里取出一个数据后,记录的指针自动向后移一位,除此之外,InputStream和Reader都提供了一些二方法来记录了指针的移动。输出流也一样。
处理流可以嫁接在任何一个已经存在的流的基础之上,这就允许了Java采用了相同的代码,透明的方式来访问不同的输入/输出设备的数据流,通过使用处理流,Java程序不需要在意输入输出的节点是什么,程序只要把这些节点包装成处理流,就可以使用相同的处理流的代码来进行读写。
字节流和字符流
1:输入流
InputStream和Reader是输入流的抽象基类,本身不能创建实例来进行输入,但是他们是所有输入流的模板。
它们的操作方式基本一样,只是inputStream操作的是字节,而Reader操作的是字符。
InputStream(字节输入流)方法:
int read():从输入流中读取单个字节,返回读取字节的数据。
int read(byte[ ]b):从输入流中读取最多b.length个字节的数据。并把读取出来的数据存取在b数组中,返回实际读取的字节数。
int read(byte[ ]b,int off,int len):从输入流最多读取len个字节的数据,放入数组b中,从off的位置开始存放,返回实际读取的字节数。
Reader(字节输出流的方法大致相同,字节输入流只不过存取读取的数据用byte类型的数组来进行存,但是reader使用char类型的数组进行存取,因为它是字符输入流)
那么我们如何判断读取的数据到了结尾呢?根据指针的指引,每次读取一个数据,指针向后指引,当指针为-1的时候,便说明了读取完毕。就到达了输入流的结束点。
由于inputStream和OutputStream都是抽象类,本身不能创建实例,但是他们都有一个读取文件的输入流:FileInputStream和FileReader。他们本身都是节点流————直接和文件相关联
package fileinput;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class FileInput {
public static void main(String[] args) throws Exception {
FileInputStream fileInputStream=new FileInputStream("G:\\a.txt");
//向使用b数组来存取G盘文件的内容
//因为程序创建了长度为1024的数组来进行读取,但是长度却达不到1024,所以说只要执行一次read
//就能读取所有的文本数据
byte[]b=new byte[1024];
//length定义一个记录存取长度的变量
int len=0;
while ((len=fileInputStream.read(b))!=-1){
System.out.println(new String(b,0,len));
}
fileInputStream.close();
}
}
使用FileReader来读取文件:
package fileinput;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderTest {
public static void main(String[] args) throws IOException{
FileReader fileReader=new FileReader("G:\\b.txt");
char[]c=new char[1024];
int len=0;
while ((len=fileReader.read(c))!=-1){
System.out.println(new String(c,0,len));
}
fileReader.close();
}
}
2:输出流(字节输出流和字符输出流)
OutputStream和Writer也非常相似
OutputStream输出流的三种方法:
1:void write(int c) 将指定的字节字符输出到输出流中,其中c既可以代表字节,也可以代表字符。
2:void write(byte【】/char【】buf):将指定的字节数组或者字符数组输出到输出流中
3:void write(byte[ ]/char [ ]buf,int off,int len)将字节数组或者字符数组从off的位置开始,长度为len的字节或者字符输出到输出流当中。
writer的方法也相似,只不过字节输出流输出的是字节或者字符,而writer输出的是字符串String
下面使用FileInputStream来进行输入,FileOutputStream来进行输出,实现文字的复制:
package fileinput2;
import fileinput.FileInput;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyTest {
public static void main(String[] args) throws IOException{
//读取a的文件内容
FileInputStream fileInputStream=new FileInputStream("G:\\a.txt");
byte[]b=new byte[1024];
int len=0;
len=fileInputStream.read(b);
fileInputStream.close();
//将读取内容写入b
FileOutputStream fileOutputStream=new FileOutputStream("G:\\b.txt");
fileOutputStream.write(b,0,len);
fileOutputStream.close();
//将B中文件进行输出
FileInputStream fileInputStream1=new FileInputStream("G:\\b.txt");
while ((len=fileInputStream1.read(b))!=-1){
System.out.println(new String(b,0,len));
}
fileInputStream1.close();
}
}
通过字符流实现文字拷贝:
package fileinput2;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyString {
public static void main(String[] args) throws IOException{
FileReader fileReader=new FileReader("G:\\a.txt");
char[]c=new char[1024];
int len=0;
len=fileReader.read(c);
fileReader.close();
//读取
FileWriter fileWriter=new FileWriter("G:\\b.txt");
fileWriter.write(c,0,len);
fileWriter.close();
//打印b
FileReader fileReader1=new FileReader("G:\\b.txt");
while((len=fileReader1.read(c))!=-1){
System.out.println(new String(c,0,len));
}
fileReader1.close();
}
}
我们使用了输出输出流的4个抽象的基类,并且使用了4中方法来对文件输入输出等访问,
字节流 基类:FileInputStream FileOutputStream 字符流基类:FileReader FileWriter
输入流:FileInputStream FileReader 输出流:FileOutputStream FileWriter
发现使用起来比较繁琐,所以我们需要一种办法来简化操作,这时我们需要认识一下处理流了。
处理流:
我们尝试用PrintStream来对FileOutputStream进行处理输出
package chuliStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
public class PrintStreamTest {
public static void main(String[] args)throws IOException {
FileOutputStream fileOutputStream=new FileOutputStream("G:\\a.txt");
PrintStream ps=new PrintStream(fileOutputStream);//对字节流进行包装
ps.println("嘿嘿嘿");
ps.println("哈哈哈哈");//可以将里面的内容进行存储
ps.close();//我们只需要关闭最上层的处理流,包装的节点流也就关闭了
}
}
转换流:
将字节流转换成字符流,有两个InputStreamReader和OutputStreamWriter
为什么只是字节流转换成字符流?
因为大家都知道,字节流用途更广,但是字符流操作起来比较方便,当我们知道一个文件都是文本内容,但是我们只有一个字节流,操作起来相当繁琐,所以我们需要转换流来对字节流进行转换,这样操作起来就十分的方便。
就比如说我们要从键盘上获取数据,但是标准的输入流是InputStream是字节流,处理起来十分难受,但是键盘输入的都是文本内容。普通的Reader的方法读取文本也很繁琐,所以我们引入转换输入流InputStreamReader(字符输入流),再将字符输入流包装成为BufferedReader。使用readLine方法进行一行一行读取,十分方便。
package chuliStream;
import java.io.*;
public class ZhuanHuanLiu {
public static void main(String[] args)throws Exception {
InputStreamReader inputStreamReader=new InputStreamReader(System.in);
BufferedReader b=new BufferedReader(inputStreamReader);//包装转换字符流
// System.out.println(b.readLine());//将键盘输入的进行打印
FileOutputStream file=new FileOutputStream("G:\\b.txt");
OutputStreamWriter outputStreamWriter=new OutputStreamWriter(file);
BufferedWriter bufferedWriter=new BufferedWriter(outputStreamWriter);//处理流效率高
bufferedWriter.write(b.readLine());
bufferedWriter.close();
b.close();
}
}
对象的序列化:
对象的序列化就是将对象目标保存在磁盘中,或者允许网络中直接传输对象,Java序列化的机制是允许将对象直接转化为网络中的二进制流,可以通过这种二进制流传输到网络中的另一个节点,其他网络中或者程序中获得了该二进制流都可以将其还原成Java中之前的对象。
对象的序列化:是将Java中的对象写入IO流中。
对象的反序列化:从IO流中读取到 Java对象。
为了让某个类的对象可以序列化,这个类必须要是可以序列化的,所以就需要导入Serializable接口。
因为传输的是 对象,所以我们需要引入两个处理流
ObjectInputStream、ObjectOutputStream 对象输入流和对象输出流
因为这两个流都是处理流,需要包装节点类,所以在使用他们的时候还需要一个节点流来搭配着使用
ObjectOutputStream使用方法
TCP 发送方 和接收方,发送方发送对象,接收方接受对象,返回ok
package socket;
import java.io.*;
import java.net.Socket;
public class SSocket {
public static void main(String[] args) throws Exception{
Socket socket=new Socket("192.168.55.16",9999);
ObjectOutputStream objectOutputStream=new ObjectOutputStream(
socket.getOutputStream());
Person p=new Person("刘大",11);
Person p2=new Person("六二",15);
objectOutputStream.writeObject(p);
objectOutputStream.writeObject(p2);
InputStreamReader inputStreamReader=new InputStreamReader(socket.getInputStream());
BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
String str=bufferedReader.readLine();
System.out.println(str);
objectOutputStream.close();
inputStreamReader.close();
socket.close();
}
}
package socket;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerSocketTest {
public static void main(String[] args)throws Exception {
ServerSocket serverSocket=new ServerSocket(9999);
while (true) {
Socket socket = serverSocket.accept();
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
System.out.println(objectInputStream.readObject());
System.out.println(objectInputStream.readObject());
OutputStreamWriter outputStreamWriter=new OutputStreamWriter(socket.getOutputStream());
BufferedWriter bufferedWriter=new BufferedWriter(outputStreamWriter);
bufferedWriter.write("ok");
//刷新
bufferedWriter.newLine();
bufferedWriter.flush();
objectInputStream.close();
outputStreamWriter.close();
socket.close();
}
}
}
还没有评论,来说两句吧...