在java.io包里面File类是惟一 一个与文件自己有关的程序处理类,可是File只可以操做文件自己而不可以操做文件的内容,或者说在实际的开发之中IO操做的核心意义在于:输入与输出操做。而对于程序而言,输入与输出可能来自于不一样的环境,例如:经过电脑链接服务器上进行浏览的时候,实际上此时客户端发出了一个信息,然后服务器接收到此信息以后进行回应处理。html
对于服务器或者是客户端而言实际上传递的就是一种数据流的处理形式,而所谓的数据流指的就是字节数据。而对于这种流的处理形式在java.io包里面提供有两类支持:java
·字节处理流:OutputStream(输出字节流)、InputStream(输入字节流);数组
·字符处理流:Writer(输出字符流)、Reader(输入字符流);服务器
全部的流操做都应该采用以下统一的步骤进行,下面以文件处理的流程为例:app
·若是如今要进行的是文件的读写操做,则必定要经过File类找到一个文件路径;ide
·经过字节流或字符流的子类为父类对象实例化;spa
·利用字节流或字符流中的方法实现数据的输入与输出操做;code
·流的操做属于资源操做,资源操做必须进行关闭处理;htm
字节的数据是以byte类型为主实现的操做,在进行字节内容输出的时候可使用OutputStream类完成,这个类的基本定义以下:对象
public abstract class OutputStream extends Object implements Closeable, Flushable
首先能够发现这个类实现了两个接口,因而基本的对应关系以下:
Closeable: |
Flushable: |
public interface Closeable extends AutoCloseable {public void close() throws Exception;} |
public interface Flushable{public void flush() throws IOException;} |
OutputStream类定义的是一个公共的输出操做标准,而在这个操做标准里面一共定义有三个内容输出的方法。
No |
方法名称 |
类型 |
描述 |
01 |
public abstract void write(int b) throws IOException |
普通 |
输出单个字节数据 |
02 |
public void write(byte[] b) throws IOException |
普通 |
输出一组字节数据 |
03 |
public void write(byte[] b,int off,int len) throws IOException |
普通 |
输出部分字节数据 |
可是须要注意的一个核心问题在于:OutputStream类毕竟是一个抽象类,而这个抽象类若是要想得到实例化对象,按照传统的认识应该经过子类实例的向上转完成,若是说如今要进行的是文件处理操做,则可使用FileOutputStream子类:
由于最终都须要发生向上转型的处理关系,因此对于此时的FileOutputStream子类核心的关注点就能够放在构造方法:
·【覆盖】构造方法:public FileOutputStream(File file) throws FileNotFoundException;
·【追加】构造方法:public FileOutputStream(File file,boolean append) throws FileNotFoundException;
范例:使用OutputStream类实现内容的输出
1 import java.io.File; 2 import java.io.FileOutputStream; 3 import java.io.OutputStream; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + 7 File.separator + "mldn.txt"); // 一、指定要操做的文件的路径 8 if (!file.getParentFile().exists()) { // 文件不存在 9 file.getParentFile().mkdirs() ; // 建立父目录 10 } 11 OutputStream output = new FileOutputStream(file) ; // 二、经过子类实例化 12 String str = "www.mldn.cn" ; // 要输出的文件内容 13 output.write(str.getBytes()); // 三、将字符串变为字节数组并输出 14 output.close(); // 四、关闭资源 15 } 16 }
本程序是采用了最为标准的形式实现了输出的操做处理,而且在总体的处理之中,只是建立了文件的父目录,可是并无建立文件,而在执行后会发现文件能够自动帮助用户建立。另外须要提醒的是,因为OutputStream子类也属于AutoCloseable接口子类,因此对于close()方法也能够简化使用。
范例:自动关闭处理
1 import java.io.File; 2 import java.io.FileOutputStream; 3 import java.io.IOException; 4 import java.io.OutputStream; 5 public class JavaAPIDemo { 6 public static void main(String[] args) throws Exception { 7 File file = new File("D:" + File.separator + "hello" + File.separator + "pluto.txt"); // 一、指定要操做的文件的路径 8 if (!file.getParentFile().exists()) { // 文件不存在 9 file.getParentFile().mkdirs(); // 建立父目录 10 } 11 try (OutputStream output = new FileOutputStream(file, true)) {//true表示追加数据 12 String str = "www.cnblogs.com\r\n"; // 要输出的文件内容 13 output.write(str.getBytes()); // 三、将字符串变为字节数组并输出 14 } catch (IOException e) { 15 e.printStackTrace(); 16 } 17 } 18 }
是否使用自动的关闭取决于项目的总体结构,另外还须要提醒的是,整个的程序里面最终是输出了一组的字节数据,可是千万不要忘记了,OutputStream类之中定义的输出方法一共有三个。
与OutputStream类对应的一个流就是字节输入流,InputStream类主要实现的就是字节数据读取,该类定义以下:
public abstract class InputStream extends Object implements Closeable
在InputStream类里面定义有以下的几个核心方法:
No |
方法名称 |
类型 |
描述 |
01 |
public abstract int read() throws IOException |
普通 |
读取单个字节数据,若是如今已经读取到底,则返回-1 |
02 |
public int read(byte[] b) throws IOException |
普通 |
读取一组字节数据,返回的是读取的个数,若是没有数据已经读取到底则返回-1 |
03 |
public int read(byte[] b,int off,int len) throws IOException |
普通 |
读取一组字节数据(只占数组的部分) |
InputStream类属于一个抽象类,这时应该依靠它的子类来实例化对象,若是要从文件读取必定使用FileInputStream子类,对于子类而言只关心父类对象实例化。
构造方法:public FileInputStream(File file) throws FileNotFoundException;
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.InputStream; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 InputStream input = new FileInputStream(file) ; 8 byte data [] = new byte [1024] ; // 开辟一个缓冲区读取数据 9 int len = input.read(data) ; // 读取数据,数据所有保存在字节数组之中,返回读取个数,若是mldn.txt文件中的长度大于1024则只会读取到1024字节长度的信息 10 System.out.println("【" + new String(data, 0, len) + "】"); 11 input.close(); 12 } 13 }
对于字节输入流里面最为麻烦的问题就在于:使用read()方法读取的时候只可以以字节数组为主进行接收。
特别须要注意的是从JDK1.9开始在InputStream类里面增长了一个新的方法:public byte[] readAllBytes() throws IOException;
1 import java.io.File; 2 import java.io.FileInputStream; 3 import java.io.InputStream; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 InputStream input = new FileInputStream(file) ; 8 byte data [] = input.readAllBytes() ; // 读取所有数据 9 System.out.println("【" + new String(data) + "】"); 10 input.close(); 11 } 12 }
若是如今要读取的内容很大很大的时候,那么这种读取直接使程序崩溃。若是要使用尽可能不要超过10KB。
使用OutputStream字节输出流进行数据输出的时候使用的都是字节类型的数据,而不少的状况下字符串的输出是比较方便的,因此对于java.io包而言,在JDK1.1的时候又推出了字符输出流:Writer,这个类的定义以下:
public abstract class Writer extends Object implements Appendable, Closeable, Flushable
在Writer类里面提供有许多的输出操做方法,重点来看两个:
·输出字符数组:public void write(char[] cbuf) throws IOException;
·输出字符串:public void write(String str) throws IOException;
范例:使用Writer输出
1 import java.io.File; 2 import java.io.FileWriter; 3 import java.io.Writer; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 if (!file.getParentFile().exists()) { 8 file.getParentFile().mkdirs(); // 父目录必须存在 9 } 10 Writer out = new FileWriter(file) ; 11 String str = "www.mldn.cn" ; 12 out.write(str); 13 out.close(); 14 } 15 }
使用Writer输出的最大优点在于能够直接利用字符串完成。Writer是字符流,字符处理的优点在于中文数据上。
Reader是实现字符输入流的一种类型,其自己属于一个抽象类,这个类的定义以下:
public abstract class Reader extends Object implements Readable, Closeable
Reader类里面并无像Writer类同样提供有整个字符串的输入处理操做,只可以利用字符数据来实现接收:
·接收数据:public int read(char[] cbuf) throws IOException;
范例:实现数据读取
1 import java.io.File; 2 import java.io.FileReader; 3 import java.io.Reader; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 if (file.exists()) { // 文件存在则进行读取 8 Reader in = new FileReader(file) ; 9 char data[] = new char[1024]; 10 int len = in.read(data) ; 11 System.out.println("读取内容:" + new String(data,0,len)); 12 in.close(); 13 } 14 } 15 }
字符流读取的时候只可以按照数组的形式来实现处理操做。
如今经过一系列的分析已经能够清楚字节流与字符流的基本操做了,可是对于这两类流依然是存在有区别的,重点来分析一下输出的处理操做。在使用OutputStream和Writer输出的最后发现都使用了close()方法进行了关闭处理。
在使用OutputStream类输出的时候若是没有使用close()方法关闭输出流发现内容依然能够实现正常的输出,可是若是在使用Writer的时候没有使用close()方法关闭输出流,那么这个时候内容将没法进行输出,由于Writer使用到了缓冲区,当使用了close()方法的时候实际上会出现有强制刷新缓冲区的状况,因此这个时候会将内容进行输出,若是没有关闭,那么将没法进行输出操做,因此此时若是在不关闭的状况下要想将所有的内容输出可使用flush()方法强制清空。
范例:使用Writer并强制性清空
1 import java.io.File; 2 import java.io.FileWriter; 3 import java.io.Writer; 4 public class JavaAPIDemo { 5 public static void main(String[] args) throws Exception { 6 File file = new File("D:" + File.separator + "hello" + File.separator + "mldn.txt"); 7 if (!file.getParentFile().exists()) { 8 file.getParentFile().mkdirs(); // 父目录必须存在 9 } 10 Writer out = new FileWriter(file) ; 11 String str = "www.mldn.cn" ; 12 out.write(str); 13 out.flush(); // 强制性刷新 14 } 15 }
问题:能够修改代码使out.flush()存在和不存在的区别?查看这二者有什么区别?
注意:以上例子中的out流不能够关闭,不然会自动flush()便达不到咱们想要的结果
字节流在进行处理的时候并不会使用到缓冲区,而字符流会使用到缓冲区。另外使用缓冲区的字符流更加适合于进行中文数据的处理,因此在往后的程序开发之中,若是要涉及到包含有中文信息的输出通常都会使用字符流处理,可是从另一方面来说,字节流和字符流的基本处理形式是类似的,因为IO不少状况下都是进行数据的传输使用(二进制)因此本次的讲解将以字节流为主。
原文出处:https://www.cnblogs.com/CSAH/p/11774782.html