Java IO流 总结

IO流分类:

1. 输入流(读)和输出流(写)。

2. 因为处理的数据不同,分为字节流和字符流。

close()和flush()的区别:

  • flush():将缓冲区的数据刷到目的地中后,流可以使用。
  • close():将缓冲区的数据刷到目的地中后,流就关闭了,该方法主要用于结束调用的底层资源。这个动作一定做。

流的操作规律

  1. 明确源和目的
    • 数据源:就是需要读取,可以使用两个体系:InputStream、Reader;
    • 数据汇:就是需要写入,可以使用两个体系:OutputStream、Writer;
  2. 操作的数据是否是纯文本数据?
    • 如果是:数据源:Reader
      数据汇:Writer
    • 如果不是:数据源:InputStream
      数据汇:OutputStream
  3. 明确操作的数据设备
    • 数据源对应的设备:硬盘(File),内存(数组),键盘(System.in)
    • 数据汇对应的设备:硬盘(File),内存(数组),控制台(System.out)。
  4. 需要在基本操作上附加其他功能吗?
    • 比如缓冲,如果需要就进行装饰。


字节流: InputStream OutputStream

适合操作非文本文件

处理字节数据的流对象。设备上的数据无论是图片或者dvd,文字,它们都以二进制存储的。二进制的最终都是以一个8位为数据单元进行体现,所以计算机中的最小数据单元就是字节。意味着,字节流可以处理设备上的所有数据,所以字节流一样可以处理字符数据。

输入流:

基类:InputStream(抽象)

实现类: FileInputStream

FileInputStream fi = new FileInputStream(file);

读取:
int i;
while((i=fi.read())!=-1){
    System.out.print((char)i);
}

输出流:

基类:OutputStream(抽象)

实现类: FileOutputStream

FileOutputStream fo = new FileOutputStream("C:/a.txt",false);

字符流读写文件:

private static void method2(String src, String dest) throws IOException {

//1,指定数据源

FileInputStream in = new FileInputStream(src);

//2,指定目的地

FileOutputStream out = new FileOutputStream(dest);

//3,读数据

byte[] buffer = new byte[1024];

int len = -1;

while ( (len=in.read(buffer)) != -1) {

//4,写数据

out.write(buffer, 0, len);

}

//5,关闭流

in.close();

out.close();

}

【注】

  1. 路径: C:/a.txt -> C:\\a.txt
  2. false: 不覆盖文件,true:更新覆盖原文件
  3. 原文件不存在则新建
  4. 路径可由 File 对象代替


字符流: Reader Writer

适合操作文本文件

字符每个国家都不一样,所以涉及到了字符编码问题,那么GBK编码的中文用unicode编码解析是有问题的,所以需要获取中文字节数据的同时+ 指定的编码表才可以解析正确数据。为了方便于文字的解析,所以将字节流和编码表封装成对象,这个对象就是字符流。只要操作字符数据,优先考虑使用字符流体系。

输入流:Reader

实现类:FileReader

//自定义缓冲区
import java.io.*;
class FileReaderDemo2 {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("demo.txt"); //创建读取流对象和指定文件关联。
		//因为要使用read(char[])方法,将读取到字符存入数组。所以要创建一个字符数组,一般数组的长度都是1024的整数倍。
		char[] buf = new char[1024];
		int len = 0;
		while(( len=fr.read(buf)) != -1) {
			System.out.println(new String(buf,0,len));
		}
		fr.close();
	}
}

输出流:Writer

实现类:FileWriter



缓冲流: Buffer

字节缓冲流:

BufferedInputStream

BufferedOutputStream

字符缓冲流 高效 读取文件

private static void method4(String src, String dest) throws IOException {

//1,指定数据源

BufferedInputStream in = new BufferedInputStream(new FileInputStream(src));

 //2,指定目的地

BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(dest));

 //3,读数据

byte[] buffer = new byte[1024];

int len = -1;

while ( (len = in.read(buffer)) != -1) {

//4,写数据

out.write(buffer, 0, len);

}
 //5,关闭流

in.close();

out.close();

}

字符缓冲流:

BufferedReader(读)

FileReader fr = new FileReader("bufdemo.txt");
	BufferedReader bufr  = new BufferedReader(fr);
	String line = null;
	while((line=bufr.readLine())!=null){  //readLine方法返回的时候是不带换行符的。
		System.out.println(line);
	}
	bufr.close();

BufferedWriter(写)

	FileWriter fw = new FileWriter("bufdemo.txt");
	BufferedWriter bufw = new BufferedWriter(fw);//让缓冲区和指定流相关联。
	for(int x=0; x<4; x++){
		bufw.write(x+"abc");
		bufw.newLine(); //写入一个换行符,这个换行符可以依据平台的不同写入不同的换行符。
		bufw.flush();//对缓冲区进行刷新,可以让数据到目的地中。
	}
	bufw.close();//关闭缓冲区,其实就是在关闭具体的流。

字符缓冲流读写文件

public class CopyTextFile {

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

//1,指定数据源, 是数据源中读数据,采用输入流

BufferedReader in = new BufferedReader(new FileReader("file.txt"));

//2,指定目的地,是把数据写入目的地,采用输出流

BufferedWriter out = new BufferedWriter(new FileWriter("copyFile.txt"));

//3,读数据

String line = null;

while ( (line = in.readLine()) != null ) {

out.write(line);//4,写数据

out.newLine();//写入换行符号

}

//5,关闭流

out.close();

in.close();

}

}



转换流: InputStreamReader OutputStreamWriter

转换流特有功能

  • 转换流可以将字节转成字符,原因在于,将获取到的字节通过查编码表获取到指定对应字符。

凡是操作设备上的文本数据,涉及编码转换,必须使用转换流。

转换流 InputStreamReader

【注意】:在读取指定的编码的文件时,一定要指定编码格式,否则就会发生解码错误,而发生乱码现象。

代码演示:

public class InputStreamReaderDemo {

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

//演示字节转字符流的转换流

readCN();

}

public static void readCN() throws IOException{

//创建读取文件的字节流对象

InputStream in = new FileInputStream("c:\\cn8.txt");

//创建转换流对象

//InputStreamReader isr = new InputStreamReader(in);这样创建对象,会用本地默认码表读取,将会发生错误解码。

InputStreamReader isr = new InputStreamReader(in,"utf-8");

//使用转换流去读字节流中的字节

int ch = 0;

while((ch = isr.read())!=-1){

System.out.println((char)ch);

}

//关闭流

isr.close();

}

}

转换流 OutputStreamWriter

【注意】:在写出指定的编码的文件时,一定要指定编码格式,否则读取时编码格式不同可能发生乱码现象。

将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去。

代码演示:

public static void writeCN() throws Exception {

//创建与文件关联的字节输出流对象

FileOutputStream fos = new FileOutputStream("c:\\cn8.txt");

//创建可以把字符转成字节的转换流对象,并指定编码

OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");

//调用转换流,把文字写出去,其实是写到转换流的缓冲区中

osw.write("你好");//写入缓冲区。

osw.close();

}


打印流

PrintWriter

package com.qfedu.bhy.test_printwriter;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * 	打印流输出异常日志信息
 * @author bhy
 *
 */
public class MyException extends Exception{
	
	//设置异常信息
		public String getMessage() {
			
			return "异常信息--打印异常日志";
		}
	//定义异常时执行的方法
	public void printException() {
		
		PrintWriter pw = null;
		FileWriter fw = null;
		try {
			fw = new FileWriter("F:/print.txt",true);//true:文件不覆盖
			pw = new PrintWriter(fw);
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			
			this.printStackTrace(pw);//this.printStackTrace(PrintWriter s);  写出当前异常信息到指定打印流中
			pw.print(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss")
					.format(new Date())+"\r\n");//追加时间信息到打印流中
			//关闭流
			if(fw!=null) {
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(pw!=null) {
				pw.close();
			}
		}
	}

}

附上自定义异常使用代码

package com.qfedu.bhy.test_printwriter;

public class TestPrintWriter {

	public static void main(String[] args){
		
		try {   /捕获异常
			print();
		} catch (MyException e) {   //处理异常
			e.printException();//调用自定义异常的异常处理方法
		}
	}
	public static int print()throws MyException{//声明异常
		
		int[] arr = new int[] {1,4,0,3};
		int n = 0 ;

		for (int i = 0; i < arr.length+1; i++) {
			if(i > arr.length-1 || arr[i] == 0) {
				throw new MyException();//抛出自定义异常对象
			}else {
				n = arr[i+1]/arr[i];
			}	
		}
		return n;
	}

}


对象流

  • ObjectInputStream
  • ObjectOutputStream

对象流–实现序列化:

import java.io.*;
class ObjectStreamDemo {
	public static void main(String[] args) throws Exception{
		writeObj();
		readObj();
	}
	public static void readObj()throws Exception{
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
		Object obj = ois.readObject();//读取一个对象。
		System.out.println(obj.toString());
	}
	public static void writeObj()throws IOException{
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
		oos.writeObject(new Person("lisi",25)); //写入一个对象。
		oos.close();
	}
}
class Person implements Serializable{
	private static final long serialVersionUID = 42L;//生成一个序列化ID号
	private transient String name;//用transient修饰后name将不会进行序列化
	public int age;
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String toString(){
		return name+"::"+age;
	}
}

猜你喜欢

转载自blog.csdn.net/LittleBlackyoyoyo/article/details/83187221