字节输入流/输出流,是指以字节为单位进行输入或输出的方式。
一、字节输入流
创建步骤:
① 创建输入源文件的 File 对象:File file=new File("路径");
② 创建 File 对象的字节输入流对象:FileInputStream fis=new FileInputStream(file);
字节输入流方法的含义:
① .available() 返回一个整数,表示源文件内容一共多少个字节
② .read() 返回一个整数,表示阅读到的位置,也就是这个位置上的字节的ASCII或其他编码值。每执行一次 .read(),指针跳动一个字节。
③ .read(byte[] b) 返回一个整数,表示这次操作一共阅读了多少个字节,同时将阅读到的字节存入字节数组 b 中。
public static void main(String[] args) throws IOException
{
//创建File对象
File file=new File("D:\\android\\test\\a.txt");
//a.txt的内容是单词“Hello”
//创建FileInputStream对象
FileInputStream fis=new FileInputStream(file);
System.out.println(fis.available()); //得到源文件的字节总量是5
System.out.println(fis.read()); //得到第一个字节的编码是72,也就是H的ASCII码值
System.out.println(fis.read()); //得到第二个字节的编码是101,也就是e的ASCII码值
System.out.println(fis.read()); //得到第三个字节的编码是108,也就是l的ASCII码值
System.out.println(fis.read()); //得到第四个字节的编码是108,也就是l的ASCII码值
System.out.println(fis.read()); //得到第五个字节的编码是111,也就是o的ASCII码值
System.out.println(fis.read()); //结果为-1,表示未阅读到任何内容,阅读完毕
}
public static void main(String[] args) throws IOException
{
//创建File对象
File file=new File("D:\\android\\test\\a.txt");
//a.txt的内容是单词“Hello”
//创建FileInputStream对象
FileInputStream fis=new FileInputStream(file);
System.out.println(fis.available()); //得到源文件的字节总量5
byte[] b=new byte[10]; //创建一个字节数组,长度等于或大于源文件的字节总量即可,用于存储读到的字节
System.out.println(fis.read(b)); //返回本次阅读的字节数,结果是5,也就是一次阅读完毕;同时将阅读到的字节存入数组b
System.out.println(fis.read(b)); //再次执行,返回结果是-1,表示没有阅读到任何内容,阅读完毕
String x=new String(b); //将数组b以字节为单位组合为字符串,亦即恢复文件
System.out.println(x); //打印出内容,hello
}
本案例中,源文件只有5个字节,所以执行第一次 fis.read(b) 就阅读了全部字节。而实际上源文件如果特别长的话,可能需要执行多次 fis.read(b),此时就需要引入循环,只要不返回-1,就一直执行。例如:
public static void main(String[] args) throws IOException
{
//创建File对象
File file=new File("D:\\android\\test\\a.txt");
//a.txt的内容是单词“Helloworld”,但我们假设它很长
//创建FileInputStream对象
FileInputStream fis=new FileInputStream(file);
System.out.println(fis.available()); //得到源文件的字节总量5
byte[] b=new byte[10]; //创建一个字节数组,长度等于或大于源文件的字节总量即可,用于存储读到的字节
int length=0;
while((length=fis.read(b))!=-1)
{
String data=new String(b,0,length);
System.out.print(data);
}
fis.close(); //关闭文件资源
}
本案例中,之所以用 new String(b,0,length),是因为每次执行 fis.read(b),都会在数组中覆盖一部分上次执行的内容。比如,Helloworld 是 10 个字节,如果第一次执行了 8 个字节,数组 b 内对应的元素就是[H,e,l,l,o,w,o,r,null,null];第二次执行剩下的 2 个字节,数组 b 内对应的元素就成了[l,d,l,l,o,w,o,r,null,null],也就是把前两个元素覆盖了。因此,在由字符数组转化为字符串的时候要限定转化的范围,只转化本次 read 到的这部分字节。
二、字节输出流
总体步骤:
① 创建输出目标文件的 File 对象:File file=new File("路径");
② 创建 File 对象的字节输出流对象:FileOutputStream fos=new FileOutputStream(file) 或者FileOutputStream fos=new FileOutputStream(file,true)。不加 true 表示覆盖写入;加上 true 表示追加写入。
③ 将需要写入的字符串转化为字节数组:byte[] b=字符串.getBytes();
④ 使用字节输出流 fos 的 write 方法,执行写入。write 方法的参数有两种,一种是字节数组;另一种是整数数字,表示该数字代表的字节。
public static void main(String[] args) throws IOException
{
File file=new File("D:\\android\\test\\a.txt");
FileOutputStream fos=new FileOutputStream(file,true);
String s="goodbye,Tom";
byte[] b=s.getBytes();
fos.write(b);
fos.flush(); //清空缓存区
fos.close(); //关闭文件资源
}
之所以输出流要增加一项清空缓存区,是因为在程序与目标文件之间有一个缓存区域。如果将程序比作一个水龙头,目标文件比作水缸,缓存区就好比在两者之间运水的水桶。一般来说,水桶满了才运一次水,但最后一次写入的时候,有可能只有半桶水,而缓存区仍在等待程序写入数据,但此时水龙头里面已经没有水了,因此就需要我们强行将缓存区清空,也就是强行将最后的半桶水倒入缸里,这样目标文件的内容才算完整。