java IO 字节流、字符流操作总结二之字节流

时间:2021-09-25 21:00:40

上一篇,主要介绍了文件类File和RandomAccessFile类的用法。接下来,我觉得还是将IO流分为字节流和字符流两部分介绍比较好。这样不至于搞混乱,同时也便于对比。这一篇主要介绍字节流。

1、字节流

首先上一张字节流的家族图谱。

java IO 字节流、字符流操作总结二之字节流

字节流主要分为两部分:InputStream、OutputStream。InputStream抽象了应用程序读取数据的方式,OutputStream抽象了应用程序写出数据的方式。

注意有时会碰到EOF(即End Of File),表示已经读完。读到-1时表示读到文件的结尾。

a、InputStream输入流基本的操作方法

int b=in.read();读一个字节,无符号填充到int低八位,-1表示EOF。
in.read(byte[]buf);读取数据填充到字节数组buf中
in.read(byte[]buf,int start,int size);读取数据到字节数组buf。然后从buf的start位置开始存放size长度的数据

b、OutputStream输出流本操作方法

out.write(intb);写一个byte到流中,写的内容是b的低8位
out.write(byte[]buf);将一个buf字节数组都写入到流
out.write(byte[]buf,int start,int size);字节数组buf从start位置开始写size长度的字节到流。

c、FileInputStream 具体实现了文件上的读取文件

注:1>单字节的读取即不用数组,在读取大文件时效率较低。

       2>批量的读取,对于大文件而言效率较高,也是我们最常用的读取文件的方式。

       3>byte类型8位,int类型为32位,为了避免数据类型的转换的错误。通过0xff将高24为清零。

       4>read()适合单字节的读取大小

in.read(byte[] buf,int start,int size);字节数组适合读取大文件 

d、FileOutputStream实现向文件中写出byte数据的方法。

文件输出流的写法:

FileOutputStream  output=new FileOutputStream(file,true);//这个方法表示文件若不存在,则创建新的文件,若存在则在后面添加内容。
FileOutputStream output=new FileOutputStream(file);//这个方法表示文件不存在就创建新文件,若文件存在则先删除文件然后再创建文件。

在执行完output.write(byte[] buf,int start,int size)之后,一定要调用output.flush()方法来刷新缓冲区。 

测试代码如下:

package com.ll.iofile;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
* 这个方法是用来测试字符流的
* 主要用到是InputStreamReader 字符输出流
* OutputStreamWriter
* @author LULEI
*
*/
public class testInputStreamReaderAndOutputStreamWriter {

public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
/*这是测试第一个例子
* 就是将gbk编码的文件复制成utf-8格式的文件
FileInputStream in=new FileInputStream("DEMO\\fileio1.txt");
InputStreamReader isr=new InputStreamReader(in);//此处默认项目的编码是gbk的
*/
/*这是测试第一个例子
* 就是将gbk编码的文件复制成utf-8格式的文件
FileOutputStream out=new FileOutputStream("Demo\\OutputStreamUTF8.txt");
OutputStreamWriter osw=new OutputStreamWriter(out,"utf-8");
*/
FileInputStream in=new FileInputStream("C:\\Users\\Administrator\\Desktop\\OutputStreamUTF8.txt");
InputStreamReader isr=new InputStreamReader(in,"utf8");//这样的写法就是设置为utf8编码
FileOutputStream out=new FileOutputStream("Demo\\OutputStreamGBK.txt");
OutputStreamWriter osw=new OutputStreamWriter(out);//默认的编码就是gbk
int c=0;
/*这是单字节的输出
while((c=isr.read())!=-1){
System.out.print((char)c);
}
*/
char[] buf=new char[20*1024];
while((c=isr.read(buf, 0, buf.length))!=-1){
// String str=new String(buf);
// System.out.println(str);
osw.write(buf,0,c);
osw.flush();
}
isr.close();
osw.close();
}

}

e、 数据输入输出流

它是字节流的一个拓展。它是用来帮助方便操作类型数据的。

1>  包含DataOutputStream和DataInputStream

2>  对“流“功能的扩展,可以更加方便的读取int,long,字符等类型数据。

3>  DataOutputStream的方法:

writeInt()/writeDouble()/writeUTF()

4>  DataInputStream的方法:

readInt()/readDouble()/readUTF()

代码如下:

package com.ll.iofile;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.Arrays;

/**
* 这个类用于测试数据的输入输出流
* 即DataOutputStream 和DataInputStream
* @author LULEI
*
*/
public class testDataOutputStreamAndDataInputStream {

public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
//测试DataOutputStream类
String str="Demo\\wq77.txt";
DataOutputStream dos=new DataOutputStream(
new FileOutputStream(str));//实例化一个对象
dos.write(10);//占一个字节

dos.writeInt(-10);//写一个int型整数,占4个字节
dos.writeDouble(10.8);//占8个字节



//以UTF-8的格式写入字符串
dos.writeUTF("中国");//一个汉子占3个字节

//以utf-16be的格式写入字符串
dos.writeChars("中国");//一个汉字占2个字节

dos.close();

//打印输出的文件的字节
IOUtils.printHexByByte(str);
System.out.println();

//实例化数据输入流对象
DataInputStream dif=new DataInputStream(new FileInputStream(str));
int a=dif.read();
System.out.println(a);
int b=dif.readInt();
System.out.println(b);
double d=dif.readDouble();
System.out.println(d);

String s1=dif.readUTF();
System.out.println(s1);

byte[] bytes=new byte[6];
dif.read(bytes);
System.out.println(Arrays.toString(bytes));//转换为字符串显示
dif.close();

}

}

f、BufferedInputStream&BufferedOutputStream(带有缓冲区的输入输出流)

这两个流位于IO提供了带有缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能。从应用程序中把输入放入文件,相当于将一缸水倒入另一个缸中。

1>  FileOutputStream:write方法相当于一滴一滴的把水转移过去。

2>  DataOutputStream:writeXXX方法会方便一些,相当于一瓢一瓢的把水转移过去

3>  BufferedOutputStream:write()方法会更方便一些,相当于一瓢一瓢先放入水桶中,在从桶中倒入缸中,性能提高了。

代码如下:

package com.ll.iofile;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*
* 这个函数是为了测试BufferedOutputStream、FileOutputStream、DataOutputStream
* 这三个类在copy文件时的速度快慢
*/
public class testBufferedOutputStreamAndBufferedInputStream {

public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
File file=new File("C:\\Users\\Administrator\\Desktop\\浪潮之巅.pdf");
long start1=System.currentTimeMillis();
FileToCopyByByte(file);
long end1=System.currentTimeMillis();
System.out.println(end1-start1);

long start2=System.currentTimeMillis();
FileToCopy(file);
long end2=System.currentTimeMillis();
System.out.println(end2-start2);

long start3=System.currentTimeMillis();
DataToCopy(file);
long end3=System.currentTimeMillis();
System.out.println(end3-start3);

long start4=System.currentTimeMillis();
bufferedFileToCopy(file);
long end4=System.currentTimeMillis();
System.out.println(end4-start4);
}

public static void FileToCopyByByte(File file)throws IOException{
if(!file.exists()){
System.out.println("文件"+file+"不存在");
}
if(!file.isFile()){
System.out.println("文件"+file+"不是文件");
}
FileInputStream fis=new FileInputStream(file);//实例化读取字节的文件流
//实例化写字节文件流
FileOutputStream fos =new FileOutputStream("Demo\\fileIoByByte1.pdf");
int b=0;
while((b=fis.read())!=-1){
fos.write(b);
}
fis.close();
fos.close();
}



public static void FileToCopy(File file)throws IOException{
if(!file.exists()){
System.out.println("文件"+file+"不存在");
}
if(!file.isFile()){
System.out.println("文件"+file+"不是文件");
}
FileInputStream fis=new FileInputStream(file);//实例化读取字节的文件流
//实例化写字节文件流
FileOutputStream fos =new FileOutputStream("Demo\\fileio1.pdf");
int length=0;
byte[] buf=new byte[20*1024];
while((length=fis.read(buf, 0, buf.length))!=-1){
fos.write(buf);
// fos.flush();
}
fis.close();
fos.close();
}



public static void DataToCopy(File dateFile)throws IOException{
if(!dateFile.exists()){
System.out.println("文件"+dateFile+"不存在");
}
if(!dateFile.isFile()){
System.out.println("文件"+dateFile+"不是文件");
}
//实例化一个读取文件的对象
DataInputStream dis=new DataInputStream(new FileInputStream(dateFile));
//实例化一个写文件的对象
DataOutputStream dos=new DataOutputStream(new FileOutputStream("Demo\\datafile1.pdf"));
int length=0;
byte[] buf=new byte[20*1024];
while((length=dis.read(buf, 0, buf.length))!=-1){
dos.write(buf);
// dos.flush();
}
//关闭文件
dis.close();
dos.close();
}



public static void bufferedFileToCopy(File bufferedFile)throws IOException{
if(!bufferedFile.exists()){
System.out.println("文件"+bufferedFile+"不存在");
}
if(!bufferedFile.isFile()){
System.out.println("文件"+bufferedFile+"不是文件");
}
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("Demo\\bufferedfile1.pdf"));
BufferedInputStream bis=new BufferedInputStream(new FileInputStream(bufferedFile));
int length=0;
byte[] buf=new byte[20*1024];
while((length=bis.read(buf, 0, buf.length))!=-1){
bos.write(buf);
bos.flush();
}
bis.close();
bos.close();
}
}

到这里我只是简单的介绍了一些常用的字节流。比如FileInputStream和FileOutputStream。聪明的你会知道这里又是使用了装饰器类设计模式。哈哈,下次别人提到装饰器设计模式,你就说IO流的实现。下一篇我讲介绍字符流的知识。