JAVAOOP-16 IO流

JAVAOOP-16 IO流

一. 流的概念

流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。
​ 一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。
​ 流的方向是重要的,根据流的方向,流可分为两类:输入流和输出流。用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往输入流写,而不能读它。
​ 实际上,流的源端和目的端可简单地看成是字节的生产者和消费者,对输入流,可不必关心它的源端是什么,只要简单地从流中读数据,而对输出流,也可不知道它的目的端,只是简单地往流中写数据。

​ 形象的比喻——水流 ,文件**======**程序 ,文件和程序之间连接一个管道,水流就在之间形成了,自然也就出现了方向:可以流进,也可以流出.便于理解,这么定义流: 流就是一个管道里面有流水,这个管道连接了文件和程序。

二. 流的分类

  1. 按输入输出分:

    ​ 输入流: Reader, InputStream类型的子类

    ​ 输出流: Writer, OutputStream类型的子类

  2. java.io包中的类对应两类流,一类流直接从指定的位置(如磁盘文件或内存区域)读或写,这类流称为结点流(node stream),其它的流则称为过滤器(filters)。过滤器输入流往往是以其它输入流作为它的输入源,经过过滤或处理后再以新的输入流的形式提供给用户,过滤器输出流的原理也类似

  3. java.io包中的stream类根据它们操作对象的类型是字符还是字节可分为两大类: 字符流和字节流。

  • Java的字节流

InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。

  • Java的字符流

Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先。

字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

注意: 输入输出流是相对于内存来说的,

​ 输入内存也就是 读取的过程 输入流就是读取操作

​ 从内存输出也就是写入过程 输出流也就是写入操作

三. 流的体系结构

JAVA字节流

  • **FileInputStream和FileOutputStream

    **这两个类属于结点流,第一个类的源端和第二个类的目的端都是磁盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。如:
    FileInputStream infile = new FileInputStream(“myfile.dat”);
    FileOutputStream outfile = new FileOutputStream(“results.dat”);

要注意的是,构造FileInputStream, 对应的文件必须存在并且是可读的,而构造FileOutputStream时,如输出文件已存在,则必须是可覆盖的。

  • BufferedInputStream和BufferedOutputStream
    它们是过滤器流,其作用是提高输入输出的效率。
  • DataInputStream和DataOutputStream
    这两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写Java数据。所以比较适合于网络上的数据传输。这两个流也是过滤器流,常以其它流如InputStream或OutputStream作为它们的输入或输出。

Java的字符流

字符流主要是用来处理字符的。Java采用16位的Unicode来表示字符串和字符,对应的字符流按输入和输出分别称为readers和writers。

  • InputStreamReader和OutputStreamWriter
    在构造这两个类对应的流时,它们会自动进行转换,将平台缺省的编码集编码的字节转换为Unicode字符。对英语环境,其缺省的编码集一般为ISO8859-1。
  • BufferedReader和BufferedWriter
    这两个类对应的流使用了缓冲,能大大提高输入输出的效率。这两个也是过滤器流,常用来对InputStreamReader和OutputStreamWriter进行处理。

四. 字节流

1. FileOutputStream 和 FileInputStream

OutputStream 输出流 抽象类 不能直接使用 使用子类FileOutputStream 从某个文件里面读取

普通方法:

abstract void write(int b) 将指定的字节写入此输出流。
void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。
void flush() 刷新此输出流并强制写出所有缓冲的输出字节。
void close() 关闭此输出流并释放与此流有关的所有系统资源。

InputStream 输入流 抽象类 不能直接使用 使用子类FileInputStream 写入到某个文件里

普通方法:

abstract int read() 从输入流中读取数据的下一个字节。

int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
void close() 关闭此输入流并释放与该流关联的所有系统资源。

FileOutputStream:
FileOutputStream(File file)
​ 创建一个向指定 File 对象表示的文件中写入数据的文件输出流
FileOutputStream(File file, boolean append)
​ 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(String name)
​ 创建一个向具有指定名称的文件中写入数据的输出文件流。
FileOutputStream(String name, boolean append)
​ 创建一个向具有指定 name 的文件中写入数据的输出文件流。
void write(int b)
​ 将指定字节写入此文件输出流。

FileInputStream:

FileInputStream(File file)
​ 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
FileInputStream(String name)
​ 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。

int read()
​ 从此输入流中读取一个数据字节。

思路:

  1. 构建输入输出流对象
  2. 读取或者写入数据
  3. 关闭流
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class TesrRW {

	public static void main(String[] args) throws IOException {
		TesrRW rw=new TesrRW();
		rw.doWrite();
		rw.doRead();

	}

//写信息到文件
public void doWrite() throws IOException{
	//建立管道,构建(打开)输出流
	OutputStream out=new FileOutputStream("D:\\day17\\aaa.txt");
	
	//针对输入输出流进行操作(写入信息)
	out.write(8);
	out.write('a');
	out.write('b');
	
	//写完之后,关闭输出流(关闭资源)
	out.close();
}
//读取文件
public void doRead(){
	//打开输入流
	InputStream in=null;
	try {
		in=new FileInputStream("D:\\day17\\aaa.txt");
		int one=in.read();
		int two=in.read();
		int three=in.read();
		System.out.println(one+" "+(char)two+" "+(char)three);
	}
			
		catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}//关闭输入流
	finally{
		if(in!=null){
			try {
				in.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	}
}

2. 文件太大,如何读取?

思路: 通过循环来实现

public int read() throws IOException从此输入流中读取一个数据字节。如果没有输入可用,则此方法将阻塞。

指定者:类 InputStream 中的 read
返回:下一个数据字节;如果已到达文件末尾,则返回 -1。
抛出: IOException - 如果发生 I/O 错误。

当读取到最后的时候, int read() 返回值为-1 ,此时则为判断条件

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;


public class TestRFile {

	public static void main(String[] args) throws IOException {
		readFile();

	}
	public static void readFile() throws IOException{
		String filePath="D:\\2015.7.27初级班\\day17\\TesrRW.java";
		InputStream in=new FileInputStream(filePath);//文件太大,不知道有多少字节
		int data=-1;//当读完的时候,返回值为-1,data表示读取道德字节
		while((data=in.read())!=-1){
			System.out.print((char)data);
		}
		in.close();
	}

}

3. 写入时如何在文件末尾追加而不是覆盖?

构造方法:

FileOutputStream(File file, boolean append)
​ 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。

FileOutputStream(String name, boolean append)
​ 创建一个向具有指定 name 的文件中写入数据的输出文件流。

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;


public class TestWF {

	public static void main(String[] args) throws IOException {
		doWrite();

	}
	public static void doWrite() throws IOException{
		OutputStream out=new FileOutputStream("D:\\day17\\b.txt",true);
		out.write('z');
		out.close();
	}

}

4. DataOutputStream 和 DataInputStream

​ 属于过滤流,在其他输入输出流的基础之上增加新的功能

DataInputStream:

DataInputStream(InputStream in)
​ 使用指定的底层 InputStream 创建一个 DataInputStream。

int read(byte[] b)
​ 从包含的输入流中读取一定数量的字节,并将它们存储到缓冲区数组 b 中。
int read(byte[] b, int off, int len)
​ 从包含的输入流中将最多 len 个字节读入一个 byte 数组中。
boolean readBoolean()
​ 参见 DataInput 的 readBoolean 方法的常规协定。
byte readByte()
​ 参见 DataInput 的 readByte 方法的常规协定。
char readChar()
​ 参见 DataInput 的 readChar 方法的常规协定。
double readDouble()
​ 参见 DataInput 的 readDouble 方法的常规协定。
float readFloat()
​ 参见 DataInput 的 readFloat 方法的常规协定。
int readInt()
​ 参见 DataInput 的 readInt 方法的常规协定。
long readLong()
​ 参见 DataInput 的 readLong 方法的常规协定。
short readShort()
​ 参见 DataInput 的 readShort 方法的常规协定。
int readUnsignedShort()
​ 参见 DataInput 的 readUnsignedShort 方法的常规协定。
String readUTF()
​ 参见 DataInput 的 readUTF 方法的常规协定。

DataOutputStream:

DataOutputStream(OutputStream out)
​ 创建一个新的数据输出流,将数据写入指定基础输出流。
void flush()
​ 清空此数据输出流。
void write(byte[] b, int off, int len)
​ 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入基础输出流。
void write(int b)
​ 将指定字节(参数 b 的八个低位)写入基础输出流。
void writeBoolean(boolean v)
​ 将一个 boolean 值以 1-byte 值形式写入基础输出流。
void writeByte(int v)
​ 将一个 byte 值以 1-byte 值形式写出到基础输出流中。
void writeBytes(String s)
​ 将字符串按字节顺序写出到基础输出流中。
void writeChar(int v)
​ 将一个 char 值以 2-byte 值形式写入基础输出流中,先写入高字节。
void writeChars(String s)
​ 将字符串按字符顺序写入基础输出流。
void writeDouble(double v)
​ 使用 Double 类中的 doubleToLongBits 方法将 double 参数转换为一个 long 值,然后将该 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。
void writeFloat(float v)
​ 使用 Float 类中的 floatToIntBits 方法将 float 参数转换为一个 int 值,然后将该 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。
void writeInt(int v)
​ 将一个 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。
void writeLong(long v)
​ 将一个 long 值以 8-byte 值形式写入基础输出流中,先写入高字节。
void writeShort(int v)
​ 将一个 short 值以 2-byte 值形式写入基础输出流中,先写入高字节。
void writeUTF(String str)
​ 以与机器无关方式使用 UTF-8 修改版编码将一个字符串写入基础输出流。

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class TestData {

	public static void main(String[] args) throws IOException {
		writeData();
		readData();

	}
	public static void writeData() throws IOException{
		OutputStream out=new FileOutputStream("D:\\day17\\bbb.txt");
		DataOutputStream dos=new DataOutputStream(out);
		//过滤流,包装一个基本输入输出流,在基本IO流的基础上增加新的功能,提高效率
		//管道建立成功,接着传输数据
		//DataOutputStream dos2=new DataOutputStream(new FileOutputStream("D:\\day17\\bbb.txt"));
		//也可以写成上面那样
		//写入8中基本数据类型
		byte b=1;
		short s=2;
		int i=3;
		long l=4;
		float f=5.0f;
		double d=6;
		char c='7';
		boolean bl=false;
		String str="开心点吧";
		dos.writeByte(b);
		dos.writeShort(s);
		dos.writeInt(i);
		dos.writeLong(l);
		dos.writeFloat(f);
		dos.writeDouble(d);
		dos.writeChar(c);
		dos.writeBoolean(bl);
		dos.writeUTF(str);
		
		dos.close();
	}
	public static void readData() throws IOException{
		InputStream in=new FileInputStream("D:\\2015.7.27初级班\\day17\\bbb.txt");
		DataInputStream  dis=new DataInputStream(in);//包装输入流
		
		//读取文件,一定要遵从当初写的顺序
		byte b=dis.readByte();
		short s=dis.readShort();
		int i=dis.readInt();
		long l=dis.readLong();
		float f=dis.readFloat();
		double d=dis.readDouble();
		char c=dis.readChar();
		boolean bl=dis.readBoolean();
		String str=dis.readUTF();
		
		System.out.println(b+" "+s+" "+i+" "+l+" "+f+" "+d+" "+c+" "+bl +" "+str);
		dis.close();
	}
}

5. 练习: 如何实现文件复制功能?

思路: 复制文件其实就是边读边写的过程

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;


public class TestCopy {

	public static void main(String[] args) throws IOException {
		String src="D:\\TesrRW.java";
		String tar="D:\\day17\\b.txt";
		doCopy(src, tar);

	}
	public static void doCopy(String src,String tar) throws IOException{
		InputStream fis=new FileInputStream(src);
		OutputStream fos=new FileOutputStream(tar);
		//复制文件其实就是边读边写的过程
		int data=-1;
		while((data=fis.read())!=-1){
			fos.write(data);
		}
		fis.close();
		fos.close();
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值