絮叨
昨天已经把文件的创建,文件夹的创建 删除等操作讲完了,接下来我们进入我们的正题,没有看过上一篇的可以去看看
送大家几句我读书看到的话,哈哈 我反正看到了就分享一下 余秋雨的
人生的路靠自己一步步走去,真正能保护你的是你自己人格的选择和文化的选择,那么反过来,真正能伤害你的同样也是你自己的选择。
I/O 工作原理
这个在昨天的介绍中没讲,今天补一下,反正我讲东西,也是一边学一边写,看到了就写一下。
磁盘I/O
典型I/O读写磁盘工作原理如下:
tips: DMA:全称叫直接内存存取(Direct Memory Access),是一种允许外围设备(硬件子系统)直接访问系统主内存的机制。基于 DMA 访问方式,系统主内存与硬件设备的数据传输可以省去CPU 的全程调度
特点
- 读写操作基于系统调用实现
- 读写操作经过用户缓冲区,内核缓冲区,应用进程并不能直接操作磁盘
- 应用进程读操作时需阻塞直到读取到数据
网络I/O
特点
- 网络I/O读写操作经过用户缓冲区,Sokcet缓冲区
- 服务端线程在从调用recvfrom开始到它返回有数据报准备好这段时间是阻塞的,recvfrom返回成功后,线程开始处理数据报
Java I/O设计
Java中对数据流进行具体化和实现,关于Java数据流一般关注以下几个点:
- (1) 流的方向 从外部到程序,称为输入流;从程序到外部,称为输出流
- (2) 流的数据单位 程序以字节作为最小读写数据单元,称为字节流,以字符作为最小读写数据单元,称为字符流
- (3) 流的功能角色
从/向一个特定的I
O设备(如磁盘,网络)或者存储对象(如内存数组)读/写数据的流,称为节点流; 对一个已有流进行连接和封装,通过封装后的流来实现数据的读/写功能,称为处理流(或称为过滤流);
Java流类图结构:
字节流介绍:
处理字节数据的流对象。设备上的数据无论是图片或者dvd,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据,但是在处理字符上的速度不如字符流。
字符流介绍:
因为字符每个国家都不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时+ 指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。
流的体系因为功能不同,但是有共性内容,不断抽取,形成继承体系。该体系一共有四个基类,而且都是抽象类。: 字节流:InputStream OutputStream 字符流:Reader Writer
常见字节流:
InputStream:是表示字节输入流的所有类的超类。
- FileInputStream:从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。
- FilterInputStream:包含其他一些输入流,它将这些流用作其基本数据源,它可以直接传输数据或提供一些额外的功能。
- BufferedInputStream:该类实现缓冲的输入流。
- Stream:
- ObjectInputStream:
- PipedInputStream:
OutputStream:此抽象类是表示输出字节流的所有类的超类。
- FileOutputStream:文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。
- FilterOutputStream:此类是过滤输出流的所有类的超类。
- BufferedOutputStream:该类实现缓冲的输出流。
- PrintStream:
- DataOutputStream:
- ObjectOutputStream:
- PipedOutputStream:
常见字符流:
Reader:用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。
- BufferedReader:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
- LineNumberReader:跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。
- InputStreamReader:是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
- FileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。
- CharArrayReader:
- StringReader:
Writer:写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。
- BufferedWriter:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
- OutputStreamWriter:是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
- FileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。
- PrintWriter:
- CharArrayWriter:
- StringWriter:
字节流
在上一篇博客中,我们一直都是在操作文件或者文件夹,并没有给文件中写任何数据。现在我们就要开始给文件中写数据,或者读取文件中的数据
字节输出流OutputStream
OutputStream此抽象类,是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法
输出流中定义都是写write方法
FileOutputStream类
OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件
FileOutputStream类,即文件输出流,是用于将数据写入 File的输出流
- 构造方法
例子
- 将数据写到文件中,代码演示
public static void main(String[] args) throws IOException { //创建存储数据的文件。 File file = new File("E:\\file.txt"); //创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。 //输出流目的是文件,会自动创建。如果文件存在,则覆盖。 FileOutputStream fos = new FileOutputStream(file); //调用父类中的write方法。 byte[] data = "abcde".getBytes(); fos.write(data); //关闭流资源。 fos.close(); } 复制代码
我们直接new FileOutputStream(file)这样创建对象,写入数据,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?
- 构造方法
例子 给文件中续写数据和换
public static void main(String[] args) throws Exception { File file = new File("E:\\file.txt"); FileOutputStream fos = new FileOutputStream(file, true); String str = "\r\n"+"HelloIO"; fos.write(str.getBytes()); fos.close(); } 复制代码