Java IO流在实际业务中使用的频率还是蛮高的,一些业务场景比如,文件的上传和导出,文件的读取等基本都是通过操作IO流来实现的,所以IO流是我们现在学习过程中必须要掌握的技能之一,熟练的使用IO流,理解它的操作过程,能够让我们在今后的开发过程中达到事半功倍的效果。话不多说,首先,让我们来看看Java IO流的组织架构图:

所以,我们可以清晰的发现IO流中主要分为了两类,一类是字节流一类是字符流,要知道两者的区别,我们还需要理解一个概念,

流:

在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。

程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。

字节流与字符流的区别:

相同点:两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。(这四个都是抽象类)

不同点:

1.InputStream 和OutputStream,两个是为字节流设计的,主要用来处理字节或二进制对象,
     Reader和 Writer.两个是为字符流(一个字符占两个字节)设计的,主要用来处理字符或字符串.

2.字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!

3.处理文件类型方面:如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点

所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列。

字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串; 字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以,字节流是最基本的,所有的InputStrem和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的 但实际中很多的数据是文本,又提出了字符流的概念,它是按虚拟机的encode来处理,也就是要进行字符集的转化 这两个之间通过 InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String来关联 在实际开发中出现的汉字问题实际上都是在字符流和字节流之间转化不统一而造成的 。

4.Reader类的read()方法返回类型为int :作为整数读取的字符(占两个字节共16位),范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1

inputStream的read()虽然也返回int,但由于此类是面向字节流的,一个字节占8个位,所以返回 0 到 255 范围内的 int 字节值。如果因为已经到达流末尾而没有可用的字节,则返回值 -1。因此对于不能用0-255来表示的值就得用字符流来读取!比如说汉字.

Java中操作文件的基本流程:

1 使用File类打开一个文件

通过字节流或字符流的子类,指定输出的位置

3 进行读/写操作

4 关闭输入/输出

IO操作属于资源操作,一定要记得关闭!

实例说明:写数据

1 import java.io.File;
 2 import java.io.FileOutputStream;
 3 import java.io.IOException;
 4 import java.io.OutputStream;
 5
 6 public class Test11 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");//指定写入到哪个文件
 9         OutputStream out=new FileOutputStream(f);//如果文件不存在会自动创建
10         String str="Hello World";
11         byte[] b=str.getBytes();
12         out.write(b);//因为是字节流,所以要转化成字节数组进行输出
13         out.close();
14     }
15 }

也可以一个字节一个字节的写入:

1 import java.io.File;
 2 import java.io.FileOutputStream;
 3 import java.io.IOException;
 4 import java.io.OutputStream;
 5
 6 public class Test11 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         OutputStream out=new FileOutputStream(f);//如果文件不存在会自动创建
10         String str="Hello World";
11         byte[] b=str.getBytes();
12         for(int i=0;i<b.length;i++){
13             out.write(b[i]);
14         }
15         out.close();
16     }
17 }

注意:以上写入只会将源文件的内容进行覆盖,如果要进行源文件内容的追加,则需要看下面的:

public FileOutputStream(File file,boolean append)throws FileNotFoundException//构造方法

在构造方法中,如果将append的值设置为true,则表示在文件的末尾追加内容。

1 import java.io.File;
 2 import java.io.FileOutputStream;
 3 import java.io.IOException;
 4 import java.io.OutputStream;
 5
 6 public class Test11 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         OutputStream out=new FileOutputStream(f,true);//追加内容
10         String str="\r\nHello World";
11         byte[] b=str.getBytes();
12         for(int i=0;i<b.length;i++){
13             out.write(b[i]);
14         }
15         out.close();
16     }
17 }

文件中换行为:\r\n

实例说明:读数据

字节输入流:InputStream

既然程序可以向文件中写入内容,则就可以通过InputStream从文件中把内容读取进来,首先来看InputStream类的定义:

public abstract class InputStream extends Object implements Closeable

与OutputStream类一样,InputStream本身也是一个抽象类,必须依靠其子类,如果现在是从文件中读取,就用FileInputStream来实现。

观察FileInputStream类的构造方法:

public FileInputStream(File file)throws FileNotFoundException

读文件:

1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.IOException;
 4 import java.io.InputStream;
 6 public class Test12 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         InputStream in=new FileInputStream(f);
10         byte[] b=new byte[1024];
11         int len=in.read(b);
12         in.close();
13         System.out.println(new String(b,0,len));
14     }
15 }

但以上方法是有问题的,用不用开辟这么大的一个字节数组,明显是浪费嘛,我们可以根据文件的大小来定义字节数组的大小,File类中的方法:public long length()

1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5
 6 public class Test13 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         InputStream in=new FileInputStream(f);
10         byte[] b=new byte[(int) f.length()];
11         in.read(b);
12         in.close();
13         System.out.println(new String(b));
14     }
15 }

我们换种方式,一个字节一个字节读入~

1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5
 6 public class Test14 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         InputStream in=new FileInputStream(f);
10         byte[] b=new byte[(int) f.length()];
11         for(int i=0;i<b.length;i++){
12             b[i]=(byte) in.read();
13         }
14         in.close();
15         System.out.println(new String(b));
16     }
17 }

但以上情况只适合知道输入文件的大小,不知道的话用如下方法:

1 import java.io.File;
 2 import java.io.FileInputStream;
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5
 6 public class Test15 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         InputStream in=new FileInputStream(f);
10         byte[] b=new byte[1024];
11         int temp=0;
12         int len=0;
13         while((temp=in.read())!=-1){//-1为文件读完的标志
14             b[len]=(byte) temp;
15             len++;
16         }
17         in.close();
18         System.out.println(new String(b,0,len));
19     }
20 }

字符流

在程序中一个字符等于两个字节,那么java提供了Reader、Writer两个专门操作字符流的类。

字符输出流:Writer

Writer本身是一个字符流的输出类,此类的定义如下:

public abstract class Writer extends Object implements Appendable,Closeable,Flushable

此类本身也是一个抽象类,如果要使用此类,则肯定要使用其子类,此时如果是向文件中写入内容,所以应该使用FileWriter的子类。

FileWriter类的构造方法定义如下:

public FileWriter(File file)throws IOException

字符流的操作比字节流操作好在一点,就是可以直接输出字符串了,不用再像之前那样进行转换操作了。

写文件:

1 import java.io.File;
 2 import java.io.FileWriter;
 3 import java.io.IOException;
 4 import java.io.Writer;
 5
 6 public class Test16 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         Writer out=new FileWriter(f);
10         String str="Hello World";
11         out.write(str);
12         out.close();
13     }
14 }

在默认情况下再次输出会覆盖,追加的方法也是在构造函数上加上追加标记

1 import java.io.File;
 2 import java.io.FileWriter;
 3 import java.io.IOException;
 4 import java.io.Writer;
 5
 6 public class Test17 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         Writer out=new FileWriter(f,true);//追加
10         String str="\r\nHello World";
11         out.write(str);
12         out.close();
13     }
14 }

字符输入流:Reader

Reader是使用字符的方式从文件中取出数据,Reader类的定义如下:

public abstract class Reader extends Objects implements Readable,Closeable

Reader本身也是抽象类,如果现在要从文件中读取内容,则可以直接使用FileReader子类。

FileReader的构造方法定义如下:

public FileReader(File file)throws FileNotFoundException

以字符数组的形式读取出数据:

1 import java.io.File;
 2 import java.io.FileReader;
 3 import java.io.IOException;
 4 import java.io.Reader;
 5
 6 public class Test18 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         Reader input=new FileReader(f);
10         char[] c=new char[1024];
11         int len=input.read(c);
12         input.close();
13         System.out.println(new String(c,0,len));
14     }
15 }

也可以用循环方式,判断是否读到底:

1 import java.io.File;
 2 import java.io.FileReader;
 3 import java.io.IOException;
 4 import java.io.Reader;
 5
 6 public class Test19 {
 7     public static void main(String[] args) throws IOException {
 8         File f = new File("d:" + File.separator+"test.txt");
 9         Reader input=new FileReader(f);
10         char[] c=new char[1024];
11         int temp=0;
12         int len=0;
13         while((temp=input.read())!=-1){
14             c[len]=(char) temp;
15             len++;
16         }
17         input.close();
18         System.out.println(new String(c,0,len));
19     }
20 }

字节流和字符流使用是非常相似的,那么除了操作代码的不同之外,还有哪些不同呢?

字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的

字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在不close的情况下输出内容

那开发中究竟用字节流好还是用字符流好呢?

在所有的硬盘上保存文件或进行传输的时候都是以字节的方法进行的,包括图片也是按字节完成,而字符是只有在内存中才会形成的,所以使用字节的操作是最多的。

如果要java程序实现一个拷贝功能,应该选用字节流进行操作(可能拷贝的是图片),并且采用边读边写的方式(节省内存)。

以上就是此次关于JavaIO流的学习,如有不足,请指正

Java成长第四集--文本处理IO流的更多相关文章

  1. JAVA学习第四十八课 — IO流(二):文件的复制 &amp; 缓冲区1

    一.复制文本文件 将G盘的文本文件拷贝到D盘上 也就是 读取G盘中文本文件的数据.写入D盘中->连读带写 而剪切呢.就是连读带写后,删除原盘的文件 <span style="fo ...

  2. java基础第十五篇之IO流和递归算法

    FileInputStream : 输入流 int available() : 一次读取所有的字节数 read() : 将文件上的字节读取到内存的数组中 FileOutputStream : 输出流 ...

  3. Java开发笔记(九十一)IO流处理简单的数据压缩

    前面介绍的文件I/O,不管是写入文本还是写入对象,文件中的数据基本是原来的模样,用记事本之类的文本编辑软件都能浏览个大概.这么存储数据,要说方便确实方便,只是不够经济划算,原因有二:其一,写入的数据可 ...

  4. Java学习之路(十二):IO流<二>

    字符流 字符流是可以直接读写字符的IO流 使用字符流从文件中读取字符的时候,需要先读取到字节数据,让后在转换为字符 使用字符流向文件中写入字符时,需要把字符转为字节在写入文件 Reader和Write ...

  5. Java学习之路(十二):IO流

    IO流的概述及其分类 IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式 Java用于操作流的类都在IO包中 流按流向分为两种:输入流(读写数据)     输出流(写数据) 流按操作 ...

  6. java学习(九) —— java中的File文件操作及IO流概述

    前言 流是干什么的:为了永久性的保存数据. IO流用来处理设备之间的数据传输(上传和下载文件) java对数据的操作是通过流的方式. java用于操作流的对象都在IO包中. java IO系统的学习, ...

  7. 四种读写方案IO流 (JAVA)

    File类用于访问文件或目录的属性 流:指一连串流动的字符,是以先进先出的方式发送信息的通道.程序和数据源之间是通过流联系起来的. 第一套:字节流读取写入方案 FileInputStream :字节流 ...

  8. Java成长记录第二集--基础重点

    第一篇写的博客给自己的学习路线立了个flag后,感觉现在学习的积极性大增,这也离不开那几位老铁们的互相鼓励.废话不多说,现在给出自己总结的Java基础部分所要重点注意的内容,对以后的开发工作也是很常用 ...

  9. Java成长第五集--面向对象设计的五大原则

    S.O.L.I.D 是面向对象设计(OOD)和面向对象编程(OOP)中的几个重要编码原则(Programming Priciple)的首字母缩写.以下图说明: 下面就个人的理解来说说这五大原则的含义到 ...

随机推荐

  1. Swift 4.0 高级-自定义操作符

    在Swift语言中,常见的操作符有+.-.*./.>.<.==.&&.||等等,如果不喜欢,你也可以定义自己喜欢的操作符. 操作符类型 中置运算符(infix operat ...

  2. [Bugku]Web题解

    bugku地址链接:https://ctf.bugku.com 1.web2 浏览器就显示一堆动态笑脸,时间长了密集恐惧症了. 解法1: F12查看源码 解法2: 地址栏输入: view-source ...

  3. .NET的资源并不限于.resx文件

    为了构建一个轻量级的资源管理框架以满足简单的本地化(Localization)的需求,我试图直接对现有的Resource编程模型进行扩展.虽然最终没能满足我们的需求,但是这两天也算对.NET如何进行资 ...

  4. SSI服务器端包含注入

    服务器端嵌入:Server Side Include,是一种类似于ASP的基于服务器的网页制作技术.大多数(尤其是基于Unix平台)的WEB服务器如Netscape Enterprise Server ...

  5. (一)iview的校验TypeError: Cannot read property 'validateField' of undefined"

    一.问题描述 我是在自己封装了一个地址级联选择,然后想要每次改变了其中数据的时候,就进行一次单独校验,所以用到了iview对部分表单字段进行校验的方法validateField.其实一开始使用的时候是 ...

  6. 动态规划-LCS-Uncrossed Lines

    2020-02-11 21:14:18 问题描述: 问题求解: 本质就是LCS. public int maxUncrossedLines(int[] A, int[] B) { int len1 = ...

  7. [最短路,floyd] Codeforces 1204C Anna, Svyatoslav and Maps

    题目:http://codeforces.com/contest/1204/problem/C C. Anna, Svyatoslav and Maps time limit per test 2 s ...

  8. npm git 常用命令行 记录

    1. 推出node命令行: 两次ctrl+C或者一次ctrl+D    退出终端:exit; 2.npm 常用 npm install <name>  安装包 npm install &l ...

  9. Spark在Windows环境下的配置

    1.下载 下载地址:http://spark.apache.org/downloads.html. 选择下面版本下载. 2.操作流程:https://blog.csdn.net/nxw_tsp/art ...

  10. Django-rest-framework源码分析(三)

    APIView(二) 在APIView执行dispatch()方法的时候,它不仅做了分发函数的功能,还进行了一系列的校验. Django的全局校验一般写在中间件中,但是rest_framework于D ...