一标题:字节输出流:OutputStream
知识点:
File类虽然可以操作文件,但是不支持操作文件内容,如果要对内容进行操作只有两种方式:字符流和字节流。
具体内容:
如果要进行输入,输出操作一般都会按照如下的步骤进行(以文件操作为例):
- 通过File类定义一个要操作文件的路径(不是文件就没有这一步);
- 通过字节流或则字符流的子类对象为父类对象实例化;
- 进行数据的读(写入),写(输出)操作;
- 数据流属于资源操作,资源操作必须关闭;
JAVA.IO包定义了两类流:
- 字节流(JDK1.0):InputStream、OutputStream;
- 字符流(JDK1.1):Reader、Writer;
字节输出流OutputStream:
OutputStream类是一个专门进行字节流数据输出的一个类,这个定义如下:
-
public abstract class OutputStream extends Object implements Closeable, Flushable
OutputStream类实现了两个接口:Closeable,Flushable
Closeable接口:(JDK1.5) | Flushable接口:(JDK1.5) |
|
|
|
OutputStream类在JDK1.0的时候提供,且这个类原本就定义了close()与flusah()方法,故以上两个接口就可以忽略不记了。
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子类,FileOutputStream类:
public FileOutputStream(String name, boolean append) throws FileNotFoundException
- 创建或覆盖已有文件:public FileOutputStream(File file) throws FileNotFoundException
- 文件内容追加:public FileOutputStream(File file, boolean append) throws FileNotFoundException
代码一:将整个字节数组的内容进行了输出。
package 字节流与字符流;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class TestD {
public static void main(String[] args) throws Exception { //此处抛出
//1.定义要输出文件的路径
File file=new File("D:"+File.separator+"Demo"+File.separator+"my.txt");
//此时由于目录不存在,所以文件不能够输出,那么应该先创建目录
if(!file.getParentFile().exists()){//文件能目录不存在
file.getParentFile().mkdirs(); //创建目录
}
//2.应该使用OutputStream和其子类进行对象实例化,此时目录存在,文件不存在
OutputStream output=new FileOutputStream(file);
//3.要进行文件内容的输出
String str="好好学习,天天向上!";
byte data []=str.getBytes();//将字符串变为字节数组
output.write(data);
//4.资源操作的最后一定要进行关闭
output.close();
}
}
以上代码是将整个字节数组进行输出,并且在输出之前,如果输出的文件不存在还可以创建之后,再输出。对于输出操作再整个OutputsStream类里面一共定义了三个方法。
代码二:采用单个字节的方式输出。
for(int x=0;x<data.length;x++){
output.write(data[x]); //将内容输出
}
代码三:输出部分字节数组内容。注:一个中国字等于两个字符,当长度为基数的时候就差一个字符的空间就会显示问号。
output.write(data,6,6);
但是以上三段代码由于FileOutputStream构造方法的原因,每一次写入都会覆盖,因此如果需要追加内容就只需要更换FileOutputStream构造方法。只要程序输出内容,都可以利用OutputStream类完成。
二标题:字节输入流:InputStream
如果程序需要进行数据的读取操作,可以利用InputStream类实现该功能。该类定义如下:
-
public abstract class InputStream extends Object implements Closeable
读取方法:
读取单个字节:public abstract int read() throws IOException
—返回值:返回读取的单个字节,如果已经读完就返回-1.
将读取的数据保存在字节数组里: public int read(byte[] b) throws IOException
—返回值:返回数据读取的长度,如果读取到结尾了,返回-1;
将读取的数据保存在部分字节数组里:public int read(byte[] b, int off, int len) throws IOException
—返回值:读取的部分数据的长度,如果已经读取到结尾了,返回-1.
由于InputStream是一个抽象类,所以要利用它的子类FileInputStream子类进行文件读取。
构造方法:public FileInputStream(File file) throws FileNotFoundException
范例: 向数组里面读取数据
package 字节流与字符流;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class TestD {
public static void main(String[] args) throws Exception { //此处抛出
//1.定义要输出文件的路径
File file=new File("D:"+File.separator+"Demo"+File.separator+"my.txt");
//1.需要判断文件是否存在后才可以进行读取
if(file.exists()){ //文件存在
//2.使用InputStream进行读取
InputStream input=new FileInputStream(file);
//3.进行数据读取
byte data [] = new byte [1024]; //准备出一个1024数组
int temp=input.read(data); //将内容保存到字节数组
//4.关闭输入流
input.close();
System.out.println("【"+new String(data,0,temp)+"】");
}
}
}
范例:单个字节读取数据
因为一个文件有很多的数据,故只能利用循环进行读取。另外没有确定循环次数,因为只能通过while循环。
实现一(了解):do...while
//3.进行数据读取
byte data [] = new byte [1024]; //准备出一个1024数组
int foot=0;
int temp=0;
do{
temp=input.read(); //读取一个字节
if(temp!=-1){ //现在是真实的内容
data[foot++]=(byte)temp; //保存读取的字节到数组中
}
}while(temp!=-1); //如果现在读取的temp的字节数据不是-1.表示还有内容
//4.关闭输入流
input.close();
实现二(重点):whie
//3.进行数据读取
byte data [] = new byte [1024]; //准备出一个1024数组
int foot=0;
int temp=0;
//第一部分:temp=input.read(),表示将read()读取的字节内容给了temp变量
//第二部分:temp=input.read()!=-1,判断读取出来的temp内容是否是-1
while((temp=input.read())!=-1){
data[foot++]=(byte) temp; //有内容进行保存
}
//4.关闭输入流
input.close();
此类读取方式是开发中使用最多的情况。
三、字符输出流:Writer
Writer类是在JDK1.1中增加的,其类的定义如下:
-
public abstract class Writer extends Object implements Appendable, Closeable, Flushable
这个类出了实现Closeable和Flushable接口外,又多实现了appendable,其定义如下:
-
public interface Appendable{ Appendable append(char c) throws IOException
-
Appendable append(CharSequence csq) throws IOException Appendable append(CharSequence csq, int start, int end) throws IOException
-
}
在Appendable接口里面定义了追加的操作,而且追加的数据都是字符串和者字符。
在Writer类里面定义有如下的输出方法(部分):
输出全部字符数组:public void write(char[] cbuf) throws IOException;
输出字符串:public void write(String str) throws IOException
Writer由于是一个抽象类,所以在实例化的时候应该用其子类FileWriter子类;
代码:
package 字节流与字符流;
import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class TestD {
public static void main(String[] args) throws Exception { //此处抛出
//1.定义要输出文件的路径
File file=new File("D:"+File.separator+"Demo"+File.separator+"my.txt");
if(file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
//2.实例化Writer类对象
Writer out=new FileWriter(file);
//3.进行内容输出
String str="千万不要被节后综合征打败,你们所有人都已经开始挑战我了!";
out.write(str); //输出字符串
//4.关闭输出流
out.close();
}
}
可以发现Writer作为字符输出流,可以直接进行字符串的输出 ,这一点就比OutputStream类强。
四、字符输入流:Reader
Reader是进行字符数据读取的输入流,其本身也是一个抽象类.
-
public abstract class Reader extends Object implements Readable, Closeable
在reader类里面也提供又一系列的read()方法:
读取内容道字符数组:public int read(char[] cbuf) throws IOException
—返回值:表示读取的数据长度,如果已经读取道结尾了就返回-1;
为Reader类实例化可以使用FileReader子类完成。
代码:使用Reader读取数据
package 字节流与字符流;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
public class TestD {
public static void main(String[] args) throws Exception { //此处抛出
//1.定义要输出文件的路径
File file=new File("D:"+File.separator+"Demo"+File.separator+"my.txt");
if(file.exists()){
//2.为Reader类对象实例化
Reader in=new FileReader(file);
//3.读取数据
char data []=new char [1024];
int len=in.read(data);
//4.关闭输入流
in.close();
System.out.println(new String(data,0,len));
}
}
}
与字节输入流相比结构几乎一样,但是数据类型由byte更换为了 char而已。
五、字节流与字符流的区别?
区别:字节流直接与终端进行数据交互,而字符流需要将数据经过缓冲区进行处理后才可以输出。在使用OutputStream输出数据的时候最后即时没有关闭流,那么内容也可以正常输出,但是如果使用的是字符输出流,如果不关闭那么就表示在缓冲区的内容不会被强制性的清空,所以就不会输出数据.如果有特殊情况不能够关闭字符输出流,可以使用flush()方法强制清空缓冲区。
代码:强制清空字符流缓冲区
package 字节流与字符流;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
public class TestD {
public static void main(String[] args) throws Exception { //此处抛出
//1.定义要输出文件的路径
File file=new File("D:"+File.separator+"Demo"+File.separator+"my.txt");
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
Writer out=new FileWriter(file);
String str="你好!";
out.write(str);//输出字符串数据
out.flush();//强制清空缓冲区
}
}
在开发之中,对于字节数据处理比较多,比如:图片,音乐,电影、文字。而对于字符流最大的好处是可以对中文进行有效处理。
总结:
1.字节流的输出以及输入操作的代码必须熟练掌握。
即:OutputStream类与InputStream类中的write()和read()方法必须掌握清楚;
2.中文处理的时候强烈建议使用字符流。