java高级之IO流

java高级之IO流与应用

java基础部分的学习已经结束,回顾java基础学习过程中,个人觉得最重要的莫过于掌握java面向对象的设计思维,以及Java的三大特征:封装、继承、多态的理解和使用,还有常用类的使用,有扎实的基础才能更好的向高级知识迈进,下面介绍java高级的第一个知识——IO流

流的定义

流(IO),在计算机系统中,将不同的输入输出源统一抽象为流,流是一种实现数据交换技术的核心,比较常见的流的使用在于:文件操作,网络数据传输等;流由两大核心部分构成:1.Input(输入),2.Output(输出);通俗的理解为人的嘴(输出)和耳朵(输入),对流的使用就分为两种操作:读和写;java中所有有关流的类都来自于java.io包。

流的分类

java-IO将流分为几种类别:

  1. 按流向分为:输入和输出
  2. 按类型分为:字节和字符
  3. 按功能分为:节点流和处理流

常见流的分类详情:

 层次结构图:

 

字节流

所谓字节流,其实就是将数据以字节为单位进行读写相关操作,字节流一般用于对于一些二进制文件(图片,音频,视频等)进行读写操作,java中的字节流都是来自以下两个抽象类:

  1. InputStream(字节输入流)
  2. OutputStream(字节输出流)

InputStream类

inputStream类是所有字节输入流的父类,是一个抽象类,常用方法包含以下:

  • available( ):获取当前流中的可读字节数
  • close( ):关闭此流
  • read( ):从流中读取一个字节,返回读取到的字节
  • read(byte[ ] b):将流中读取到的字节存入到指定的字节数组中,返回真实读取的长度,读取不到返回-1
  • read(byte[ ] b,int offset,int len):将流中读取奥的字节存入到指定的字节数组中(跳过offset个字节存储,存储长度为len),读取不到返回-1

InputStream类的常见子类有FileInputStream,ByteArrayInputStream,ObjectInputStream,FilterInputStream等,

以FileInputStream类为例:

public class ReadFileDemo {

	public static void main(String[] args) throws IOException {		
		//创建File对象
		File f = new File("C:\\Users\\Desktop\\a.txt");
		//基于File对象创建文件字节输入流
		FileInputStream fis = new FileInputStream(f);
		//获取当前输入流的可读字节数
		int len = fis.available();
		//获取文件对象的可读字节数
		byte[] b = new byte[len];
		fis.read(b);		
		System.out.println(new String(b)); 
	}
}

 通过以上代码看出可以根据流中有效字节长度创建字节数组,在下一次读取时,直接将所有读取的内容存储到数组中,但是如果流中数据过大,将会需要消耗大量空间存储,考虑到空间的限制,一般不会一次性读完,而是采用循环的方式每次读取固定长度的数据并缓存到字节数组中,以减少内存空间的消耗,以上程序修改后,如下:

public class ReadFileDemo2 {

	public static void main(String[] args) throws IOException {
		//创建File对象
		File f = new File("C:\\Users\\Desktop\\a.txt");
		//基于File对象创建文件字节输入流
		FileInputStream fis = new FileInputStream(f);
	
		//声明一个指定长度的字节缓冲区(太大会消耗大量运行时内存)
		byte[] b = new byte[1024];
		//声明临时变量用于存储每次读取的字节的真实长度
		int len = 0;
        //循环读取
		while((len = fis.read(b)) != -1){
			String s = new String(b,0,len);
			System.out.println(s);
		}
		fis.close();
	}

}

 

OutputStream类

OutputStream类是所有字节输出流的父类,是一个抽象类,常用方法如下:

  • write(byte[] b):将字节数组中的内容写入输出源(文件,网络,内存)
  • write(byte[] b,int offset,int len):将字节数组中的内容从offset开始写入len长到输出源
  • write(int b):将一个字节写入输出源
  • flush():将流中的数据强制刷新到输出源
  • close():关闭此流

OutputStream类的常见子类有FileOutputStream,ByteArrayOutputStream,ObjectOutputStream,FilterOutputStream等,

以FileOutputStream类为例:

public class WriteFileDemo {
	public static void main(String[] args) throws IOException {
		//准备目标文件对象
		File file = new File("C:\\Users\\Desktop\\a.txt");
		//创建一个基于目标文件的字节输出流
		FileOutputStream fos = new FileOutputStream(file,true);
		
		String msg = "床前明月光,疑似地上霜!";
		//将需要通过输出流输出的内容转换为字节数组并输出
		fos.write(msg.getBytes()); 
		//关闭资源
		fos.close();
	}
}

 

文件拷贝

通过以上字节流(输入输出)的使用,可以实现系统中的文件拷贝功能,文件拷贝原理即:获取源文件的输入流,获取目标文件的输入流,通过读取输入流中的数据并写入输出流中,如下:

 

public class FileCopy {
	/**
	 * 将源文件拷贝到目标目录中
	 * @param sourceFile 源文件(标准文件)
	 * @param targetDir 目标目录(目录)
	 */
	public void copy(File sourceFile,File targetDir){
		FileInputStream fis = null;
		FileOutputStream fos = null;
	
		try {
			//获取源文件的输入流
			fis = new FileInputStream(sourceFile);
			//获取目标文件的输出流
			fos = new FileOutputStream(new File(targetDir,sourceFile.getName()));
			//声明字节缓冲区
			byte[] b = new byte[1024];
			//声明变量存储真实读取长度
			int len = 0;
			//循环读取以及写入
			while((len = fis.read(b)) != -1){
				fos.write(b,0,len); 
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
                //关闭资源
				if(fos != null){
					fos.close();
				}
				if(fis != null){
					fis.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
			
	}
	
	public static void main(String[] args) {
		File source = new File("D:\\素材\\视频\\larva搞笑虫子\\35.avi");
		File target = new File("C:\\Users\\Desktop");
		new FileCopy().copy(source, target); 
	}
	
}

字符流

字符流,顾名思义,是以字符的形式对输入输出源操作,通常情况下一个字符表示两个字节,但是在一些unicode编码,如UTF-8则使用3个字节表示,但是由于字符流的特殊性,一般用字符流主要操作一些文本输入输出源(文本文档,记事本文件等字符数据);java中所有的字符流都从以下两个抽象类继承:

  1. Reader 字符输入流

  2. Writer 字符输出流

Reader

字符输入流,是所有字符输入流的父类,是一个抽象类,内部的常见方法如下:

  • read():读取并返回一个字符
  • read(char[] c):将从流中读取的字符存储到字符数组
  • read(char[] c,int offset,int len):将从流中读取的字符存入字符数组(跳过offset个字节,写入len长)
  • ready():返回此流是否准备好被读取的状态
  • close():关闭此流

Reader类的常见子类包含:InputStreamReader,BufferedReader,FilterReader,PipedReader等,常见的间接子类有FileReader,使用如下:

public class ReaderDemo1 {

	public static void main(String[] args) throws IOException {
		
		File f = new File("C:\\Users\\3.txt");
		//根据给定的文件对象构建一个文件字符输入流对象
		FileReader fr = new FileReader(f);
		
//		System.out.println(fr.ready());
//		int i = fr.read();
//		System.out.println((char)i);
		
		char[] c = new char[512];
		int len = 0;
		while((len = fr.read(c)) != -1){
			String s = new String(c,0,len);
			System.out.println(s);
		}
		
	}

}

Writer

字符输出流,是所有字符输出流的父类,是一个抽象类,内部的常见方法如下:

  • append(char c):向流中追加一个字符
  • append(CharSequence c):向流中追加一个字符序列(字符串)
  • witer(String s):写入一个字符串到目标输出源
  • witer(char[] c):写入字符数组到目标输出源

Writer类的常见子类包含:OutStreamReader,BufferedWriter,FilterWriter,PipedWriter等,常见的间接子类有FileWriter,使用如下:

public class WriteDemo {

	public static void main(String[] args) throws IOException {
		
		File f = new File("C:\\Users\\Desktop\\test.txt");
		//获取文件的字符输出流,使用追加模式
		FileWriter fw = new FileWriter(f,true);	
		fw.write("飞流直下三千尺,疑是银河落九天");
		
		//使用字符流执行写入操作时,由于内置的字符缓冲区可能不能及时将内容输出
		//因此,需要手动调用flush强制将内容通过输出流输出或者执行close
//		fw.flush();
		fw.close();
	}
}

 

转换流、缓冲流打印流

​ 由于以上所提到的流,按照功能来说都属于节点流(直接跟输入输出源打交道),而在实际开发中有些需求可能会涉及到需要将字节流转换为字符流,或者将字符流转换为字节流等一些转换操作;另外也有可能需要将这些低级的节点流提高读取和写入效率,因此还需要一些高级流来进行处理,因此这些高级流也被称之为处理流,比如:转换流,缓冲流,打印流等。

转换流

java-io中的转换流主要分为两个:

  • InputStreamReader:将字节流转换为字符流的桥梁
  • OutputStreamWriter:将字符流转换为字节流的桥梁

缓冲流

缓冲流的出现主要为了提高节点流的读取和写入效率,使用方式通常为将其他节点流包装起来,io包中的缓冲流分为以下几个:

  • BufferedReader
  • BufferedWriter
  • BufferedInputStream
  • BufferedOutputStream

转换流&缓冲流综合使用1

public class StreamDemo {

	public static void main(String[] args) throws IOException {
		//获取标准输入流
		InputStream is = System.in;
		//将字节流转换为字符流(装饰器模式)  gbk  utf-8   gb2312  gb18030
		InputStreamReader isr = new InputStreamReader(is,"gbk");
		//将低级字符流转换为高级字符缓冲流
		BufferedReader br = new BufferedReader(isr);
		
		String s = br.readLine();
		System.out.println(s);
	}
}

转换流&缓冲流综合使用2

public class StreamDemo3 {
	public static void main(String[] args) throws IOException {
		String msg = "你好世界";
		OutputStream os = System.out;
		//将字符流转字节流的桥梁
		OutputStreamWriter osw = new OutputStreamWriter(os);
		//将低级字符输出流转换为缓冲流
		BufferedWriter bw = new BufferedWriter(osw);
		bw.write(msg);
		bw.close();

	}
}

打印流

另外在IO包中还提供了两个特殊的流,这两个流只有输出,没有输入:

  • PrintStream 字节打印流
  • PrintWriter 字符打印流

打印流通常可以对其他输出流(Writer,OutputStream)以及文件(File)进行包装,然后通过提供的相关API操作这些流,常见构造器:

  1. PrintStream
  • PrintStream(File file)
  • PrintStream(String fileName)
  • PrintStream(OutputStream os)
  • PrintStream(OutputStream os,boolean autoFlush)
  1. PrintWriter
  • PrintWriter(File file)
  • PrintWriter(String fileName)
  • PrintWriter(OutputStream os)
  • PrintWriter(OutputStream os,boolean autoFlush)
  • PrintWriter(Writer w )
  • PrintWriter(Writer w,boolean autoFlush)

使用如下:

public class PrintDemo {

	public static void main(String[] args) throws FileNotFoundException {
		//创建文件字节输出流(追加模式)
		OutputStream os = new FileOutputStream("C:\\Users\\Desktop\\test.txt",true);
		
//		PrintStream ps = new PrintStream(os);
//		ps.println("谁知盘中餐");
		
		PrintWriter pw = new PrintWriter(os,true);
		pw.println("粒粒皆辛苦");
//		pw.flush();
		
	}
}

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值