1. 字节流

在前面的学习过程中,我们一直都是在操作文件或者文件夹,并没有给文件中写任何数据。现在我们就要开始给文件中写数据,或者读取文件中的数据。

1.1 字节输出流OutputStream

OutputStream此抽象类,是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法。

输出流中定义都是写write方法,如下图:

1.1.1 FileOutputStream类

OutputStream有很多子类,其中子类FileOutputStream可用来写入数据到文件。

FileOutputStream类,即文件输出流,是用于将数据写入 File的输出流。

构造方法

1.1.2 FileOutputStream类写入数据到文件中

将数据写到文件中,代码演示:

  1. public class FileOutputStreamDemo {
  2. public static void main(String[] args) throws IOException {
  3. //需求:将数据写入到文件中。
  4. //创建存储数据的文件。
  5. File file = new File("c:\\file.txt");
  6. //创建一个用于操作文件的字节输出流对象。一创建就必须明确数据存储目的地。
  7. //输出流目的是文件,会自动创建。如果文件存在,则覆盖。
  8. FileOutputStream fos = new FileOutputStream(file);
  9. //调用父类中的write方法。
  10. byte[] data = "abcde".getBytes();
  11. fos.write(data);
  12. //关闭流资源。
  13. fos.close();
  14. }
  15. }

1.1.3 给文件中续写和换行

我们直接new FileOutputStream(file)这样创建对象,写入数据,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?

继续查阅FileOutputStream的API。发现在FileOutputStream的构造函数中,可以接受一个boolean类型的值,如果值true,就会在文件末位继续添加。

构造方法

给文件中续写数据和换行,代码演示:

  1. public class FileOutputStreamDemo2 {
  2. public static void main(String[] args) throws Exception {
  3. File file = new File("c:\\file.txt");
  4. FileOutputStream fos = new FileOutputStream(file, true);[设置给指定文件续写数据]
  5. String str = "\r\n"[实现换行]+"itcast";
  6. fos.write(str.getBytes());
  7. fos.close();
  8. }
  9. }

1.1.4 IO异常的处理

在前面编写代码中都发生了IO的异常。我们在实际开发中,对异常时如何处理的,我们来演示一下。

  1. public class FileOutputStreamDemo3 {
  2. public static void main(String[] args) {
  3. File file = new File("c:\\file.txt");
  4. //定义FileOutputStream的引用
  5. FileOutputStream fos = null;
  6. try {
  7. //创建FileOutputStream对象
  8. fos = new FileOutputStream(file);
  9. //写出数据
  10. fos.write("abcde".getBytes());
  11. } catch (IOException e) {
  12. System.out.println(e.toString() + "----");
  13. } finally {
  14. //一定要判断fos是否为null,只有不为null时,才可以关闭资源
  15. if (fos != null) {
  16. try {
  17. fos.close();
  18. } catch (IOException e) {
  19. throw new RuntimeException("");
  20. }
  21. }
  22. }
  23. }
  24. }

1.2 字节输入流InputStream

通过前面的学习,我们可以把内存中的数据写出到文件中,那如何想把内存中的数据读到内存中,我们通过InputStream可以实现。InputStream此抽象类,是表示字节输入流的所有类的超类。,定义了字节输入流的基本共性功能方法。

int read():读取一个字节并返回,没有字节返回-1.

int read(byte[]): 读取一定量的字节数,并存储到字节数组中,返回读取到的字节数。

1.2.1 FileInputStream类

InputStream有很多子类,其中子类FileInputStream可用来读取文件内容。

FileInputStream 从文件系统中的某个文件中获得输入字节。

构造方法

1.2.2 FileInputStream类读取数据read方法

在读取文件中的数据时,调用read方法,实现从文件中读取数据

从文件中读取数据,代码演示:

  1. public class FileInputStreamDemo {
  2. public static void main(String[] args) throws IOException {
  3. File file = new File("c:\\file.txt");
  4. //创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
  5. FileInputStream fis = new FileInputStream(file);
  6. //读取数据。使用 read();一次读一个字节。
  7. int ch = 0;
  8. while((ch=fis.read())!=-1){
  9. System.out.pr }intln("ch="+(char)ch);
  10.  
  11. // 关闭资源。
  12. fis.close();
  13. }
  14. }

1.2.3 读取数据read(byte[])方法

在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符。

  1. public class FileInputStreamDemo2 {
  2. public static void main(String[] args) throws IOException {
  3. /*
  4. * 演示第二个读取方法, read(byte[]);
  5. */
  6. File file = new File("c:\\file.txt");
  7. // 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
  8. FileInputStream fis = new FileInputStream(file);
  9. //创建一个字节数组。
  10. byte[] buf = new byte[1024];//长度可以定义成1024的整数倍。
  11. int len = 0;
  12. while((len=fis.read(buf))!=-1){
  13. System.out.println(new String(buf,0,len));
  14. }
  15. fis.close();
  16. }
  17. }

1.3 字节流练习

既然会了文件的读和写操作了,那么我们就要在这个基础上进行更为复杂的操作。使用读写操作完成文件的复制。

1.3.1 复制文件

原理;读取一个已有的数据,并将这些读到的数据写入到另一个文件中。

  1. public class CopyFileTest {
  2. public static void main(String[] args) throws IOException {
  3. //1,明确源和目的。
  4. File srcFile = new File("c:\\YesDir\test.JPG");
  5. File destFile = new File("copyTest.JPG");
  6.  
  7. //2,明确字节流 输入流和源相关联,输出流和目的关联。
  8. FileInputStream fis = new FileInputStream(srcFile);
  9. FileOutputStream fos = new FileOutputStream(destFile);
  10.  
  11. //3, 使用输入流的读取方法读取字节,并将字节写入到目的中。
  12. int ch = 0;
  13. while((ch=fis.read())!=-1){
  14. fos.write(ch);
  15. }
  16. //4,关闭资源。
  17. fos.close();
  18. fis.close();
  19. }
  20. }

上述代码输入流和输出流之间是通过ch这个变量进行数据交换的。

上述复制文件有个问题,每次都从源文件读取一个,然后在写到指定文件,接着再读取一个字符,然后再写一个,一直这样下去。效率极低。

1.3.2 缓冲数组方式复制文件

上述代码复制文件效率太低了,并且频繁的从文件读数据,和写数据,能不能一次多把文件中多个数据都读进内容中,然后在一次写出去,这样的速度一定会比前面代码速度快。

  1. public class CopyFileByBufferTest {
  2. public static void main(String[] args) throws IOException {
  3. File srcFile = new File("c:\\YesDir\test.JPG");
  4. File destFile = new File("copyTest.JPG");
  5. // 明确字节流 输入流和源相关联,输出流和目的关联。
  6. FileInputStream fis = new FileInputStream(srcFile);
  7. FileOutputStream fos = new FileOutputStream(destFile);
  8. //定义一个缓冲区。
  9. byte[] buf = new byte[1024];
  10. int len = 0;
  11. while ((len = fis.read(buf)) != -1) {
  12. fos.write(buf, 0, len);// 将数组中的指定长度的数据写入到输出流中。
  13. }
  14. // 关闭资源。
  15. fos.close();
  16. fis.close();
  17. }
  18. }

第1章 字符流

经过前面的学习,我们基本掌握的文件的读写操作,在操作过程中字节流可以操作所有数据,可是当我们操作的文件中有中文字符,并且需要对中文字符做出处理时怎么办呢?

2.1 字节流读取字符的问题

通过以下程序读取带有中文件的文件。

  1. public class CharStreamDemo {
  2. public static void main(String[] args) throws IOException {
  3. //给文件中写中文
  4. writeCNText();
  5. //读取文件中的中文
  6. readCNText();
  7. }
  8. //读取中文
  9. public static void readCNText() throws IOException {
  10. FileInputStream fis = new FileInputStream("c:\\cn.txt");
  11. int ch = 0;
  12. while((ch = fis.read())!=-1){
  13. System.out.println(ch);
  14. }
  15. }
  16. //写中文
  17. public static void writeCNText() throws IOException {
  18. FileOutputStream fos = new FileOutputStream("c:\\cn.txt");
  19. fos.write("a传智播客欢迎你".getBytes());
  20. fos.close();
  21. }
  22. }

上面程序在读取含有中文的文件时,我们并没有看到具体的中文,而是看到一些数字,这是什么原因呢?既然看不到中文,那么我们如何对其中的中文做处理呢?要解决这个问题,我们必须研究下字符的编码过程。

2.2 字符编码表

我们知道计算机底层数据存储的都是二进制数据,而我们生活中的各种各样的数据,如何才能和计算机中存储的二进制数据对应起来呢?

这时老美他们就把每一个字符和一个整数对应起来,就形成了一张编码表,老美他们的编码表就是ASCII表。其中就是各种英文字符对应的编码。

编码表:其实就是生活中字符和计算机二进制的对应关系表。

1、ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx

2、iso-8859-1:拉丁码表 latin,用了一个字节用的8位。1-xxxxxxx  负数。

3、GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节是负数,第二个字节可能是正数

  GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0

  GB18030:最新的中文码表,目前还没有正式使用。

4、unicode:国际标准码表:无论是什么文字,都用两个字节存储。

  Java中的char类型用的就是这个码表。char c = 'a';占两个字节。

  Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。

5、UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)。

  能识别中文的码表:GBK、UTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。

  对于我们开发而言;常见的编码 GBK  UTF-8  ISO-8859-1

  文字--->(数字) :编码。 “abc”.getBytes()  byte[]

  (数字)--->文字  : 解码。 byte[] b={97,98,99}  new String(b)

2.3 字符输入流Reader

上述程序中我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都是一个一个字节。只要把这些字节去查阅对应的编码表,就能够得到与之对应的字符。API中是否给我们已经提供了读取相应字符的功能流对象,Reader,读取字符流的抽象超类。

read():读取单个字符并返回

read(char[]):将数据读取到数组中,并返回读取的个数。

2.3.1 FileReader类

查阅FileInputStream的API,发现FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。

打开FileReader的API介绍。用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的

构造方法

2.3.2 FileReader读取包含中文的文件

使用FileReader读取包含中文的文件

  1. public class CharStreamDemo {
  2. public static void main(String[] args) throws IOException {
  3. //给文件中写中文
  4. writeCNText();
  5. //读取文件中的中文
  6. readCNText();
  7. }
  8. //读取中文
  9. public static void readCNText() throws IOException {
  10. FileReader fr = new FileReader("D:\\test\\cn.txt");
  11. int ch = 0;
  12. while((ch = fr.read())!=-1){
  13. //输出的字符对应的编码值
  14. System.out.println(ch);
  15. //输出字符本身
  16. System.out.println((char)ch);
  17. }
  18. }
  19. //写中文
  20. public static void writeCNText() throws IOException {
  21. FileOutputStream fos = new FileOutputStream("D:\\test\\cn.txt");
  22. fos.write("a传智播客欢迎你".getBytes());
  23. fos.close();
  24. }
  25. }

2.4 字符输出流Writer

既然有专门用于读取字符的流对象,那么肯定也有写的字符流对象,查阅API,发现有一个Writer类,Writer是写入字符流的抽象类。其中描述了相应的写的动作。

2.4.1 FileWriter类

查阅FileOutputStream的API,发现FileOutputStream 用于写入诸如图像数据之类的原始字节的流。要写入字符流,请考虑使用 FileWriter。

打开FileWriter的API介绍。用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。

构造方法

2.4.2 FileWriter写入中文到文件中

写入字符到文件中,先进行流的刷新,再进行流的关闭。

  1. public class FileWriterDemo {
  2. public static void main(String[] args) throws IOException {
  3. //演示FileWriter 用于操作文件的便捷类。
  4. FileWriter fw = new FileWriter("d:\\text\\fw.txt");
  5. fw.write("你好谢谢再见");//这些文字都要先编码。都写入到了流的缓冲区中。
  6. fw.flush();
  7. fw.close();
  8. }
  9. }

2.5 flush()和close()的区别?

flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用。

close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据,然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以不刷新,由close完成刷新并关闭。

2.6 字符流练习

2.6.1 复制文本文件

练习:复制文本文件。

思路:

1,既然是文本涉及编码表。需要用字符流。

2,操作的是文件。涉及硬盘。

3,有指定码表吗?没有,默认就行。

操作的是文件,使用的 默认码表。使用哪个字符流对象。直接使用字符流操作文件的便捷类。FileReader  FileWriter

  1. public class CopyTextFileTest {
  2. public static void main(String[] args) throws IOException {
  3. copyTextFile();
  4. }
  5. public static void copyTextFile() throws IOException {
  6. //1,明确源和目的。
  7. FileReader fr = new FileReader("c:\\cn.txt");
  8. FileWriter fw = new FileWriter("c:\\copy.txt");
  9. //2,为了提高效率。自定义缓冲区数组。字符数组。
  10. char[] buf = new char[1024];
  11. int len = 0;
  12. while((len=fr.read(buf))!=-1){
  13. fw.write(buf,0,len);
  14. }
  15. /*2,循环读写操作。效率低。
  16. int ch = 0;
  17. while((ch=fr.read())!=-1){
  18. fw.write(ch);
  19. }
  20. */
  21. //3,关闭资源。
  22. fw.close();
  23. fr.close();
  24. }
  25. }

java基础(23):字节流、字符流的更多相关文章

  1. -1-4 java io java流 常用流 分类 File类 文件 字节流 字符流 缓冲流 内存操作流 合并序列流

      File类 •文件和目录路径名的抽象表示形式 构造方法 •public File(String pathname) •public File(String parent,Stringchild) ...

  2. Java IO---字节流和字符流

    一.IO流简介 流 流是一个抽象概念,Java程序和外部设备(可以是硬盘上的文件,也可以是网络设备)之间的输入输出操作是基于流的. 流就好比水管中的水流,具有流入和流出,类比数据的输入和输出. Jav ...

  3. Java基础教程——字节流

    IO流 水流 特点 连续性 逝者如斯夫,不舍昼夜: 方向性 一江春水向东流.水往低处流.百川东到海,何时复西归?少壮不努力,老大徒伤悲! 源头尽头 唯有源头活水来:覆水难收 Java里的IO也有这样的 ...

  4. IO流(字节流,字符流,缓冲流)

    一:IO流的分类(组织架构) 根据处理数据类型的不同分为:字节流和字符流 根据数据流向不同分为:输入流和输出流   这么庞大的体系里面,常用的就那么几个,我们把它们抽取出来,如下图:   二:字符字节 ...

  5. Java基础-二进制以及字符编码简介

    Java基础-二进制以及字符编码简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 想必计算机毕业的小伙伴或是从事IT的技术人员都知道数据存储都是以二进制的数字存储到硬盘的.从事开 ...

  6. Java基础---IO(一)---IO流概述、字符流、字节流、流操作规律

    第一讲     IO概述 概述 1.IO流:即InputOutput的缩写. 2.特点: 1)IO流用来处理设备间的数据传输. 2)Java对数据的操作是通过流的方式. 3)Java用于操作流的对象都 ...

  7. JAVA基础之字节流与字符流

    个人理解: IO流就是将数据进行操作的方式,因为编码的不同,所以对文件的操作就产生两种.最好用字节流,为了方便看汉字等,(已经确定文字的话)可以使用字符流.每个流派也就分为输入和输出,这样就可以产生复 ...

  8. Java之IO流(字节流,字符流)

    IO流和Properties IO流 IO流是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口.它对于任何计算机系统都非常关键, 因而所有 I/O 的主体实际上是内置在操作系统中的.单独的 ...

  9. java基础11(IO流)-字符流

    转换流 由于字节流操作中文不是特别方便,所以java中提供了转换流 编码表:由现实世界的字符和对应的数值组成的一张表 编码:把看得懂的变成看不懂的(String-------byte[]) 解码:把看 ...

随机推荐

  1. IT兄弟连 HTML5教程 CSS3揭秘 CSS3属性3

    5 用户界面属性 在CSS3中,新的用户界面特性包括重设元素尺寸.盒尺寸及轮廓等.本小节着重介绍一下resize属性,只有Firefox 4和Safari 3浏览器支持此属性.resize属性可用于重 ...

  2. numpy-np.ceil,np.floor,np.expand_dims方法

    np.ceil(多维数组):对多维数组的各个数向上取整 np.floor(多维数组):对多维数组的各个数向下取整 np.expand_dims(x,axis = 0):在x的第一维度上插入一个维度,a ...

  3. ETCD:gRPC代理

    原文地址:gRPC proxy gRPC代理是在gRPC层(L7)运行的无状态etcd反向代理.代理旨在减少核心etcd群集上的总处理负载.对于水平可伸缩性,它合并了监视和租约API请求. 为了保护集 ...

  4. 双链表算法原理【Java实现】(八)

    前言 前面两节内容我们详细介绍了ArrayList,一是手写实现ArrayList数据结构,而是通过分析ArrayList源码看看内置实现,关于集合内容一如既往,本节课我们继续学习集合LinkedLi ...

  5. SpringBoot 整合Shiro实现动态权限加载更新+Session共享+单点登录

    作者:Sans_ juejin.im/post/5d087d605188256de9779e64 一.说明 Shiro是一个安全框架,项目中主要用它做认证,授权,加密,以及用户的会话管理,虽然Shir ...

  6. Slickflow.NET 开源工作流引擎快速入门之一: 简单序列流程代码编写示例

    前言:对于急切想了解引擎功能的开发人员,在下载版本后,就想尝试编写代码,完成一个流程的开发和测试.本文试图从一个最简单的流程来示例说明,如何快速了解引擎代码的编写. 版本: .NETCore 2.1 ...

  7. Web前端基础(17):jQuery基础(四)

    1. jQuery的属性操作 jquery的属性操作模块分为四个部分:html属性操作,dom属性操作,类样式操作和值操作 html属性操作:是对html文档中的属性进行读取,设置和移除操作.比如at ...

  8. 网络协议 2 - IP 地址和 MAC 地址

    了解完网络协议,我们会发现,网络通信的五层模型里,有两个很重要的概念:IP 地址和 MAC 地址. 那么 IP 地址是怎么来的,又是怎么没的?MAC 地址与 IP 地址又有什么区别? 这回答上面问题前 ...

  9. RabbitMQ的第一次亲密接触

    企业应用系统,如果系统之间的通信.集成与整合,尤其当面临异构系统时,那么需要分布式的调用与通信.系统中一般会有很多对实时性要求不高但零零碎碎且耗时的地方,比如发送短信,邮件提醒,记录用户操作日志等,在 ...

  10. 【JS基础语法】---学习roadmap---6 parts

    JS基础语法---roadmap Part 1 - 2: Part 3 - 4:   Part 5 - 6