建议保留:两个星期整理IO必学内容

建议保留:星期整里出来IO流必学的笔记

、IO流.
Java 的 IO 流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作,在 Java 中把不同的输入/输出源(键盘、文件、网络连接等)抽象表述 为“流”(stream),通过流的方式允许 Java 程序使用相同的方式来访问不同的输入输出源。
stream 是从起源(source)到接收(sink)的有序数据。
Java 把所有传统的流类型(类或抽象类)都放在 java.io 包中,用以实现输入输出功能

流的分类

1.输入流和输出流 按照流的流向来分,可以分为输入流和输出流。
输入、输出都是从程序运行所在 内存的角度来划分的。

输入流:只能从中读取数据,而不能向其写入数据。由 InputStream 和 Reader 作为基类

输出流:只能向其写入数据,而不能从中读取数据。由 OutputStream 和 Writer 作为基类

2.字节流和字符流 字节流和字符流的用法几乎完全一样,区别在于字节流和字符流所操 作的数据单 元不同。

字节流操作的数据单元是 8 位的字节,由 InputStream 和 OutputStream 作为基类。

字符流操作的数据单元是 16 位的字符,由 Reader 和 Writer 作为基类。

3.节点流和处理流 按照流的角色来分,可以分为节点流和处理流。

节点流:可以从向一个特定的 IO 设备(如磁盘、网络)读/写数据的流。也被称为低级流 。

处理流:用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能 。也称为高级流。

IO 类结构图
在这里插入图片描述

1)Java File 类(文件操作类)(只操作不访问)
File 类是 java.io 包中唯一代表磁盘文件本身的对象,如果在程序中操作文件和目录,则都 可以通过 File 类来完成。

File 类定义了一些方法来操作文件,如新建、删除、重命名文件和目录等。

File 类不能访问文件内容本身,如果需要访问文件内容本身,则需要使用输入/输出流。

File 类提供了如下三种形式构造方法。

File(String path):如果 path 是实际存在的路径,则该 File 对象表示的是目录;如果 path 是文件名,则该 File 对象表示的是文件。

File(String path, String name):path 是路径名,name 是文件名。

File(File dir, String name):dir 是路径对象,name 是文件名。

使用任意一个构造方法都可以创建一个 File 对象,然后调用其提供的方法对文件进行操作 。

File类的常用方法及说明。
方法名称 说明
boolean canRead() 测试应用程序是否能从指定的文件中进行读取

boolean canWrite() 测试应用程序是否能写当前文件

boolean delete() 删除当前对象指定的文件

boolean exists() 测试当前 File 是否存在

String getAbsolutePath() 返回由该对象表示的文件的绝对路径名

String getName() 返回表示当前对象的文件名或路径名(如果是路径,则返回最后一 级子路径名)

String getParent() 返回当前 File 对象所对应目录(最后一级子目录)的父目录名

boolean isAbsolute() 测试当前 File 对象表示的文件是否为一个绝对路径名。该方法消除 了不同平台的差异,可以直接判断 file 对象是否为绝对路径。在 UNIX/Linux/BSD 等系统上,如果路径名开头是一条斜线/,则表明该 File 对象对应一个绝对路径;在 Windows 等系统上,如果路径开头是盘符,则说明它是一个绝对路径。

boolean isDirectory() 测试当前 File 对象表示的文件是否为一个路径

boolean isFile() 测试当前 File 对象表示的文件是否为一个“普通”文件

long lastModified() 返回当前 File 对象表示的文件最后修改的时间

long length() 返回当前 File 对象表示的文件长度

String[] list() 返回当前 File 对象指定的路径文件列表

String[] list(FilenameFilt er) 返回当前 File 对象指定的目录中满足指定过滤器的文件列表

boolean mkdir() 创建一个目录,它的路径名由当前 File 对象指定

boolean mkdirs() 创建一个目录,它的路径名由当前 File 对象指定

boolean renameTo(File) 将当前 File 对象指定的文件更名为给定参数 File 指定的路径名

File 类中有以下两个常用常量:

public static final String pathSeparator:指的是分隔连续多个路径字符串的分隔符, Windows 下指 ;。
public static final String separator:用来分隔同一个路径字符串中的目录的,
Windows 下指 /。例如 C:/Program Files/Common Files。

获取文件属性:

在 Java 中获取文件属性信息的第一步是先创建一个 File 类对象并指向一个已存在的文件, 然后调用上面的方法进行操作。

例 1
假设有一个文件位于 C:\windows\notepad.exe。编写 Java 程序获取并显示该文件的长度、 是否可写、最后修改日期以及文件路径等属性信息。实现代码如下:

package com.gxIO;

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Test01 {

public static void main(String[] args) {
      String path = "C:/windows/"; // 指定文件所在的目录 
         File f = new File(path, "notepad.exe"); // 建立 File 变量,并设定由 f 变量引用
         
         System.out.println("C:\\windows\\notepad.exe 文件信息如下:"); 
         System.out.println("============================================"); 
         System.out.println("文件长度:" + f.length() + "字节"); 
         System.out.println("文件或者目录:" + (f.isFile() ? "是文件" : "不是文件")); 
         System.out.println("文件或者目录:" + (f.isDirectory() ? "是目录" : "不是目录")); 
         System.out.println("是否可读:" + (f.canRead() ? "可读取" : "不可读取")); 
         System.out.println("是否可写:" + (f.canWrite() ? "可写入" : "不可写入")); 
         System.out.println("是否隐藏:" + (f.isHidden() ? "是隐藏文件" : "不是隐藏文件 ")); 
         //System.out.println("最后修改日期:" + new Date(f.lastModified())); 
         DateFormat d = new SimpleDateFormat("YYYY-MM-DD HH:mm:ss");  
          System.out.println("最后修改日期:" +  d.format(new Date(f.lastModified()))); 
         System.out.println("文件名称:" + f.getName()); 
         System.out.println("文件路径:" + f.getPath()); 
         System.out.println("绝对路径:" + f.getAbsolutePath()); 
}

}

输出:
C:\windows\notepad.exe 文件信息如下:

文件长度:17920字节
文件或者目录:是文件
文件或者目录:不是目录
是否可读:可读取
是否可写:可写入
是否隐藏:不是隐藏文件
最后修改日期:2018-04-102 07:34:25
文件名称:hh.exe
文件路径:C:\windows\hh.exe
绝对路径:C:\windows\hh.exe

在上述代码中 File 类构造方法的第一个参数指定文件所在位置,这里使用 C:/作为文件的 实际路径;第二个参数指定文件名称。创建的 File 类对象为 f,然后通过 f 调用方法获取相 应的属性

创建和删除文件
File 类不仅可以获取已知文件的属性信息,还可以在指定路径创建文件,以及删除一个文件。创建文件需要调用 createNewFile()方法,删除文件需要调用 delete() 方法。
无论是创建还是删除文件通常都先调用 exists() 方法判断文件是否存在。

例 2
假设要在 E盘上创建一个 test.txt 文件,程序启动时会检测该文件是否存在,如果不存在 则创建;如果存在则删除它再创建。

package com.gxIO;

import java.io.File;
import java.io.IOException;

public class Test02 {
	
	public static void main(String[] args)throws IOException {
		
		
		try {
			File f = new File("E:\\test.txt");//创建指向文件的File对象
			//判断文件是否存在
			if (f.exists()) {
				f.delete();//存在则删除
			}
			f.createNewFile();//再创建
		} catch (Exception e) {
			System.out.println(e);
		}
		
	}

}

运行程序之后可以发现,在 C 盘中已经创建好了 test.txt 文件。但是如果在不同的操作系 统中,路径的分隔符是不一样的,例如:
Windows 中使用反斜杠\表示目录的分隔符。
Linux 中使用正斜杠/表示目录的分隔符。

那么既然 Java 程序本身具有可移植性的特点,则在编写路径时最好可以根据程序所在的操作系统自动使用符合本地操作系统要求的分隔符,这样才能达到可移植性的目的。要实现 这样的功能,则就需要使用 File 类中提供的两个常量。

代码修改如下:

package com.gxIO;

import java.io.File;
import java.io.IOException;

public class Test02 {
	public static void main(String[] args)throws IOException {
		try {
			//File f = new File("E:\\test.txt");//创建指向文件的File对象
			String path= "E:"+File.separator+"test2.java";
			File f= new File(path);
			//判断文件是否存在
			if (f.exists()) {
				f.delete();//存在则删除
			}
			f.createNewFile();//再创建
		} catch (Exception e) {
			System.out.println(e);
		}
	}
}

程序的运行结果和前面程序一样,但是此时的程序可以在任意的操作系统中使用。

注意:在操作文件时一定要使用 File.separator 表示分隔符。在程序的开发中,往往会使用 Windows 开发环境,因为在 Windows 操作系统中支持的开发工具较多,使用方便,而在 程序发布时往往是直接在 Linux 或其它操作系统上部署,所以这时如果不使用 File.separator,则程序运行就有可能存在问题。关于这一点我们在以后的开发中一定要有 所警惕。

创建和删除目录
File 类除了对文件的创建和删除外,还可以创建和删除目录。创建目录需要调用 mkdir() 方 法,删除目录需要调用 delete() 方法。无论是创建还是删除目录都可以调用 exists() 方法判 断目录是否存在。

例 3
编写一个程序判断 E盘根目录下是否存在 config 目录,如果存在则先删除再创建。实现代 码如下:

package com.gxIO;

import java.io.File;

public class Test03 {
public static void main(String[] args) {
String path =“E:/config”;//指定目录位置
File f =new File(path);
if (f.exists()) {
f.delete();
}
f.mkdir();//创建文件目录
}

}


遍历目录
通过遍历目录可以在指定的目录中查找文件,或者显示所有的文件列表。

File 类的 list() 方法提供了遍历目录功能,该方法有如下两种重载形式。

  1. String[] list()

该方法表示返回由 File 对象表示目录中所有文件和子目录名称组成的字符串数组,如果调 用的 File 对象不是目录,则返回 null。
提示:list() 方法返回的数组中仅包含文件名称,而不包含路径。但不保证所得数组中的相 同字符串将以特定顺序出现,特别是不保证它们按字母顺序出现。

  1. String[] list(FilenameFilter filter)

该方法的作用与 list() 方法相同,不同的是返回数组中仅包含符合 filter 过滤器的文件和目 录,如果 filter 为 null,则接受所有名称。

例 4
假设要遍历 E盘根目录下的所有文件和目录,并显示文件或目录名称、类型及大小。使用 list() 方法的实现代码如下:

package com.gxIO;

import java.io.File;

public class Test04 {
	public static void main(String[] args) {
		 File f= new File("E:/");//建立File 变量,并设定由f变量数引用
		 System.out.println("文件名称\t\t 文件类型\t\t 文件大小");
		 System.out.println("==================================================="); 
		 String fileList[] =f.list();//调用不带参数的list()方法
		 for (int i = 0; i < fileList.length; i++) {
			System.out.print(fileList[i]+"\t\t");
			System.out.print((new File("E:/",fileList[i])).isFile()?"文件"+"\t\t":"文件夹"+"\t\t");
			System.out.println((new File("E:/",fileList[i])).length()+"字节");
		}
		 
	}

}

输出:
文件名称 文件类型 文件大小

$RECYCLE.BIN 文件夹 0字节
.temp 文件夹 0字节
23976f938723ebeef34448cda86a88b1 文件夹 0字节
FileHistory 文件夹 0字节
qqpcmgr_docpro 文件夹 0字节
Richyingyong 文件夹 0字节
System Volume Information 文件夹 0字节
test.txt 文件 0字节
test2.java 文件 0字节
可以调整快慢的播放器 文件夹 0字节
壁纸图片 文件夹 4096字节
学生会资料 文件夹 4096字节
拼音字母表.jpg 文件 98649字节
生活文案 文件夹 0字节
自制图片 文件夹 4096字节
音乐 文件夹 8192字节

由于 list() 方法返回的字符数组中仅包含文件名称,因此为了获取文件类型和大小,必须先转换为 File 对象再调用其方法。

例 5
假设希望只列出目录下的某些文件,这就需要调用带过滤器参数的 list() 方法。首先需要创建文件过滤器,该过滤器必须实现 java.io.FilenameFilter 接口,并在 accept()方法中指定允许的文件类型。

如下所示为允许 SYS、TXT 和 BAK 格式文件的过滤器实现代码:

package com.gxIO;

import java.io.File;
import java.io.FilenameFilter;

public class Test05 implements FilenameFilter {
	//实现FilenameFileter
	 public boolean accept(File dir, String name) { 
		  return name.endsWith(".sys") || name.endsWith(".txt") || name.endsWith(".bak"); 
	}

	
}

上述代码创建的过滤器名称为 Test05,接下来只需要将该名称传递给 list() 方法即可实 现筛选文件。如下所示为修改后的 list() 方法,其他代码与例 4 相同,这里不再重复。
调用:

String fileList[] = f.list(new ImageFilter());

package com.gxIO;

import java.awt.image.ImageFilter;
import java.io.File;

public class Test04 {
	public static void main(String[] args) {
		Test05 h=new Test05();
		 File f= new File("E:/");//建立File 变量,并设定由f变量数引用
		 System.out.println("文件名称\t\t 文件类型\t\t 文件大小");
		 System.out.println("==================================================="); 
		 String fileList[] =f.list(h); //调用过滤器
		 for (int i = 0; i < fileList.length; i++) {
			System.out.print(fileList[i]+"\t\t");
			System.out.print((new File("E:/",fileList[i])).isFile()?"文件"+"\t\t":"文件夹"+"\t\t");
			System.out.println((new File("E:/",fileList[i])).length()+"字节");
		}		 
	}
}

递归遍历全目录
/* * 对一个目录的下的所有内容,进行完全的遍历编程技巧,方法的递归调用,自己调用自己 */

package com.gxIO;

import java.io.File;

public class Test06 {

	public static void main(String[] args) {
		File dir = new File("F:\\2020年java基础课程");
		getAllDir(dir);
	}

	/* * 定义方法,实现目录的全遍历 */
	public static void getAllDir(File dir) {
		try {
			System.out.println(dir);
			// 调用方法 listFiles()对目录,dir 进行遍历
			File[] fileArr = dir.listFiles();
			for (File f : fileArr) {
				// 判断变量 f 表示的路径是不是文件夹
				if (f.isDirectory()) {
					// 是一个目录,就要去遍历这个目录
					// 本方法,getAllDir,就是给个目录去 遍历
					// 继续调用 getAllDir,传递他目录
					getAllDir(f);
				} else {
					System.out.println(f);
				}
			}
		} catch (Exception e) {
			
			System.out.println(e);
		}
	}
}

输出:

在这里插入图片描述

2)字节流
字节输出流 OutputStream

OutputStream 此抽象类,是表示输出字节流的所有类的超类。

操作的数据都是字节,定义了输出字节流的基本共性功能方法。
输出流中定义都是写 write方法,如下图:
在这里插入图片描述

FileOutputStream 类
OutputStream 有很多子类,其中子类 FileOutputStream可用来写入数据到文件。 FileOutputStream 类,即文件输出流,是用于将数据写入File的输出流
在这里插入图片描述

FileOutputStream 类写入数据到文件中
将数据写到文件中,代码演示:

package com.gxIO;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamDemo {  
	public static void main(String[] args) throws IOException {     
		//需求:将数据写入到文件中。      
  //创建存储数据的文件。
		File file = new File("E:\\file.txt");     
		//创建一个用于操作文件的字节输出流对象。一创建就必须明确 数据存储目的地。       
		//输出流目的是文件,会自动创建。如果文件存在,则覆盖。      
		FileOutputStream fos = new FileOutputStream(file);        
		//调用父类中的 write 方法。     
		byte[] data = "abcde".getBytes();      
		fos.write(data);           
		fos.close();  //关闭流资源。    
   }
}

在这里插入图片描述

给文件中续写和换行
我们直接 new FileOutputStream(file)这样创建对象,写入数据,会覆盖原有的文件, 那么我们想在原有的文件中续写内容怎么办呢?
查阅 FileOutputStream 的 API。
发现在 FileOutputStream 的构造函数中,可以接受一个 boolean 类型的值,如果值 true,就会在文件末位继续添加。

构造方法

在这里插入图片描述

给文件中续写数据和换行,代码演示:

package com.gxIO;

import java.io.File;
import java.io.FileOutputStream;
public class FileOutputStreamDemo2 {
	public static void main(String[] args) throws Exception {
		File file = new File("E:\\file.txt");
		FileOutputStream fos = new FileOutputStream(file, true);
		String str = "\r\n" + "itcast";
		fos.write(str.getBytes());
		fos.close();
	}
}

 





字节输入流 InputStream

如何把数据读到内存中,我们通过 InputStream 可以实现。
InputStream 此抽象类,是表示字节输入流的所有类的超类。定义了字节输入流的基本 共性功能方法。

在这里插入图片描述

int read():读取一个字节并返回,没有字节返回-1.
int read(byte[]): 读取一定量的字节数,并存储到字节数组中,返回读取到的字节数。
FileInputStream 类

InputStream 有很多子类,其中子类 FileInputStream 可用来读取文件内容。
FileInputStream 从文件系统中的某个文件中获得输入字节。

构造方法:
在这里插入图片描述

FileInputStream 类读取数据 read 方法
在读取文件中的数据时,调用 read 方法,实现从文件中读取数据
从文件中读取数据,代码演示:
在读取文件中的数据时,调用 read 方法,每次只能读取一个

package com.gxIO;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamDemo {
	public static void main(String[] args) throws IOException {
		File file = new File("E:\\file.txt");
		// 创建一个字节输入流对象,必须明确数据源,其实就 是创建字节读取流和数据源相关联。
		FileInputStream fis = new FileInputStream(file);
		// 读取数据。使用 read();一次读一个字节。
		int ch = 0;
		while ((ch = fis.read()) != -1) {	
			   System.out.println("ch="+(char)ch); 
		} // 关闭 资源。
		fis.close();
	}
}

读取数据 read(byte[])方法


在这里插入图片描述



在读取文件中的数据时,调用 read 方法,每次只能读取一个,太麻烦了,于是我们可 以定义数组作为临时的存储容器,这时可以调用重载的 read 方法,一次可以读取多个字 符。

package com.xiaohaihai;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamDemo {
	public static void main(String[] args) throws IOException {
		File file = new File("E:\\file.txt");
		// 创建一个字节输入流对象,必须明确数据源,其实就 是创建字节读取流和数据源相关联。
		FileInputStream fis = new FileInputStream(file);
		byte[] buf = new byte[1024];// 长度可以定义成 1024 的整数倍。
		int ch = 0;
		
		try {
			while ((ch = fis.read(buf)) != -1) {
				
				System.out.println(new String(buf, 0, ch));
			} // 关闭 资源。
		} catch (Exception e) {
		System.out.println(e);
		}
		fis.close();
	
	}
}
复制文件:
原理;读取一个已有的数据,并将这些读到的数据写入到另一个文件中
package com.xiaohaihai;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException
public class FileInputStreamDemo {
	public static void main(String[] args) throws IOException {
		File file = new File("E:\\file.txt");
		File file2= new File("E:\\\\file.txt");
		// 创建一个字节输入流对象,必须明确数据源,其实就 是创建字节读取流和数据源相关联。
		FileInputStream fis = new FileInputStream(file);
		FileOutputStream fis1 = new FileOutputStream (file2);
		
		// 读取数据。使用 read();一次读一个字节。
		int ch = 0;
			while ((ch = fis.read()) != -1) {
				fis1.write(ch);// 			}
 // 关闭 资源。
		fis.close();
		fis.close();
	}
}

上述代码输入流和输出流之间是通过 ch 这个变量进行数据交换的。
上述复制文件有个问题,每次都从源文件读取一个,然后在写到指定文件,接着再读 取一个字符,然后再写一个,一直这样下去。效率极低。

缓冲数组方式复制文件
上述代码复制文件效率太低了,并且频繁的从文件读数据,和写数据,能不能一次多 把文件中多个数据都读进内容中,然后在一次写出去,这样的速度一定会比前面代码速度 快。

package com.xiaohaihai;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamDemo {
	public static void main(String[] args) throws IOException {
		File file = new File("E:\\file.txt");
		File file2= new File("E:\\file.txt");
		// 创建一个字节输入流对象,必须明确数据源,其实就 是创建字节读取流和数据源相关联。
		FileInputStream fis = new FileInputStream(file);//读取
		FileOutputStream fis1 = new FileOutputStream (file2);//写入
		
		// 读取数据。使用 read();一次读一个字节。
		byte[] buf = new byte[1024];// 长度可以定义成 1024 的整数倍。
		int ch = 0;
		
		try {
			while ((ch = fis.read(buf)) != -1) {
				fis1.write(buf, 0, ch);// 
				System.out.println(new String(buf, 0, ch));
			} // 关闭 资源。
		} catch (Exception e) {
		System.out.println(e);
		}
		fis.close();
		fis.close();
	}
}

3)字符流
字节流读取字符的问题
通过以下程序读取带有中文件的文件。

字符输入流 Reader
在这里插入图片描述

上述程序中我们读取拥有中文的文件时,使用的字节流在读取,那么我们读取到的都 是一个一个字节。只要把这些字节去查阅对应的编码表,就能够得到与之对应的字符。
API 中是否给我们已经提供了读取相应字符的功能流对象,Reader,读取字符流的抽象超类。

read():读取单个字符并返回
read(char[]):将数据读取到数组中,并返回读取的个数。

FileReader 类

查阅 FileInputStream 的 API,发现 FileInputStream 用于读取诸如图像数据之类的原始字节流。要读取字符流,请考虑使用 FileReader。

打开 FileReader 的 API 介绍。用来读取字符文件的便捷类。此类的构造方法假定默认 字符编码和默认字节缓冲区大小都是适当的
构造方法
在这里插入图片描述

字符输出流 Writer
既然有专门用于读取字符的流对象,那么肯定也有写的字符流对象,查阅 API,发现 有一个 Writer 类,Writer 是写入字符流的抽象类。其中描述了相应的写的动作。
在这里插入图片描述

FileWriter 类
查阅 FileOutputStream 的 API,发现 FileOutputStream 用于写入诸如图像数据之类的原 始字节的流。要写入字符流,请考虑使用 FileWriter。
打开 FileWriter 的 API 介绍。用来写入字符文件的便捷类。此类的构造方法假定默认 字符编码和默认字节缓冲区大小都是可接受的。
构造方法
在这里插入图片描述

实例:
FileWriter和FileReader 的使用
例一:(效率低)

package com.xiaohaihai;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CharStreamDemo {
	public static void main(String[] args) throws IOException {
		 //给文件中写中文     
		writeCNText(); 
		//读取文件中的中文 
		readCNText();    
	}

	private static void readCNText() throws IOException {
		FileWriter  fos = new FileWriter ("E:\\file1.txt");
		fos.write("你好!!!!!");    
		fos.close();   	
	}
	private static void writeCNText() throws IOException {
		//File file=File("E:\\file.txt");
		FileReader  file01=new FileReader ("E:\\file.txt");
		int h=0;
		byte[] byt=new byte[1024];
		while  ((h = file01.read()) != -1) {
			//String n=(String).h;
			System.out.println((h));
			System.out.println(h);
		    System.out.println((char)h);     
		}
		file01.close();   
	}
}
例二、(效率高)read(char[])
package com.xiaohaihai;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyTextFileTest {
public static void main(String[] args) throws IOException {
	copyTextFile();
}

private static void copyTextFile() throws IOException {
   FileReader file01=new FileReader("E:\\file.txt");
   
   FileWriter file =new FileWriter("E:\\file1.txt");
   
   char[] but =new char[1024];
   int sb= 0;
 while ((sb=file01.read(but))!=-1) {
	 file.write(but,0,sb); 
	 System.out.println(new String(but,0,sb));
	 
	

	
}   
 file01.close();     
 file.close();   
	
}
}


4)flush()和 close()的区别
flush():将流中的缓冲区缓冲的数据刷新到目的地中,刷新后,流还可以继续使用。
在这里插入图片描述

close():关闭资源,但在关闭前会将缓冲区中的数据先刷新到目的地,否则丢失数据, 然后在关闭流。流不可以使用。如果写入数据多,一定要一边写一边刷新,最后一次可以 不刷新,由 close 完成刷新并关闭。

5)转换流
OutputStreamWriter 类
在这里插入图片描述

查阅 OutputStreamWriter 的 API 介绍,OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节。它的作用的就是,将字 符串按照指定的编码表转成字节,在使用字节流将这些字节写出去。

代码演示:

package com.gxIO;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;

public class writeCN {
public static void main(String[] args) throws IOException {
	//创建与文件关联的字节输出流对象
	 FileOutputStream fos =new FileOutputStream("E:\\test.txt");
	//创建可以把字符转成 字节的转换流对象,并指定编码      
	 OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");  
	//调用转换流,把文字写出去,其实是写到转换流的 缓冲区中 
	  osw.write("你好");//写入缓冲区。     
	  osw.close();  
}
}

OutputStreamWriter 流对象,它到底如何把字符转成字节输出的呢?

其实在 OutputStreamWriter 流中维护自己的缓冲区,当我们调用 OutputStreamWriter 对象的 write 方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到 OutputStreamWriter 缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲 区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中。

InputStreamReader 类
在这里插入图片描述

查阅 InputStreamReader 的 API 介绍,InputStreamReader 是字节流通向字符流的桥梁 :它使用指定的字符编码表读取字节并将其解码为字符。它使用的字符集可以由名称指定 或显式给定,或者可以接受平台默认的字符集。

代码演示

package com.xiaohaihai;

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

public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
	 //演示字节转字符流的转换流 
	readCN();
}

private static void readCN() throws IOException {
	  //创建读取文件的字节流对象 
	InputStream  in =new FileInputStream("E:\\test.txt");
		
	   //创建转换流对象 ;
   //这样创建对象,会用本地默认码表读取,将会发生错误解码的错 误     
    //InputStreamReader isr = new InputStreamReader(in)
	InputStreamReader isr=new InputStreamReader(in,"utf-8");
	
	 char[] but =new char[1024];
	
    int ch = 0;        
    while((ch = isr.read(but))!=-1){     
    	//System.out.println((char)ch);    
   	 System.out.println(new String(but,0,ch));
    	}        
    //关闭流
    isr.close();   
}
}

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

转换流和子类区别
发现有如下继承关系:
OutputStreamWriter:
|–FileWriter:

InputStreamReader:
|–FileReader;

父类和子类的功能有什么区别呢?
OutputStreamWriter 和 InputStreamReader 是字符和字节的桥梁:也可以称之为字符转 换流。字符转换流原理:字节流+编码表。

FileWriter 和 FileReader:作为子类,仅作为操作字符文件的便捷类存在。当操作的字 符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码 。
InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”));//默认字 符集。

InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”),“GBK”);//指 定 GBK 字符集。

FileReader fr = new FileReader(“a.txt”);
这三句代码的功能是一样的,其中第三句最为便捷。
注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用 子类呢?
条件:
1、操作的是文件。2、使用默认编码。

  1. 缓冲流
    在我们学习字节流与字符流的时候,大家都进行过读取文件中数据的操作,读取数据 量大的文件时,读取的速度会很慢,很影响我们程序的效率,那么,我想提高速度,怎么 办?
    Java 中提高了一套缓冲流,它的存在,可提高 IO 流的读写速度
    缓冲流,根据流的分类分类字节缓冲流与字符缓冲流。

01、字节缓冲流
字节缓冲流根据流的方向,共有 2 个
写入数据到流中,字节缓冲输出流 BufferedOutputStream
读取流中的数据,字节缓冲输入流 BufferedInputStream
它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了 IO 流的读写速度
字节缓冲输出流 BufferedOutputStream

通过字节缓冲流,进行文件的读写操作 写数据到文件的操作

构造方法
public BufferedOutputStream(OutputStream out)创建一个新的缓冲输出流,以将数
据写入指 定的底层输出流。

public class BufferedOutputStreamDemo01 {    
 public static void main(String[] args) throws IOException {        
         //写数据到文件的方法 
       write();   
  }    
   /* * 写数据到文件的方法  * 1,创建流 * 2,写数据 * 3,关闭流  */  
   private static void write() throws IOException {     
//创建基本的字节输出流     
  FileOutputStream fileOut = new FileOutputStream("abc.txt");          
   //使用高效的流,把基本的流进行封装,实现速度的提升       
 BufferedOutputStream out = new BufferedOutputStream(fileOut);        
 //2,写数据   
     out.write("hello".getBytes());       
  //3,关闭流  
      out.close();   
  }
 }

字节缓冲输入流 BufferedInputStream

刚刚我们学习了输出流实现了向文件中写数据的操作,那么,现在我们完成读取文件中数 据的操作

构造方法
public BufferedInputStream(InputStream in)
/** 从文件中读取数据* 1,创建缓冲流对象 * 2,读数据,打印 * 3,关闭 */ private static void read()

throws IOException {
         //1,创建缓冲流对象  
      FileInputStream fileIn = new FileInputStream("abc.txt");
         //把基本的流包装成高效的 流   
     BufferedInputStream in = new BufferedInputStream(fileIn);   
      //2,读数据  
      int ch = -1;   
      while ( (ch = in.read()) != -1 ) {  
           //打印     
       System.out.print((char)ch);    
     }         //3,关闭   
     in.close();  
   }

使用基本的流与高效的流完成复制文件

package com.gxIO;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferedOuputStre {
	public static void main(String[] args) throws IOException {
//		long li= System.currentTimeMillis();
//		GxiaoLiu();
//		long li2=System.currentTimeMillis();
		//System.out.println("耗时"+(li2-li)+"毫秒");//耗时286毫秒
//		long li= System.currentTimeMillis();
//		Btongtiu();
//		long li2=System.currentTimeMillis();
//		System.out.println("耗时"+(li2-li)+"毫秒");//耗时902毫秒
		long li= System.currentTimeMillis();
		YiGuYig();
		long li2=System.currentTimeMillis();
		System.out.println("耗时"+(li2-li)+"毫秒");//耗时655905毫秒
	}

	private static void YiGuYig() throws IOException {
		
		
		FileInputStream fileIo = new FileInputStream("E:\\录像30.lxe");
		FileOutputStream fileO = new FileOutputStream("E:\\copy_录像30.lxe");
		int i = 0;
	//	byte[] sb = new byte[1024];
		while ((i = fileIo.read()) != -1) {
			fileO.write(i);
			
		}
		fileO.close();
		fileO.close();
	}

	private static void Btongtiu() throws IOException {
		FileInputStream fileIo = new FileInputStream("E:\\录像30.lxe");
		FileOutputStream fileO = new FileOutputStream("E:\\copy_录像30.lxe");
		int i = 0;
		byte[] sb = new byte[1024];
		while ((i = fileIo.read(sb)) != -1) {
			fileO.write(sb, 0, i);
			
		}
		fileO.close();
		fileO.close();
	}
	

	private static void GxiaoLiu() throws IOException {
		try {
			FileInputStream fileIo = new FileInputStream("E:\\录像30.lxe");
			FileOutputStream fileO = new FileOutputStream("E:\\copy_录像30.lxe");
			BufferedInputStream fileIo01 = new BufferedInputStream(fileIo);
			BufferedOutputStream fileO01 = new BufferedOutputStream(fileO);
			int i = 0;
			byte[] sb = new byte[1024];
			while ((i = fileIo01.read(sb)) != -1) {
				fileO01.write(sb, 0, i);
			}
fileO01.flush();     //先写再关闭。
			fileO.close();
			fileIo01.close();
			fileO.close();
			fileO01.close();
		} catch (Exception e) {
		System.out.println(e);
		}
	}

}

02、字符缓冲流
字符缓冲输入流 BufferedReader

字符缓冲输出流 BufferedWriter

完成文本数据的高效的写入与读取的操作
字符缓冲输出流 BufferedWriter
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写 入。
方法:

void newLine() 根据当前的系统,写入一个换行符

/* * BufferedWriter 字符缓冲输出流 * 方法 *
public void newLine()写入一个行分隔符 * * 需 求: 通过缓冲输出流写入数据到文件 * 分析: * 1,创建流对象 * 2,写数据 * 3,关闭流 * */

package com.gxIO;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BuffereRW {
		  public static void main(String[] args) throws IOException {  
		       //创建流        //基本字符输出流       
		 FileWriter fileOut = new FileWriter("E:\\file1.txt");    
		 //把基本的流进行包装      
		 BufferedWriter out = new BufferedWriter(fileOut);   
		 //2,写数据     
		   for (int i=0; i<5; i++) {      
		       out.write("hello");     
		        out.newLine();   //换行
		        System.out.println(i);
		  }         //3,关闭流  
		      out.close();    
		 }
		 } 
 

在这里插入图片描述

字符缓冲输入流 BufferedReader
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
l 方法
public String readLine() 读取一个文本行,包含该行内容的字符串,不包含任何行终止 符,如果已到达流末尾,则返回 null

/* * BufferedReader 字符缓冲输入流 * * 方法: * String readLine() * 需求:从文件中读取 数据,并显示数据 */

public class BufferedReaderDemo { 
package com.gxIO;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class BuffereRW {
	public static void main(String[] args) throws IOException {  
	       //1,创建流      
BufferedReader in = new BufferedReader(new FileReader("E:\\file1.txt")); 
//2,读数据 //一次一个字符 //一次一个字符数组 //一 次读取文本中一行的字符串内容     
	 String line = null;    
	while((line=in.readLine())!=null ){       
	      System.out.println(line);    
	     }                 //3,关闭流   
	     in.close();    
	 } 
	} 
 


 使用字符缓冲流完成文本文件的复制 
package com.gxIO;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyTextFile {
	public static void main(String[] args) throws IOException {
		long li =System.currentTimeMillis();
		
		
			try {
				GaoxRW();
			} catch (Exception e) {
				System.out.println(e);
				e.printStackTrace();
			}
		long li2 = System.currentTimeMillis();
		System.out.println("耗时"+(li2-li)+"毫秒");
	}

	private static void GaoxRW() throws IOException {
        FileReader Ri=new FileReader("E:\\file.txt");
        FileWriter Wi=new FileWriter("E:\\file1.txt");
		BufferedReader Ril= new BufferedReader(Ri);
		BufferedWriter wil=new BufferedWriter(Wi);
		String  sb= null;
		while ((sb=Ril.readLine())!=null) {
			wil.write(sb);
			wil.newLine();
		}
		
		wil.flush();
		Ri.close();
		Wi.close();
		Ril.close();
		wil.close();
	}

}

7)Properties(连接IO的唯一集合) 配置文件类
Properties 类介绍
在这里插入图片描述

Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性 列表中每个键及其对应值都是一个字符串。
特点:
1、Hashtable 的子类,map 集合中的方法都可以用。
2、该集合没有泛型。键值都是字符串。
3、它是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化的 设备(硬盘、U 盘、光盘)上。键值的来源也可以是持久化的设备。
4、有和流技术相结合的方法。

load(InputStream) 把指定流所对应的文件中的数据,读取出来,保存到 Propertie 集合中
load(Reader)
store(OutputStream,commonts)把集合中的数据,保存到指定的流所对应的文件中,参数 commonts 代表对描述信息
stroe(Writer,comments);

代码演示:
/* * * Properties 集合,它是唯一一个能与 IO 流交互的集合 * 需求:向 Properties 集合中 添加元素,并遍历 * 方法: * public Object setProperty(String key, String value) * 调用 Hashtable 的方法 put。 * public Set stringPropertyNames()返回此属性列表中的键集 , * public String getProperty(String key)用指定的键在此属性列表中搜索属性 */

package com.gxIO;

import java.util.Properties;
import java.util.Set;


public class PropertiesDemo01 {
	
public static void main(String[] args) {
	 Properties prop = new Properties();    
	 //添加元素到集合      prop.put(key, value);     
	 prop.setProperty("name", "张三");      
	 prop.setProperty("age", "30");      
	 prop.setProperty("sex", "男");       
	 //System.out.println(prop);//测试的使用 
	 Set<String> keys = prop.stringPropertyNames();   
	 for (String key : keys) {   
		 //通过键 找值       
		 // prop.get(key);    
		 String value = prop.getProperty(key);   
		 
		 System.out.println(key+"==" +value);    
		 } 
	 }
}	

将集合中内容存储到文件
需求:使用 Properties 集合,完成把集合内容存储到 IO 流所对应文件中的操作
分析:
1,创建 Properties 集合
2,添加元素到集合
3,创建流
4,把集合中的数据存储到流所对应的文件中 stroe(Writer,comments)
store(OutputStream,commonts) 把集合中的数据,保存到指定的流所对应的文件中,参数 commonts 代表对描述信息
5,关闭流

package com.gxIO;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;


public class PropertiesDemo01 {
	
public static void main(String[] args) throws IOException {
	//1,创建 Properties 集合 
	 Properties prop = new Properties();    
   //2,添加元素到 集合       prop.put(key, value);     
	 prop.setProperty("name", "张三");      
	 prop.setProperty("age", "30");      
	 prop.setProperty("sex", "男");       
	 //System.out.println(prop);//测试的使用 
	 //3,创建流   
	 FileWriter out = new FileWriter("E:\\test.txt");
	 //4,把集合中的数据存储到流所对应的文件中
	 prop.store(out, "save data");
	  out.close();
	 }
}

在这里插入图片描述

读取文件中的数据,并保存到集合

需求:从属性集文件 prop.properties 中取出数据,保存到集合中
分析:
1,创建集合
2,创建流对象
3,把流所对应文件中的数据 读取到集合中load(InputStream)把指定流所对应的文件中的数据,读取出来,保存到 Propertie 集合中 load(Reader)
4,关闭流
5,显示集合中的数据

代码演示:
需求:从属性集文件 prop.properties 中取出数据,保存到集合中
分析:
1,创建集合
2,创建流对象
3,把流所对应文件中的数据 读取到集合中
load(InputStream) 把指定流所对应的文件中的数据,读取出来,保存到 Propertie 集合中load(Reader)
4,关闭流
5,显示集合中的数据

package com.gxIO;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public class PropertiesDemo03 {
	public static void main(String[] args) throws IOException {
		//创建集合
		Properties prop=new Properties();
		//创建流对象
		//FileInputStream in= new FileInputStream("E:\\test.txt");
		FileReader in = new FileReader("E:\\test.txt"); 
		  //3,把流所对应文件中的数据 读取到集合中 
		prop.load(in);
		   //4,关闭流 
		in.close(); 
		//5,显示集合中的数据    
		System.out.println(prop);   
	}
}

输出:
{age=30, name=张三, sex=男}

注意:使用字符流 FileReader 就可以完成文件中的中文读取操作了

8)序列化流与反序列化流
ObjectInputStream 称为反序列化流

ObjectOutputStream 称为序列化流

特点:用于操作对象。
可以将对象写入到文件中,也可以从文件中读取对象。
对象序列化流 ObjectOutputStream
ObjectOutputStream 将Java对象的基本数据类型和图形写入 OutputStream。
可以使用 ObjectInputStream 读取(重构)对象。
通过在流中使用文件可以实现对象的持久存储。
注意:只能将支持 java.io.Serializable 接口的对象写入流中
在这里插入图片描述

代码演示:

public class ObjectStreamDemo { 
public static void main(String[] args)throws IOException, 
ClassNotFoundException {   
      /* * 将一个对象存储到持久化(硬盘)的设备上。  */      
  writeObj();//对象的序列化。
}    
 public static void writeObj() throws IOException {  
       //1,明确存储对象的文件。 
FileOutputStream fos = new FileOutputStream("tempfile\\obj.object"); 
        //2,给操作文件对象加入写入对象功能。  
      ObjectOutputStream oos = new ObjectOutputStream(fos);  
       //3,调用了写入对象的方 法。 
       oos.writeObject(new Person("wangcai",20));         //关闭资源。        oos.close();   
  }
 } 

Person 类 
public class Person implements Serializable {  
   private String name;  
   private int age;    
 public Person() { 
        super();  
   }  
   public Person(String name, int age) {   
      super();        
 this.name = name;     
this.age = age;  
   }    
   public String getName() {    
     return name; 
    }     
public void setName(String name) {    
     this.name = name;  
   }     
public int getAge() {         return age;   
  }   
  public void setAge(int age) {     
this.age = age;
     } 
 
   @Override 
   public String toString() {         return "Person [name=" + name + ", age=" + age + "]";
     }
 }

把对象 Person [nema=wangcai, age=20] 存到文件中。

对象反序列化流 ObjectInputStream
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列 化。支持 java.io.Serializable 接口的对象才能从流读取。

代码演示

package com.gxIO;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class ObjectStreamDemo02 {
	 public static void main(String[] args) 
			 throws IOException, ClassNotFoundException {    
		 readObj();//对象的反序列化。   
		 }    
		 public static void readObj()  throws IOException, ClassNotFoundException {    
			 
			 //1,定义流对象关联存储了对象文件 。
			 FileInputStream fis = new FileInputStream("E:\\test.txt");
			 //2,建立用于 读取对象的功能对象。    
			 ObjectInputStream ois = new ObjectInputStream(fis);       
			 Person obj = (Person)ois.readObject();         
			 System.out.println(obj.toString());      
fis.close();
			 ois.close();
			 } 
	 }

对象Person [name=wangcai, age=20]从文件中拿出来。






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值