Day27-Java之字节输出流:OutputStream
关于作者
• 作者介绍
🍓 博客主页:作者主页 🍓 简介:JAVA领域优质创作者🥇、一名在校大三学生🎓、在校期间参加各种省赛、国赛,斩获一系列荣誉🏆。 🍓 关注我:关注我学习资料、文档下载统统都有,每日定时更新文章,励志做一名JAVA资深程序猿👨💻。
IO— 字节流与字符流
字符流和字节流最本质的区别就是只有一个字节流是原生的操作,二字符流是经过处理后的操作。经过磁盘数据保存所保存的支持的数据类型只有:字节,所有磁盘中的数据必须先读到内存后才可以操作,内存里面会帮助我们把字节变为字符。字符更加适合处理中文。
**字节操作流:**OutputStream,InputStream;
**字符操作流:**Writer,Reader。
但是不管是字节流还是字符流的操作,本身都表示资源操作,而执行所有的资源都会按照如下几个步骤进行,下面以文件操作为例(对文件进行读,写操作):
- 要根据文件创建File对象
- 根据字节流或字符流的子类实例化我们的父类对象
- 进行数据的读取、写入操作
- 关闭流(clone())
对于IO操作属于资源处理,所有的对于资源的处理进行处理完成后必须进行关闭,否则资源就再也无法执行。
字节输出流:OutputStream
Java.io.OutputStream主要的功能是进行字节数据的输出的,而这个类的定义如下:
public abstract class OutputStream extends Object
implements Closeable, Flushable
发现OutputStream类定义的时候实现了两个接口:Closeable,Flushable,这两个接口定义如下:
Closeable: | Flushable: |
---|---|
public interface Closeable<br />extends AutoCloseable{<br /> public void close() throws IOException; <br />} | public interface Closeable{<br /> public void flush() throws IOException; <br /> } |
当取得了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
提示:对于Closeable继承的AutoCloseable接口
AuotCloseable实在JDK1.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
实现文件内容的输出
package com.day14.demo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class OutputDemo {
public static void main(String[] args) throws Exception {
//1.定义文件路径
File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
if(!file.getParentFile().exists()){//父路径不存在
file.getParentFile().mkdirs();//创建父目录
}
//2.要输出的数据
String str = "Hello,zsr!!!!";
//3.实例化对象
FileOutputStream stream = new FileOutputStream(file);
//4.将内容写进stream
stream.write(str.getBytes());//输出数据,要将输出的数据变为字节数组输出
//5.关闭流
stream.close();
}
}
这里默认执行时进行文档内容的覆写,如果不希望进行文档内容的覆写可以直接将FileOutputStream改为
FileOutputStream stream = new FileOutputStream(file,true);
如果对写入的内容需要换行操作必须使用\r\n进行换行操作。
字节输入流:InputStream
如果现在要从指定的数据源之中读取数据,使用InputStream,而这个类的定义如下:
public abstract class InputStreamextends Objectimplements Closeable
发现InputStream只实现了Closeable接口
在InputStream之中定义了三个读取数据的方法:
**读取单个字节:**public abstract int read() throws IOException
**说明:**每次执行read()方法都会读取一个数据源的指定数据,如果现在发现已经读取到了结尾则返回-1.
**读取多个字节:**public int read(byte[] b) throws IOException
**说明:**如果现在要读取的数据小于开辟的字节数组,这个时候read()方法的返回值int返回的是数据个数;如果现在开辟的字节数组小于读取的长度,则这个时候返回就是长度;如果数据已经读完了,则这个时候的int返回的是-1.
**读取指定多个字节:**public int read(byte[] b,int off,int len) throws IOException
**说明:**每次只读取传递数组的部分内容,如果读取满了,返回就是长度;如果没有读取满,返回的就是读取的个数;如果读取到最后没有数据了,就返回-1
既然InputStream为抽象类,那么这个抽象类要使用就必须有子类,现在是通过文件读取内容,肯定使用FileInputStream子类进行操作,与OutputStream类的使用一样,对于FileInputStream也只关心构造方法:
**FileInputStream****类构造方法:public FileInputStream(File file) throws FileNotFoundException
文件信息的读取
package com.day14.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class InputDemo {
public static void main(String[] args) throws Exception {
File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
if(!file.exists()){
System.out.println("指定文件不存在!!");
}else{
FileInputStream is = new FileInputStream(file);
byte[] result = new byte[1024];
int length = is.read(result);
System.out.println("读取的内容为:" + new String(result,0,length));
}
}
}
字符输出流:Writer
Writer类也是一个专门用来数据输出的操作类,对于中文数据来说是比较友好的,这个类定义:
public abstract class Writer
extends Object
implements Appendable, Closeable, Flushable
在Writer类之中定义的writer()方法都是以字符数据为主,但是在这些方法之中,只关心一个:
**输出一个字符串:**public void write(String str) throws IOException
如果要操作文件肯定使用FileWriter子类。
package com.day14.demo;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class WriterDemo {
public static void main(String[] args) throws IOException {
//1.定义文件路径
File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
if(!file.getParentFile().exists()){//父路径不存在
file.getParentFile().mkdirs();//创建父目录
}
//2.要输出的数据
String str = "我正在学java这门课程!!!!\r\n";
//如果想要进行内容不覆盖的直接使用true就可以了
//FileWriter out = new FileWriter(file,true);
FileWriter out = new FileWriter(file);
out.write(str);
out.close();
}
}
字符输入流:Reader
Reader是进行字符数据读取的一个操作类,其定义:
public abstract class Reader
extends Object
implements Readable, Closeable
在Writer类之中存在了直接输出一个字符串数据的方法,可是在Reader类之中并没有定义这样的方法,只是定义了三个按照字符串读取的方法?为什么会这样?
因为在使用OutputStream输出数据的时候,其程序可以输出的大小一定是程序可以承受的数据的大小,那么如果说使用InputStream读取的时候,可能被读取的数据非常大,那么如果一次性全读进来,就会出现问题,所以只能一个一个的进行读取。
Reader依然是抽象类,那么如果从文件读取,依然使用FileReader类
package com.day14.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class ReadDemo {
public static void main(String[] args) throws IOException {
File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
if(!file.exists()){
System.out.println("指定文件不存在!!");
}else{
FileReader reader = new FileReader(file);
char[] result = new char[1024];
int length = reader.read(result);
System.out.println("读取的内容为:" + new String(result,0,length));
}
}
}
字符比字节的好处就是在于字符串数据的支持上,而这个好处还只是在Writer()类中体现,所以与字节流相比,字符流的操作并不是对等的关系。
字节流与字符流区别
通过我们一系统的分析,可以发现字节流和字符流的代码操作区别不大,如果从我们实际的使用,我们字节流是优先考虑,只有再我们使用中文的时候才考虑使用字符流,因为所有的字符都需要通过内存缓冲来进行处理。
既然读数据需要缓存的处理,那么写数据也同样需要。如果使用字符流没有进行刷新,那么我们的内容可能再缓存之中,所以必须进行强制刷新才能得到完整的数据内容。
package com.day14.demo;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class WriterDemo {
public static void main(String[] args) throws IOException {
//1.定义文件路径
File file = new File("f:" + File.separator + "test" + File.separator + "hello.txt");
if(!file.getParentFile().exists()){//父路径不存在
file.getParentFile().mkdirs();//创建父目录
}
//2.要输出的数据
String str = "我正在学java这门课程!!!!\r\n";
//如果想要进行内容不覆盖的直接使用true就可以了
//FileWriter out = new FileWriter(file,true);
FileWriter out = new FileWriter(file);
out.write(str);
out.flush();
}
}
在以后的IO处理的时候,如果处理的是图片、音乐、文字都可以使用字节流,只有再处理中文的时候才会使用字符流。