Java从入门到精通_学习笔记16(I/O)

流概述

流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种。 I/O(Input/Output,输入/输出)流提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。虽然I/O流通常与磁盘文件存取有关,但是程序的源和目的地也可以是键盘、鼠标、内存或显示器窗口等。


Java由数据流处理输入/输出模式,程序从指向源的输入流中读取源中的数据,源可以是文件、网络、压缩包或其他数据源;输出流的指向是数据要到达的目的地,程序通过向输出流中写入数据把信息传递到目的地,输出流的目标可以是文件、网络、压缩包、控制台和其他数据输出目标。

输入/输出流

Java语言定义了许多类专门负责各种方式的输入/输出,这些类都被放在java.io包中。其中,所有输入流类都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流) 的子类;而所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流) 的子类。

1.输入流(读)

InputStream类是字节输入流的抽象类,是所有字节输入流的父类。

在这里插入图片描述


InputStream类中的常用方法:

  • read()方法:从输入流中读取数据的下一个字节。返回0~255范围内的int字节值。如果因为已经到达流末尾而没有可用的字节,则返回值为-1。
  • read(byte[ ] b):从输入流中读入一定长度的字节,并以整数的形式返回字节数。
  • mark(int readlimit)方法:在输入流的当前位置放置一个标记,readlimit参数告知此输入流在标记位置失效之前允许读取的字节数。
  • reset()方法:将输入指针返回到当前所做的标记处。
  • skip(long n)方法:跳过输入流上的n个字节并返回实际跳过的字节数。
  • markSupported()方法:如果当前流支持mark()/reset()操作就返回true。
  • close方法:关闭此输入流并释放与该流关联的所有系统资源

注:

  • 不是所有的InputStream类的子类都支持InputStream中定义的所有方法,如skip()、mark()、reset()等方法只对某些子类有用。
  • 该类中所有方法遇到错误时都会引发IOException异常。

Reader类是Java为字符文本输入专门提供的一个输入流类,但Render不是InputStream类的替换者,相比于InputStream类,Reader类简化了处理字符串的编程(Java中字符串是Unicode编码,是双字节的)

在这里插入图片描述


注:Reader类中的方法与InputStream类相类似

2. 输出流(写)

OutputStream类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。
在这里插入图片描述

OutputStream类中常用的方法:

  • write(int b)方法:将指定的字节写入此输出流。
  • write(byte[ ] b)方法:将b个字节从指定的byte数组写入此输出流。
  • write(byte[ ] b,int off,int len)方法:将指定byte数组中从偏移量off开始的len个字节写入此输出流。
  • flush()方法:彻底完成输出并清空缓存区。
  • close()方法:关闭输出流。

注:

  • OutputStream类中的所有方法均返回void,在遇到错误时会引发IOException异常。

Writer类是Java为字符串输出专门提供的一个类,方便字符串输出的编程。 Writer类是字符输出流的抽象类,所有字符输出类的实现都是它的子类。
在这里插入图片描述


注:Writer类中的方法与OutputStream类中方法类似。

File类

File类是java.io包中唯一代表磁盘文件本身的对象。 File类定义了一些与平台无关的方法来操作文件,可以通过调用File类中的方法,实现创建删除重命名文件等操作。File类的对象主要用来获取文件本身的一些信息,如文件所在的目录、文件的长度、文件读写权限等。数据流可以将数据写入到文件中,文件也是数据流最常用的数据媒体。

1.文件的创建与删除

File类创建文件对象时常用的构造方法:

  • File(String pathname):给定路径名字符串转换为抽象路径名来创建一个新File实例。
  • File(String parent,String child):根据定义的父路径和子路径字符串(包含文件名)创建一个新的File对象。
  • File(File f , String child):根据parent抽象路径名和child路径名字符串创建一个新File实例。

代码演示:

public class FileTest {
	public static void main(String args[]){
		File file = new File(word.txt); // 实例化一个文件对象
		if(file.exists()) { // 判断文件是否存在
			file.delete(); // 删除文件
			System.out.println("文件已删除");
		}else {
			try{ // 处理可能会出现的IOException异常
				file.createNewFile();
				System.out.println("文件已创建");
			}catch(IOException e) {
				e.printStackTrace();
			}
		}
	}	
}

2. 获取文件信息

在这里插入图片描述


代码演示:

public class FileTest {
	public static void main(String args[]){
		File file = new File("word.txt"); 
		if(file.exists()) {
			String name = file.getName(); // 获取文件名称
			long length = file.length(); // 获取文件长度
			boolean hidden = file.isHidden(); // 判断文件是否为隐藏文件
			System.out.println("文件名称:" + name);
			System.out.println("文件长度:" + length);
			System.out.println("该文件是否隐藏文件:" + hidden);
		}else {
			System.out.println("该文件不存在");
		}
	}	
}

文件输入/输出流

程序运行期间,大部分数据都在内存中进行操作,==当程序结束或关闭时,这些数据将消失。==如果需要将数据永久保存,可使用文件输入/输出流与指定的文件建立连接,将需要的数据永久保存到文件中

1. FileInputStream与FileOutputStream类

FileInputStream类与FileOutputStream类都用来操作磁盘文件。,该类继承自InputStream类。FileOutputStream类与FileInputStream类对应,提供了基本的文件写入能力。FileOutputStream类是OutputStream类的子类。


FileInputStream类常用的构造方法:

  • FileInputStream(String name)
  • FileInputStream(File file)

FileOutputStream类常用的构造方法:

  • FileOutputStream(String name)
  • FileOutputStream(File file)

代码演示:

public class Test {
	public static void main(String args[]){
		File file = new File("word.txt");	
		try {
			FileOutputStream out = new FileOutputStream(file);
			byte buy[] = "我有一只小毛驴,我从来都不骑。".getBytes();
			out.write(buy);
			out.close();
		} catch(Exception e) {
			e.printStackTrace();
		}
		
		tyr{
			// 创建FileInputStream对象
			FileInputStream in = new FileInputStream(file);
			byte buyt[] = new byte[1024]; // 创建byte数组
			int len = in.read(byt);  // 从文件中独去读取信息
			System.out.println("文件中的信息是:" + new String(byt , 0 , len)); // 使用String的构造方法将字节数组转换成字符串,然后输出
			in.close(); // 关闭流
		} catch(Exception e) {
			e.printStackTrace();
		}
	}	
}

注:

  • 使用完流后,显式地关闭所有打开的流是一个好习惯。
  • 使用FileOutputStream类向文件中写入数据与使用FileInputStream类从文件中将内容读出来,都存在一点不足,即这两个类都只提供了对字节或字节数组的读取方法。由于汉字在文件中占用两个字节,如果使用字节流,读取不好可能会出现乱码现象,此时采用字符流Reader或Writer类即可避免这种现象。

2. FileReader和FileWriter类

FileReader和FileWriter字符流对应了FileInputStream和FileOutputStream类。FileReader流顺序地读取文件,只要不关闭流,每次调用read()方法就顺序地读取源中其余的内容,直到源的末尾或流被关闭。


FileReader类常用的构造方法:

  • FileReader(String name)
  • FileReader(File file)

FileWriter类常用的构造方法:

  • FileWriter(String name)
  • FileWriter(File file)

带缓存的输入/输出流

缓存是I/O的一种性能优化。缓存流为I/O流增加了内存缓存区。 有了缓存区,使得在流上执行skip()、mark()和reset()方法都成为可能。

1. BufferedInputStream与BufferedOutputStream类

BufferedInputStream类可以对所有InputStream类进行带缓存区的包装以达到性能的优化。


BufferedInputStream类有两个构造方法:

  • BufferedInputStream(InputStream in) : 法创建了一个带有32个字节的缓存流
  • BufferedInputStream(InputStream in,int size) : 按指定的大小来创建缓存区

在这里插入图片描述


BufferedOutputStream类有两个构造方法:

  • BufferedOutputStream(OutputStream in) : 法创建了一个带有32个字节的缓存区
  • BufferedOutputStream(OutputStream in,int size) : 按指定的大小来创建缓存区

注:

  • flush()方法就是用于即使在缓存区没有满的情况下,也将缓存区的内容强制写入到外设,习惯上称这个过程为刷新。
  • 当调用close()方法时,系统在关闭流之前,也会将缓存区中的信息刷新到磁盘文件中。

2. BufferedReader与BufferedWriter类

BufferedReader类与BufferedWriter类分别继承Reader类与Writer类。 这两个类同样具有内部缓存机制,并可以以行为单位进行输入/输出。


BufferedReader类有两个构造方法:

  • BufferedReader(Reader read)

BufferedWriter类有两个构造方法:

  • BufferedWriter(Writer writer)
    在这里插入图片描述

BufferedReader类中常用的方法:

  • read()方法:读取单个字符。
  • readLine()方法:读取一个文本行,并将其返回为字符串。若无数据可读,则返回null。

BufferedWriter类中的常用的方法:

  • write(String s, int off, int len)方法:写入字符串的某一部分。
  • flush()方法:刷新该流的缓存。
  • newLine()方法:写入一个行分隔符。
public class Student {
	public static void main(String args[]){
		String content[] = {"好久不见" , "最近好吗" , "常联系"}; // 定义字符串数组
		File file = new File("word.txt"); // 实例化一个File类
		try { 
			FileWriter fw = new FileWriter(file); // 实例化一个FileWriter类
			BufferedWriter bfw = new BufferedWriter(fw); // 通过FileWriter类对象实例化一个BufferedWriter类
			for(int k = 0 ; k < content.length ; k++) { /
				bfw.write(content[k]); / 将数组里的字符串元素写入到文件中
				bfw.newLine(); // 写入一个换行符到文件中
			}
			bfw.close(); // 关闭BufferedWriter流,释放资源
			fw.close(); // 关闭FlieWriter流,释放资源
		}catch(Exception e) {
			e.printStackTrace();
		}
	
		try{
			FileReader fr = new FileReader(file); // 实例化一个FileReader对象
			BufferedReader bfr = new BufferedReader(fr); // 通过FileReader对象实例化一个BufferedReader对象
			String str = null; // 定义一个字符串,初始设置值为null
			int i = 0; 
			// 如果文件的文本行数不为null,则进入循环
			while((str = bfr.readLine()) != null) { // 每次循环读取文件中的一行赋值给str
				i++;
				System.out.println("第" + i + "行 : " + str);
			}
			bfr.close(); // 关闭BufferedReader流,释放资源
			fr.close(); // 关闭FileReader流,释放资源
		}catch(Exception e) {
			e.printStackTrace();
		}
	}	
}

数据输入/输出流

数据输入/输出流(DataInputStream类与DataOutputStream类)允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型。也就是说,当读取一个数据时,不必再关心这个数值应当是哪种字节。


DataInputStream类的构造方法:

  • DataInputStream(InputStream in):使用指定的基础InputStream创建一个DataInputStream

DataOutputStream类的构造方法:

  • DataOutputStream(OutputStream out):创建一个新的数据输出流,将数据写入指定基础输出流

DataOutputStream类提供了如下3种写入字符串的方法:

  • writeBytes(String s)
  • writeChars(String s)
  • writeUTF(String s)

DataInputStream类只提供了一个readUTF()方法返回字符串


代码演示:

public class Example{
	public static void main(String args[]){
		try{
			FileOutputStream fs = new FileOutputStream("word.txt"); // 实例化FileOutputStream对象
			DataOutputStream ds = new DataOutputStream(fs); // 通过FileOutputStream对象实例化DataOutputStream对象
		
			// 写入磁盘文件数据	
			ds.writeUTF("使用writeUTF()方法写入数据"); 
			ds.writeChars("使用writeChars()方法写入数据");	
			ds.writeBytes("使用writeBytes()方法写入数据");
			
			// 关闭流,释放资源
			ds.close();
			fs.close();
			
			FileInputStream fis = new FileInputStream("word.txt"); // 实例化FileInputStream对象
			DataInputStream dis = new DataInputStream(fis); // 通过FileInputStream对象实例化DataInputStream对象
			
			// 读取磁盘文件数据并输出
			System.out.println(dis.readUTF()); 
		}catch(Exception e) {
			e.printStackTrace();
		}
	}	
}

ZIP压缩输入/输出流

ZIP压缩管理文件(ZIP archive) 是一种十分典型的文件压缩形式,使用它可以节省存储空间。Java实现了I/O数据流与网络数据流的单一接口,因此数据的压缩、网络传输和解压缩的实现比较容易;在Java中使用java.util.zip包中的ZipOutputStream与ZipInputStream类来实现文件的压缩/解压缩;ZipEntry类产生的对象,是用来代表一个ZIP压缩文件内的进入点(entry)。ZipInputStream类用来读取ZIP压缩格式的文件,所支持的包括已压缩及未压缩的进入点(entry)。ZipOutputStream类用来写出ZIP压缩格式的文件,而且所支持的包括已压缩及未压缩的进入点(entry)。

1. 压缩文件

利用ZipOutputStream类对象,可将文件压缩为.zip文件


ZipOutputStream类的构造方法如下:

  • ZipOutputStream(OutputStream out);

ZipOutputStream类的常用方法:
在这里插入图片描述


代码演示:

import java.util.*;
	
public class MyZip{
	private void zip(String zipFileName , File inputFile) throws Exception{
		ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
		zip(out , inputFile , "");
		System.out.println("压缩中...");
		out.close();
	}	
	
	private void zip(ZipOutputStream out , File f , String base) throws Exception {
		if(f.isDirectory()) {
			File fl[] = f.listFiles();
			if(base.length() != 0){
				out.putNextEntry(new ZipEntry(base + "/"));
			}
			for(int i = 0 ; i < fl.length ; i++) {
				zip(out , fl[i] ; base + f[i]);
			}
		}else {
			out.putNextEntry(new ZipEntry(base));
			FileInputStream in = new FileInputStream(f);
			int b;
			System.out.println(base);
			while((b = in.read()) != -1) {
				out.write(b);
			}
			in.close();
		}
	}
	public static void main(String args[]){
		MyZip book = new MyZip();
		try{
			book.zip("E:/hello.zip" , new File("E:/hello"));
			System.out.println("压缩完成");
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
}

2. 解压缩ZIP文件

ZipInputStream类可读取ZIP压缩格式的文件,包括已压缩和未压缩的条目(entry)。


ZipInputStream类的构造方法如下:

  • ZipInputStream(InputStream in)

ZipInputStream类的常用方法:
在这里插入图片描述


代码演示:

public class Decompressing {
	public static void main(String args[]) {
			File file = new File("hello.zip");
			ZipInputStream zin;
			try{
				ZipFile zipFile = new ZipFile(file);
				zin = new ZipInputStream(new FileInputSteam(file));
				ZipEntry entry = zin.getNextEntry();
				while(((entry = zin.getNextEntry())!= null) && !entry.isDirectory()) {
					File tmp = new File("C:\\" + entry.getName());
					if(!tmp.exists()) {
						temp.getParentFile().mkdirs();
						OutputStream os = new FileOutputStream(tmp);
						InputStream in = zipFile.getInputStream(entry);
						int count = 0;
						while((count = in.read()) != -1) {
							os.write(count);
						}
						os.close();
						in.close();
					}
					zin.closeEntry();
					System.out.println(entry.getName() + "解压成功");
				}
				zin.close();
			} 	catch(Exception e) {
				e.printStackTrace(0;
			}
	}	
}
  • 0
    点赞
  • 2
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值