Java之IO流

今天复习了一下IO流,故想总结一下。


一、流的定义

流就是程序和设备之间嫁接起来的一根用于数据传输的管道,这个管道上有很多按钮,不同的按钮可以实现不同的功能,这根管道就是流。

如果一个类是用作输入输出,则这个类有一个新的名字,叫做流,所以说,流一定是类,但类不一定是流。



二、流的分类

Java中的流,可以从不同的角度进行分类。

按照数据流的方向不同可以分为:输入流和输出流。

按照处理数据单位不同可以分为:字节流和字符流。

按照实现功能不同可以分为:节点流和处理流。

注意:输入流和输出流都是对于程序来讲的,比如说OutputStream是输出流,是程序输出数据到其他设备中去。


节点流(也叫原始流):直接与数据源相连,读入或读出。


处理流(也叫包裹流):在节点流的基础上,再套接一层,套接在节点流(也可能套接在处理流)上的就是处理流。



三、四大基本抽象流

J2SDK所提供的所有流类型都分别继承自以下四种抽象流类型。


InputStream和OutputStream读写数据的单位是一个字节,Reader和Writer读写数据的单位是一个字符,在Java中一个 字符占两个字节。

凡是以Stream结尾的都是字节流,以Writer或Reader结尾的是字符流。


InputStream中常用的方法:

public int read()	throws IOException
  • 读取一个字节并以整数形式返回
  • 如果读取到输入流的末尾则返回-1
public int read(byte[] b)	throws IOException
  • 从输入流中读取一定数量的字节,并将其存储在缓冲器数组b中。以整数形式返回实际读取的字节数
  • 如果因为流位于文件末尾而没有可用的字节,则返回值-1
public int read(byte[] b,int off,int len)	throws IOException
  • 从输入流中最多读取len个字节的数据并存入数组b中,读取的第一个字节存储在元素b[off]中,下一个字节存储在b[off+1]中,以此类推。读取的字节数最多等于len
  • 尝试读取len个字节,但读取的字节也可能小于该值,以整数形式返回实际读取的字节数
  • 如果读到了文件末尾,返回-1
void close()	throws IOException
  • 关闭此输入流并释放与该流关联的所有系统资源
OutputStream中常用的方法:
void write(int b)	throws IOException
  • 向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(byte[] b)	throws IOException
  • 将一个字节类型的数组中的数据写入输出流
void write(byte[] b,int off,int len)	throws IOException
  • 将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void close()	throws IOException
  • 关闭此输出流并释放与该流关联的所有系统资源
void flush()	throws IOException
  • 将输出流中缓冲的数据全部写出到目的地
Reader和Writer中的常用方法与InputStream和OutputStream的方法类似,就不再做过多介绍。


四、文件流

文件流包括:
  • FileOutputStream   FileInputStream       ——字节流
  • FlieWriter       FlieReader                          ——字符流
先看一个例子:读取一个文件的内容并将其输出到显示器上
/*
	2017年2月28日23:30:24
	利用FileInputStream流来读取一个文件中的数据,并在显示器上输出!
*/
import java.io.*;

public class TestFileInputStream
{
	public static void main(String[] args) throws IOException       //先不考虑对异常的处理
	{
		FileInputStream fis = new FileInputStream("F:\Code\Java\TestFileInputStream.java");//也可以用FileReaderStream
		int temp;
		
		temp = fis.read();
		while(-1 != temp)
		{
			System.out.printf("%c",(byte)temp);
			temp = fis.read();
		}
		
		fis.close();
	}
}

字符流和字节流的区别:
  • FileInputStream和FileOutputStream可以完成所有格式的复制,而FileReader和FileWriter只能完成文本文件的复制,却无法完成视频等其他格式的复制
  • 因为字节是不需要解码和编码的,将字节转化为字符才存在编码和解码的问题
  • 字节流可以从所有格式的设备中读写数据,但字符流只能从文本格式的设备中读写数据
例子:使用FileInputStream和OutputStream实现对文件进行复制
/*
	2017年3月1日10:43:06
	使用FileInputStream和OutputStream对文件进行复制
*/
import java.io.*;

public class CopyFileInputStream
{
	public static void main(String[] args) throws IOException       //先不考虑对异常的处理
	{
		//如果是对文本文件的复制,也可以使用FileWriter和FileReader,但其他格式只能使用FileInputStream和OutputStream
		FileInputStream fis = new FileInputStream("F:\Code\Java\CopyFileInputStream.java");
		FileOutputStream fos = new FileOutputStream("F:\Code\Java\CopyFile.java");
		int temp;
		
		temp = fis.read();
		while(-1 != temp)
		{
			fos.write(temp);
			temp = fis.read();
		}
		
		fos.flush();
		fis.close();
		fos.close();
	}
}

四、缓冲流

缓冲流就是带有缓冲区的输入输出流。缓冲流可以显著减少对IO访问的次数,保护硬盘,而且提高了读写的效率。缓冲流是处理流,必须依附于节点流。

例子:使用缓冲流对文件进行复制,能极大的加快复制速率
/*
	2017年3月1日16:49:24
	使用缓冲流对文件进行复制
*/
import java.io.*;

public class TestBufferedInputStream
{
	public static void main(String[] args) throws IOException       //先不考虑对异常的处理
	{
		BufferedInputStream bis =new BufferedInputStream(new FileInputStream("F:\Code\Java\TestBufferedInputStream.java"));
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("F:\Code\Java\CopyFile_1.java"));
		
		byte[] data = new byte[1024];
		int len;
		
		len = bis.read(data);
		while(-1 != len)
		{
			bos.write(data,0,len);  //这里不能写成bos.write(data),因为数组data不一定会写满
			len = bis.read(data);
		}
		
		bos.flush();
		bis.close();
		bos.close();
	}
}

五、数据流

DataInputStream能够以一种与机器无关的方式,直接从底层字节输入流读取Java基本类型和String类型的数据。DataInputStream是包裹流,必须依附于InputStream,常用的方法有:

DataOutputStream能够以一种与机器无关的方式,直接从底层字节输出流写入Java基本类型和String类型的数据。DataOutputStream是包裹流,必须依附于OutputStream,常用的方法有:

例子:编程实现将long类型数据写入byte数组,然后从byte数组中把该数据读出来
注:这是Socket编程中经常要完成的功能,因为网络编程中经常要把数值型数据存入byte数组中, 然后把byte数组打包成数据包(即DatagramPacket),数据包经过网络传输到目的机,目的机再从byte数组中把原数值型数据还原回来。
/*
	2017年3月2日09:59:41
	编程实现将long类型数据写入byte数组,然后从byte数组中把该数据读出来

*/
import java.io.*;

public class TestDataInputStream
{
	public static void main(String[] args) throws IOException     //先不考虑对异常的处理
	{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();//会自动创建一个新的byte数组
		DataOutputStream dos = new DataOutputStream(baos);          
		long m = 12345678;
		dos.writeLong(m);
		dos.flush();
		
		byte[] data = baos.toByteArray();                //将ByteArrayOutputStream创建的数组复制给data
		
		
		//网络编程......
		
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		DataInputStream dis = new DataInputStream(bais);
		long n = dis.readLong();
		
		System.out.println("n = " + n);
		
		dos.close();
		dis.close();
		baos.close();
		bais.close();
	}
}



原文地址:https://www.cnblogs.com/yzy-blogs/p/6597321.html