JavaIO操作(1)字节流和字符流-1
3.2、字节流和字符流(核心)
使用File类执行的所有操作都是针对于文件本身,但是却没有针对于文件的内容,而要进行文件内容操作就需要通过Java之中提供的两组类完成:
· 字节操作流(是在JDK 1.0的时候定义的):OutputStream、InputStream;
· 字符操作流(是在JDK 1.1的时候定义的):Writer、Reader。
但是不管是字节流还是字符流的操作,本身都表示资源操作,而执行所有的资源操作都会按照如下的几个步骤进行,下面以文件操作为例(对文件进行读、写操作):
· 如果要操作的是文件,那么首先要通过File类对象找到一个要操作的文件路径(路径有可能存在,有可能不存在,如果不存在,则要创建路径);
· 通过字节流或字符流的子类为字节流或字符流的对象实例化(向上转型);
· 执行读 / 写操作;
· 最后一定要关闭操作的资源(close()),不管日后如何操作,资源永远要关闭。
3.2.1、字节输出流:OutputStream
java.io.OutputStream主要的功能是进行字节数据的输出的,而这个类的定义如下:
public abstract class OutputStream extends Object implements Closeable, Flushable |
发现OutputStream类定义的时候实现了两个接口:Closeable、Flushable,那么这两个接口的定义如下:
Closeable:JDK 1.5推出 |
Flushable:JDK 1.5推出 |
public interface Closeable extends AutoCloseable { public void close() throws IOException; } |
public interface Flushable { public void flush() throws IOException; } |
提示:对于Closeable继承的AutoCloseable接口
AutoCloseable是在JDK 1.7的时候又增加了一个新的接口,但是这个接口的定义和Closeable定义是完全一样的,我个人认为:有可能在一些其他的类上出现了自动的关闭功能,Closeable是手工关闭,AutoCloseable属于自动关闭。
但是对于Closeable和Flushable这两个接口实话而言用户不需要关注,因为从最早的习惯对于flush()和close()两个方法都是直接在OutputStream类之中定义的,所以很少去关心这些父接口问题。
对于OutputStream类而言发现其本身定义的是一个抽象类(abstract class),按照抽象类的使用原则来讲,需要定义抽象类的子类,而现在如果要执行的是文件操作,则可以使用FileOutputStream子类完成,如果按照面向对象的开发原则,子类要为抽象类进行对象的实例化,而后调用的方法以父类中定义的方法为主,而具体的实现找实例化这个父类的子类完成,也就是说在整个的操作之中,用户最关心的只有子类的构造方法:
· 实例化FileOutputStream(新建数据):public FileOutputStream(File file) throws FileNotFoundException;
· 实例化FileOutputStream(追加数据):public FileOutputStream(File file, boolean append)
throws FileNotFoundException
当取得了OutputStream类的实例化对象之后,下面肯定要进行输出操作,在OutputStream类之中定义了三个方法:
· 输出单个字节数据:public abstract void write(int b) throws IOException;
· 输出一组字节数据:public void write(byte[] b) throws IOException;
· 输出部分字节数据:public void write(byte[] b, int off, int len) throws IOException;
范例:使用OutputStream向文件之中输出数据,输出路径:d:\hellodemo\test.txt
package cn.mldn.demo; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class TestDemo { public static void main(String[] args) throws Exception { File file = new File("D:" + File.separator + "hellodemo" + File.separator + "test.txt"); // 第1步:定义文件路径 if (!file.getParentFile().exists()) { // 父路径不存在 file.getParentFile().mkdirs(); // 创建父路径 } OutputStream output = new FileOutputStream(file); // 第2步:通过子类实例化父类 String data = "Hello World .";// 要输出的数据 output.write(data.getBytes()); // 第3步:输出数据,要将数据变为字节数组输出 output.close(); // 第4步:关闭资源 } } |
在整个的文件输出过程之中可以发现,如果现在要输出的文件不存在,那么会出现自动创建文件的情况,并且如果重复执行以上的代码,会出现新的内容覆盖掉旧内容的操作,所以下面可以使用FileOutputStream类的另外一个构造方法进行数据的追加:
package cn.mldn.demo; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class TestDemo { public static void main(String[] args) throws Exception { File file = new File("D:" + File.separator + "hellodemo" + File.separator + "test.txt"); // 第1步:定义文件路径 if (!file.getParentFile().exists()) { // 父路径不存在 file.getParentFile().mkdirs(); // 创建父路径 } OutputStream output = new FileOutputStream(file, true);// 第2步:通过子类实例化父类 String data = "Hello World .\r\n";// 要输出的数据 output.write(data.getBytes()); // 第3步:输出数据,要将数据变为字节数组输出 output.close(); // 第4步:关闭资源 } } |
如果说现在不想全部内容输出,也可以使用另外一个write()方法部分内容输出。
package cn.mldn.demo; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class TestDemo { public static void main(String[] args) throws Exception { File file = new File("D:" + File.separator + "hellodemo" + File.separator + "test.txt"); // 第1步:定义文件路径 if (!file.getParentFile().exists()) { // 父路径不存在 file.getParentFile().mkdirs(); // 创建父路径 } OutputStream output = new FileOutputStream(file); // 第2步:通过子类实例化父类 String data = "Hello World .\r\n";// 要输出的数据 output.write(data.getBytes(), 0, 5); // 第3步:输出数据,要将数据变为字节数组输出 output.close(); // 第4步:关闭资源 } } |
在OutputStream类之中所有的数据都是以字节数据为主的。