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

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

1、字节流

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


字节流主要分为两部分: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流的实现。下一篇我讲介绍字符流的知识。

猜你喜欢

转载自blog.csdn.net/LULEI1217/article/details/51001633