Java成长第四集--文本处理IO流

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流的学习,如有不足,请指正

原文地址:https://www.cnblogs.com/lmyou/p/9435740.html

时间: 2024-07-31 08:52:52

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

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

一.复制文本文件 将G盘的文本文件复制到D盘上 也就是 读取G盘中文本文件的数据,写入D盘中->连读带写 而剪切呢,就是连读带写后,删除原盘的文件 <span style="font-family:KaiTi_GB2312;font-size:18px;"><strong>import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public clas

JAVA学习第四十九课 — IO流(三):缓冲区2 &amp; 装饰设计模式

一.模拟BufferedReader 自定义MyBuffereaReader 对于缓冲区而言,里面其实就是封装一个数组,对外提供方法对数组的操作,这些方法最终操作的都是数组的角标 原理:从源中取出数据存入缓冲区,再从缓冲区不断的取出数据,取完后,继续从源中继续取数据,进缓冲区,直至源中的数据取完,用-1做为结束标记 import java.io.*; class MyBufferedReader { private FileReader fr; //定义数组作为缓冲区 private char[

JAVA基础语法练习(四)--File 及IO流

File: 文件和目录路径名的抽象表示形式. 构造方法 public File(String pathname) public File(String parent,String child) public File(File parent,String child) 创建功能 public boolean createNewFile() public boolean mkdir() public boolean mkdirs() 删除功能 public boolean delete() 重命名

JAVA学习第五十二课 — IO流(六)File对象

File类 用来给文件或者文件夹封装成对象 方便对文件与文件夹的属性信息进行操作 File对象可以作为参数传递给流的构造函数 一.构造函数和分隔符 public static void FileDemo() {//构造函数演示 //可以将一个已存在或不存在的文件或目录封装成File对象 File file = new File("d:\\a.txt"); File file2 = new File("d:","a.txt"); File file

JAVA学习第五十五课 — IO流(九)文件切割合成器

文件切割器 private static final int SIZE = 1024 *1024; public static void splitFile(File file) throws IOException{ //用读取流关联文件(不确定文件格式) FileInputStream fis = new FileInputStream(file);//源是一个 byte[] by = new byte[SIZE];//定义1M的缓冲区 FileOutputStream fos = null

JAVA学习第五十六课 — IO流(十)对象的序列化和反序列化 &amp; RandomAccessFile

操作对象 ObjectInputStream.ObjectOutputStream 被操作的对象需要实现Serializable(标记接口) ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream.可以使用 ObjectInputStream 读取(重构)对象.通过在流中使用文件可以实现对象的持久存储.如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象. 对象的默认序列化机制写入的内容是:对象的类,类签名,以及非瞬态和非静态字段的

Java中的IO流体系

Java为我们提供了多种多样的IO流,我们可以根据不同的功能及性能要求挑选合适的IO流,如图10-7所示,为Java中IO流类的体系. 注:这里只列出常用的类,详情可以参考JDK API文档.粗体标注为常用! 图10-7 Java中的IO流体系 从上图发现,很多流都是成对出现的,比如:FileInputStream/FileOutputStream,显然是对文件做输入和输出操作的.我们下面简单做个总结: 1. InputStream/OutputStream 字节流的抽象类. 2. Reader

文件和IO流

摘要:本文主要介绍了Java的文件处理以及常用的IO流操作. 文件操作 概念 File是数据源(保存数据的地方)的一种,可以表示一个文件,也可以表示一个文件目录. File类只能对文件和文件夹进行创建和删除等操作,可以查看文件和文件夹的属性,不能读取或修改内容.如果需要读取或修改文件的内容,需要使用IO流. 常常将File类的对象作为参数传递到IO流的类的构造器中. 绝对路径和相对路径 绝对路径:绝对路径名是完整的路径名,不需要任何其他信息就可以定位它所表示的文件或文件夹. 相对路径:相对路径名

腾讯首席架构师:Java程序员四个阶段成长路线,少走弯路

有这么一位Java大牛 他是前 Oracle 首席工程师,负责过北京Java核心类库.国际化.分发服务等技术团队的组建.大家都知道,Java 就是 Oracle 公司的,他对Java的理解会与众不同.他把Java程序员的成长路线划分为新手.高级新手.胜任者.精通者和专家,让大家少走弯路.创一个小群,供大家学习交流聊天如果有对学JAVA方面有什么疑惑问题的,或者有什么想说的想聊的大家可以一起交流学习一起进步呀.也希望大家对学JAVA能够持之以恒JAVA爱好群,如果你想要学好JAVA最好加入一个组织