OutputStream与InputStream是所有字节流的抽象父类,字节流的处理单位是字节(1Byte)
FileOutputStream与FileInputStream
FileOutputStream(File file)
FileOutputStream(String name)
FileOutputStream(File file,boolean append)
FileOutputStream(String name,boolean append)
创建一个指定路径的输出流对象.
append表示是否在末尾追加.为true表示添加,为false的时候其实等同于一个参数的构造器.
若指定目录下没有传入的文件名,则会自动创建文件.
若指定文件的父目录不存在,则报文件找不到异常(FileNotFoundException).
import java.io.FileOutputStream;
public class FileClassTest {
public static void main(String[] args) {
//创建两个文件输出流对象
FileOutputStream fos=null;
FileOutputStream fos1=null;
//使用try...catch...包围.
try{
//一个参数的构造器,为了防止打错分隔符,可以使用常量File.separator来代替.
fos=new FileOutputStream("D:"+File.separator+"demo01.txt");
//两个参数的构造器.
fos1=new FileOutputStream("demo02.txt",true);
..........
}catch (Exception e){
e.printStackTrace();
}finally {
try {
//关闭流也需要try...catch...处理.
fos.close();
fos1.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
void close():关闭输出流.
void flush():将流内的数据冲刷至文件.
void write(int b):写出参数b的一个字节,int类型的低八位.
void write(byte[] b):将字节数组b中的数据按顺序写出.
void write(byte[] b,int off,int len):将字节数组b中的数据按顺序写出,从下标off开始,写入len个.
方法实例
..........
//写入int
fos1.write(100);
//写入byte数组
fos1.write(bs);
//写入byte数组的一部分
fos1.write(bs,2,3);
具体是什么效果在下面的输入流测试~
同输出流
void close():关闭输入流
int read():读取该流中的一个字节(8位二进制)的数据,返回一个int数据,存储到一个int数据的低八位上.如果读取至文件末尾,则返回-1.
int read(byte[] b):读取字节存入数组b中,最多能读取b.length个,返回的是实际读取的字节个数.
long skip(long n):跳过流中n个字节,传入负值则往回跳n个字节.
int available(): 返回此输入流中剩余的字节数.
文件输入流测试,读取的文件为上面创建的文件.
import java.io.FileInputStream;
import java.util.Arrays;
public class FileBlogTest {
public static void main(String[] args) {
FileInputStream fis=null;
try{
fis=new FileInputStream("demo02.txt");
//读取一个字节的方法,使用int类型数据接收一下.
int i=fis.read();
//输出的是读取数据对应的char值,读取的数据为小写字母d.
System.out.println("读取一个字节:"+i);
//读取数据存入byte数组中,定义数组的length为5.
//实际读出的内容是ABCDE.
byte[] bs=new byte[5];
int a= fis.read(bs);
//输出的依旧是数据对应的char值.
System.out.println("读取5个数据的byte数组:"+ Arrays.toString(bs));
//返回值为实际读取的个数.
System.out.println("输出返回值:"+a);
//跳过方法,这里跳过2.读出内容为CDE
fis.skip(2);
byte[] bs1=new byte[3];
fis.read(bs1);
System.out.println("读取跳过2个数据的byte数组:"+ Arrays.toString(bs1));
System.out.println(a);
//输出流中剩余的字节数
//先往回跳过5个位置
fis.skip(-4);
int left=fis.available();
System.out.println("剩余数据个数为"+left);
}catch (Exception e){
e.printStackTrace();
}finally {
try{
fis.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
运行结果
读取一个字节:100
读取5个数据的byte数组:[65, 66, 67, 68, 69]
输出返回值:5
读取跳过2个数据的byte数组:[67, 68, 69]
5
剩余数据个数为4
缓冲输出流的特点:在流里维护了一个缓冲区,写的时候先将字节写入缓冲区,当缓冲区满时,再一次性将数据写入目的地,有效降低了写入次数,因此也提高了效率.
因为缓冲输出流缺失即时性,可以使用flush方法进行冲刷.
常用构造器
BufferedOutputStream(OutputStream out):创建一个指定字节流输出流的缓冲流对象.
BufferedOutputStream(OutputStream out,int size):创建一个指定字节流输出流的缓冲流对象,并设置缓冲区的大小.
常用方法
void flush():将缓冲区内的数据冲刷出去.
void write(int b):写int数据的低八位至缓冲区内.
void write(int b,int off,int len):写一个指定长度(len)的字节数组至缓冲区,从off开始写入.
注意,调用缓冲流的关闭操作(close方法)时,先调用了flush方法.若同时存在多个流,应该先关闭高级流,再关闭低级流.
当一次性写入的字节超出缓冲区大小,会出现溢出的情况,溢出的字节会先写入文件.
方法测试
import java.io.*;
public class BufferedTest {
public static void main(String[] args) {
BufferedOutputStream bos=null;
BufferedInputStream bis=null;
File f=null;
try{
byte[] bytes="ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes();
//写入数据,但是由于没有充满缓冲区,所以并不能在文件中看到内容.
//创建一个文件
bos=new BufferedOutputStream(new FileOutputStream("buffered.txt"));
bis=new BufferedInputStream(new FileInputStream("buffered.txt"));
bos.write(bytes);
//输出大小
f=new File("buffered.txt");
System.out.println("文件的大小:"+f.length());
//flush方法将数据"推"出缓冲区
bos.flush();
System.out.println("再次输出文件大小:"+f.length());
//读取文件内容
byte[] bytes1=new byte[(int)(f.length())];
bis.read(bytes1);
//转换为字母输出
System.out.println("输出数组↓");
for (int i = 0; i < bytes.length; i++) {
System.out.print((char)bytes[i]+" ");
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
bos.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
运行结果
文件的大小:0
再次输出文件大小:26
输出数组↓
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
可以看到第一次输出大小时文件的大小为0,调用flush方法之后缓冲区内的数据被写入文件,所以变为26.for循环遍历输出输出数组元素,强转为char之后可以看到是原本的写入内容.