Java IO

1. Java 流式输入/输出原理

Java 程序中,对于数据的输入/输出操作以 “流” ( stream )方式进行;输入流指向称为它的源,输出流的指向称为它的目的地;虽然 I/O 流经常与磁盘文件存取有关,但是源和目的地也可以是·键盘、内存或显示器窗口。
在这里插入图片描述
注意: 输入流虽然指向源,但是输入流的功能是从源中获取数据,也就是一个拉取数据的过程。输出流虽然指向目标,是将数据写入到目标,是一个推送数据的过程。

1.2 输入/输出流的分类

  • java.io 包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同的角度对其进行分类:
    • 按数据流的方向不同可以分为输入流和输出流。(在程序角度)
    • 按处理数据单位不同可以分为字节流和字符流。
    • 按照功能不同可以分为节点流和处理流。
  • java.io 包( I/O 流库)提供大量的流类,分别继承自以下四种抽象类型
字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

在这里插入图片描述

1.3 节点流和处理流

  • 节点流为可以从特定一个的数据源(节点)读写数据(如:文件,内存)
  • 处理流是 “连接” 在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。

1.4 InputStream

继承自 InputStream 的流都是用于向程序中输入数据,且数据的单位为字节(8 bit );下图中红色框内为节点流,其余为处理流。
在这里插入图片描述
基本方法

//读取一个字节并以整数的形式返回( 0~255 ),
//如果返回 -1 已到输入流的末尾。
int read() throws IOException

//读取一系列字节并存储到一个数组 buffer,
//返回实际读取的字节数,如果读取前已到输入流的末尾返回 -1
int read(byte[] buffer) throws IOException

//读取 length 个字节
//并存储到一个字节数组 buffer ,从 offset 位置开始 
//返回实际读取的字节数,如果读取前已到输入流的末尾返回 -1
int read(byte[] buffer,int offset,int length) throws IOException

//关闭流释放内存资源
void close() throws IOException

1.5 OutputStream

继承自 OutputStream 的流是用于程序中输入数据,且数据的单位为字节(8 bit );下图中红色框内为节点流,其他为处理流。
在这里插入图片描述
基本方法

//向输出流中写入一个字节数据,该字节数据为参数 b 的低 8 位
void write(int b) throws IOException

//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException

//将一个字节类型的数组中的从指定位置( off )开始的
// len 个字节写入到输出流
void write(byte[] b,int off,int len) throws IOException

//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
//尽量先写 flush() ,再写 close()

1.6 Reader

继承自 Reader 的流都是用于向程序中输入数据,且数据的单位为字符( 16 bit );下图中红色框内为节点流,其余为处理流。
在这里插入图片描述
基本方法

//读取一个字符并以整数的形式返回(0~225),
//如果返回 -1 已到输入流的末尾
int read() throws IOException

//读取一系列字符并存储到一个数组 buffer
//返回实际读取的字符数,如果读取前已到输入流的末尾返回 -1
int read(char[] cbuf) throws IOException

//读取 length 个字符
//并存储到一个数组 buffer ,从 offset 位置开始
//返回实际读取的字符数,如果读取前已到输入流末尾返回 -1
int read(char[] cbuf,int offset,int length) throws IOException

//关闭流释放内存资源
void close() throws IOException

1.7 Writer

继承自 Writer 的流都是用于程序中输出数据,且数据的单位为字符(16 bit );下图中红色框内为节点流,其余为处理流。
在这里插入图片描述
基本方法

//向输出流中写入一个字符数据,该字节数据为参数 b 的低 16 位
void write(int b) throws IOException

//将一个字符类型的数组中的数据写入输出流
void write(char[] cbuf) throws IOException

//将一个字符类型的数组中的从指定位置( offset )开始的
//length 个字符写入到输出流
void write(char[] cbuf,int offset,int length) throws IOException

//关闭流释放内存资源
void close() throws IOException

//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException

2. 节点流类型

在这里插入图片描述

2.1 访问文件

2.1.1 FileInputStream 和 FileOutputStream

FileInputStreamFileOutputStream 分别继承自 InputStreamOutputStream 用于向文件中输入和输出字节。

import java.io.*;
public class TestFileInputStream{
	public static void main(String[] args) {
		int b = 0;
		FileInputStream in = null;
		try {
			in = new FileInputStream("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\TestFileInputStream.java");
		} catch (FileNotFoundException e) {
			System.out.println("找不到指定文件");
			System.exit(-1);
		}
		
		try {
			long num = 0;
			while((b=in.read())!=-1) {
				System.out.print((char)b);
				//汉字输出为乱码,因为汉字以两个字节存储
				num++;
			}
			in.close();
			System.out.println();
			System.out.println("共读取了"+num+"个字节");
		} catch (IOException e1){
			System.out.println("文件读取错误");
			System.exit(-1);
		}
	}
}
import java.io.*;
public class TestFileOutputStream{
	public static void main(String[] args) {
		int b = 0;
		FileInputStream in = null;
		FileOutputStream out = null;
		try {
			in = new FileInputStream("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\Hello.java");
			out = new FileOutputStream("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\HE.java");
			//可自动创建文件
			while((b=in.read())!=-1) {
				out.write(b);
			}
			in.close();
			out.close();
			//注意两个文件都要关闭
		}catch (FileNotFoundException e2) {
			System.out.println("找不到指定文件");
			System.exit(-1);
		}catch (IOException e1) {
			System.out.println("文件复制错误");
			System.exit(-1);
		}
		System.out.println("文件已复制");
	}
}

2.1.2 FileReader 和 FileWriter

import java.io.*;
public class TestFileReader{
	public static void main(String[] args) {
		FileReader fr = null;
		int c = 0;
		try {
			fr = new FileReader("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\TestFileReader.java");
			while((c=fr.read())!=-1) {
				System.out.print((char)c);
				//汉字可正常输出
			}
			fr.close();
		}catch (FileNotFoundException e) {
			System.out.println("找不到指定文件");
		}catch (IOException e) {
			System.out.println("文件读取错误");
		}
	}
}
import java.io.*;
public class TestFileWriter{
	public static void main(String[] args) {
		FileWriter fw = null;
		try {
			fw = new FileWriter("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\unicode.txt");
			//可自动创建
			for(int c=0;c<50000;c++) {
				fw.write(c);
			}
			fw.close();
		}catch (IOException e1) {
			e1.printStackTrace();
			System.out.println("文件写入错误");
			System.exit(-1);
		}
	}
}

3. 处理流类型

处理流把另一个流对象作为参数
在这里插入图片描述

3.1 缓冲流

  • 缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,减少读入次数,提高了读写的效率,保护硬盘,同时增加了一些新的方法。
  • 对于输出的缓冲流,写出的数据会先在内存中缓存,使用 flush 方法将会使内存中的数据立刻写出。

3.1.1 Buffering

readLine()

import java.io.*;
public class TestBufferStream1{
	public static void main(String[] args) {
		try {
			FileInputStream fis = 
					new FileInputStream("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\Hello.java");
			BufferedInputStream bis = 
					new BufferedInputStream(fis);
			int c = 0;
			System.out.println(bis.read());
			System.out.println(bis.read());
			for(int i=0;i<=10 && (c=bis.read())!=-1;i++) {
				System.out.print(c+" ");
			}
			System.out.println();
			bis.close();
		} catch (IOException e) {
			e.printStackTrace();
		} 
	}
}
import java.io.*;
public class TestBufferStream2{
	public static void main(String[] args) {
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\dat2.txt"));
			BufferedReader br = new BufferedReader(
					new FileReader("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\dat2.txt"));
			String s = null;
			for(int i=1;i<=100;i++) {
				s = String.valueOf(Math.random());
				//产生一个随机数并转换成字符串
				bw.write(s);
				bw.newLine();//换行
			}
			bw.flush();
			while((s=br.readLine())!=null) {//读取一行
				System.out.println(s);
			}
			bw.close();
			br.close();
		} catch (IOException e){
			e.printStackTrace();
		}
	}
}

3.2 转换流

字节流与字符流的转换

import java.io.*;
public class TestTransForm1{
	public static void main(String[] args) {
		try {
			OutputStreamWriter osw = new OutputStreamWriter(
					new FileOutputStream("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\char.txt"));
			osw.write("bluemsun");
			System.out.println(osw.getEncoding());
			//返回字符编码
			osw.close();
			osw = new OutputStreamWriter(
					new FileOutputStream("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\char.txt",true),
					//true表示在原有基础上添加,不加则为替换
					"ISO8859_1");
					//按照规定的字符编码写入
			osw.write("bluemsun");
			System.out.println(osw.getEncoding());
			osw.close();
		} catch (IOException e){
			e.printStackTrace();
		}
	}
}
import java.io.*;
public class TestTransForm2{
	public static void main(String[] args) {
		InputStreamReader isr = 
				new InputStreamReader(System.in);
				//阻塞,等待键盘输入
		BufferedReader br = new BufferedReader(isr);
		String s = null;
		try {
			s = br.readLine();
			while(s!=null) {
				if(s.equalsIgnoreCase("exit"))break;
				System.out.println(s.toUpperCase());
				s = br.readLine();			
		   }
		   br.close();
	    } catch (IOException e) {
		    e.printStackTrace();
	      }
	}
}

3.3 数据流

  • DataInputStreamDateOutputStream 分别继承自 InputStreamOutputStream,它属于处理流,需要分别“套接”在 INpurStreamOutputStream 类型的节点流上。
  • DataInputStreamDateOutputStream 提供了可以存取与机器无关的 Java 原始类型数据的方法。

3.3.1 DataIO 和 ByteArrayIO

import java.io.*;
public class TestDataStream{
	public static void main(String[] args) {
		ByteArrayOutputStream baos = 
				new ByteArrayOutputStream();
				//创建字节数组
		DataOutputStream dos = 
				new DataOutputStream(baos);
				//套接
		try {
			dos.writeDouble(Math.random());
			//8个字节
			dos.writeBoolean(true);
			//1个字节
			ByteArrayInputStream bais =
					new ByteArrayInputStream(baos.toByteArray());
					//转换成字节数组
			System.out.println(bais.available());
			//有多少个字节
			DataInputStream dis = new DataInputStream(bais);
			//套接
			System.out.println(dis.readDouble());
			//先写先读,先进先出
			System.out.println(dis.readBoolean());
			dos.close();
			dis.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

3.4 Print流

  • PrintWriterPrintStream 都属于输出流,分别针对字符和字节
  • PrintWriterPrintStream 提供了重载的 print
  • Println 方法用于多种数据类型的输出
  • PrintWriterPrintStream 的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
  • PrintWriterPrintStream 有自动 flush 功能
import java.io.*;
public class TestDataStream{
	public static void main(String[] args) {
		PrintStream ps = null;
		try {
			FileOutputStream fos = 
					new FileOutputStream("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\log.txt");
			ps = new PrintStream(fos);
			//套接
		} catch (IOException e) {
			e.printStackTrace();
		}
		if(ps != null) {
			System.setOut(ps);
			//输出到 ps
		}
		int ln = 0;
		for(char c=0;c<=60000;c++) {
			System.out.print(c+" ");
			if(ln++>=100) {
				System.out.println();
				ln=0;
			}
		}
	}
}

3.5 Object流

  • 直接在 Object 写入或读入
    • TestObjectIO.java
    • transient 关键字
    • serializable 接口(序列化,不用考虑如何序列)
    • externalizable 接口(自己控制如何序列化)
import java.io.*;
public class TestObjectIO{
	public static void main(String[] args) throws Exception {
		T t = new T();
		t.k = 8;
		FileOutputStream fos = new FileOutputStream("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\testobjectio.txt");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		//套接
		oos.writeObject(t);
		oos.flush();
		oos.close();
		
		FileInputStream fis = new FileInputStream("C:\\Users\\LENOVO\\eclipse-workspace\\text\\src\\text\\testobjectio.txt");
		ObjectInputStream ois = new ObjectInputStream(fis);
		//套接
		T tReaded = (T)ois.readObject();
		//读入并分解
		System.out.println(tReaded.i+" "+tReaded.j+" "+tReaded.d+" "+tReaded.k);
  }
}

class T implements Serializable{
	int i = 10;
	int j = 9;
	double d =2.3;
	int k = 15;
	//transient int k = 15;序列化时不考虑,输出 k 为 0
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值