Day16
课程内容
1、File类型
2、IO流的内容
3、字节流 字节输入流,字节输出流
4、字节流的拷贝
5、字符流
6、缓冲流。包装流
一、File类型
File类型的删除方法
1、boolean delete() 删除抽象路径表示的文件或者目录
2、注意:
如果此路径名表示一个目录,则该目录必须为空才能删除。
import java. io. File;
public class Demo_1 {
public static void main ( String[ ] args) {
File f1 = new File ( "E:\\a\\b\\c\\d\\HelloWorld.txt" ) ;
System. out. println ( f1. delete ( ) ) ;
File f2 = new File ( "E:\\a\\b\\c" ) ;
System. out. println ( f2. delete ( ) ) ;
}
}
File类型的重命名方法
1、renameTo(File dest)
调用者是当前的文件夹或者文件的路径对象
dest参数是重命名后的文件夹或者文件的路径对象
2、注意:
1.如果重命名后的文件和文件夹和源文件是在同一文件夹下,就是重命名
2.如果重命名后的文件和文件夹和源文件不是在同一文件夹下,就是剪切加重命名
import java. io. File;
public class Demo_2 {
public static void main ( String[ ] args) {
File f = new File ( "a/a.txt" ) ;
File dest2 = new File ( "b/bb.txt" ) ;
f. renameTo ( dest2) ;
}
}
File类型的判断方法
1、exists() 判断当前封装的抽象路径是否存在
2、isDirectory()判断封装的路径是否是文件夹路径对象
3、isFile() 判断封装的抽象路径是否是文件路径对象
import java. io. File;
public class Demo_3 {
public static void main ( String[ ] args) {
File file = new File ( "b" ) ;
System. out. println ( file. exists ( ) ) ;
System. out. println ( file. isDirectory ( ) ) ;
System. out. println ( file. isFile ( ) ) ;
}
}
File类型的获取功能
1、getAbsolutePath() 获取当前File对象的绝对路径
2、getName() 获取的是抽象路径所表示的最底层的文件或者文件夹的名称
3、getPath() 构造方法封装的是什么抽象路径字符串,打印的就是什么样的字符串
4、length() 获取文件的字节个数
注意:如果调用者file对象是一个文件夹,那么返回值是不确定的
5、File[] listFiles() 获取当前文件夹下所有文件和文件夹的抽象路径表示的file对象
注意:如果此抽象路径名不表示一个目录,那么此方法将返回 null
6、String[] list():获取当前文件夹下所有文件和文件夹的名称
注意:如果此抽象路径名不表示一个目录,那么此方法将返回 null
import java. io. File;
public class Demo_4 {
public static void main ( String[ ] args) {
File file = new File ( "a" ) ;
System. out. println ( file) ;
System. out. println ( file. getAbsolutePath ( ) ) ;
File f1 = new File ( "E:\\codedata\\eclipse_workspace\\Day16" ) ;
System. out. println ( f1. getName ( ) ) ;
File file2 = new File ( "a" ) ;
System. out. println ( file2. getPath ( ) ) ;
File file3 = new File ( "C:\\Users\\Administrator\\Desktop\\长沙java\\InletexEMCFree汉化版.exe" ) ;
System. out. println ( file3. length ( ) ) ;
File file4 = new File ( "C:\\Users\\Administrator\\Desktop\\长沙java" ) ;
File[ ] files = file4. listFiles ( ) ;
for ( File file5 : files) {
System. out. println ( file5. getAbsolutePath ( ) ) ;
}
String[ ] list = file4. list ( ) ;
for ( String string : list) {
System. out. println ( string) ;
}
}
}
获取功能练习
1、键盘录入一个字符串,表示一个路径,如果不是文件夹路径提示重新录入
打印当前文件夹下,所有大于20M的后缀名是.wmv的文件的绝对路径
import java. io. File;
import java. util. Scanner;
public class Demo_5 {
public static void main ( String[ ] args) {
File dir = getDir ( ) ;
File[ ] files = dir. listFiles ( ) ;
for ( File file : files) {
if ( file. isFile ( ) && file. getName ( ) . endsWith ( ".wmv" ) && file. length ( ) > 60 * 1024 * 1024 ) {
System. out. println ( file. getAbsolutePath ( ) ) ;
}
}
}
public static File getDir ( ) {
Scanner sc = new Scanner ( System. in) ;
while ( true ) {
System. out. println ( "清输入一个路径" ) ;
String str = sc. nextLine ( ) ;
File f = new File ( str) ;
if ( f. isDirectory ( ) ) {
return f;
} else {
System. out. println ( "请重新录入" ) ;
}
}
}
}
二、IO概述
1、Input: 输入
2、Output:输出
3、IO流的理解:
在计算中的,所有的数据都是以二进制信息进行存储的。流是一个抽象的概念。站在内存的角度理解IO流:从其他设备进内存的过程称为输入,把从从内存到其他设备这个过程称为输入。
I/O就是用于设备之间进行数据交互的对象的所属类型。
4、java中操作设备与设备之间进行数据的传输,要使用的类型都是IO流类型,这个类型都在io包中
IO分类
1、分类的方式:按照功能进行分类,按照流向进行分类
2、按照功能进行分类:
字节流:操作的数据对象就是字节类型的。
字符流:操作的数据对象是字符类型的。
3、按照流向进行分类
输入流:其他设备进内存的流对象
输出流:从内存到其他设备的流对象
4、IO流体系结构
字节流:
顶层抽象父类
字节输入流:InputStream
字节输出流:OutputStream
字符流:
顶层抽象父类
字符输入流:Reader
字符输出流:Writer
IO程序书写规范
1、根据业务需求选择合适的流对象
2、在使用流对象之前,都要进行导包,都是IO包下
3、使用流对象进行操作,注意:处理编译时异常
4、用完流对象之后,要记得关流
字节流
1、作的数据对象就是字节类型的。
2、流向:字节输入和字节输出流
3、顶层抽象父类:InputStream OutputStream
4、根据交互设备的不同,有不同的实现子类
InputStream
1、字节输出流的顶层抽象父类
2、常用的方法:
int read(); 从输入流中读取数据的下一个字节。读到文件的末尾就返回-1
read(byte[] b) :将流中的数据读入到b这个数组中去,最多能将b.length的字节数据读入到b数组中
read(byte[] arr) 将最多arr.length个数据,读取到数组arr中,返回读取到的字节个数,-1表示读到文件末尾
available() ;得到的就是流中剩余的字节个数
import java. io. FileInputStream;
import java. io. IOException;
import java. io. InputStream;
public class Demo_6 {
public static void main ( String[ ] args) throws IOException {
InputStream is = new FileInputStream ( "b/bb.txt" ) ;
is. read ( ) ;
is. read ( ) ;
is. read ( ) ;
System. out. println ( is. available ( ) ) ;
is. close ( ) ;
}
}
FileInputStream
1、InputStream的子类类型,用于和磁盘上的文件进行交互
2、FileInputStream这个类型,不仅可以读取文本字节信息,还能读取非纯文本字节信息(图片,视频,音频,压缩包等)。
FileInputStream继承InputStream,因此不仅能够一次读取一个字节,还能一次读取多个字节
3、FileInputStream构造方法
FileInputStream(String name) 给定义字符串抽象路径,将抽象路径封装到字节输入流中,将来就可以读取封装路径中文件的字节信息了
FileInputStream(File file) 将File对象封装的抽象路径封装到字节输入流中,将来就可以从封装的file文件对象中读取字节信息
4、注意:
无论是哪种构造方法 ,都只能封装的是文件的路径,封装的是文件夹路径或者不存在的路径,那么会抛出FileNotFoundException 异常
import java. io. File;
import java. io. FileInputStream;
import java. io. FileNotFoundException;
import java. io. IOException;
public class Demo_7 {
public static void main ( String[ ] args) throws IOException {
FileInputStream fis = new FileInputStream ( "b/bb.txt" ) ;
File file = new File ( "b/bb.txt" ) ;
FileInputStream fiss = new FileInputStream ( file) ;
int i;
while ( ( i = fiss. read ( ) ) != - 1 ) {
System. out. println ( ( char ) i) ;
}
fiss. close ( ) ;
}
}
OutputStream
1、字节输出流的顶层父类
2、OutputStream是一个抽象类,只是使用子类FileOutputStream创建对象
3、常用方法
write(int b) 只将一个字节信息写出到指定的设备中
write(byte[] b) 将一个字节数组中的所有信息,都写出到指定文件中
write(byte[] b, int off, int len) 将字节数组的一部分写出到指定文件中,off要从哪个索引开始写出
len从off索引,开始写出字节的个数
close()关闭流对象
import java. io. FileNotFoundException;
import java. io. FileOutputStream;
import java. io. IOException;
import java. io. OutputStream;
public class Demo_8 {
public static void main ( String[ ] args) throws IOException {
OutputStream os = new FileOutputStream ( "a.txt" ) ;
byte [ ] arr = { 97 , 98 , 97 , 97 , 99 , 100 } ;
os. write ( arr, 3 , 3 ) ;
os. close ( ) ;
}
}
FileOutputStream
1、是OutputStream的一个子类类型
2、作用:将字节数据写出到指定的设备中
3、构造方法
FileOutputStream(String name) 将name所表示抽象路径封装成字节输出流对象,将来用于指定要写出字节信息的设备
FileOutputStream(File file) 将file所表示抽象路径封装成字节输出流对象,将来用于指定要写出字节信息的设备
注意:如果该文件存在,但它是一个目录,而不是一个常规文件;或者该文件不存在,但无法创建它;抑或因为其他某些原因而无法打开,则抛出 FileNotFoundException。
4、如果不想初始化指定文件的内容,那么就在构造方法中,加上一个true,开启追加模式即可
eg:FileOutputStream fos = new FileOutputStream(file,true);
5、使用输出流写出字节信息的时候,本质上就是写的是字节信息,就是数字
我们打开文件的时候,发现都是字符,原因:文本编辑器,会根据平台默认编码将字节信息解码成字符
文件拷贝
1、将一个文件中的数据,拷贝到另一个文件中去
2、实现方式
(1)使用输入流将要拷贝的文件信息进行读取,读取到内存中去
(2)使用输出流将内存中的文件信息再进行写出,写出到指定的文件中去
源文件--输入流---> 内存中---使用输出流---->目的文件
import java. io. FileInputStream;
import java. io. FileOutputStream;
import java. io. IOException;
public class Demo_10 {
public static void main ( String[ ] args) throws IOException {
FileInputStream fis = new FileInputStream ( "C:\\Users\\Administrator\\Desktop\\长沙java\\InletexEMCFree汉化版.exe" ) ;
FileOutputStream fos = new FileOutputStream ( "Emc.exe" ) ;
int i ;
while ( ( i = fis. read ( ) ) != - 1 ) {
fos. write ( i) ;
}
fis. close ( ) ;
fos. close ( ) ;
System. out. println ( "拷贝完成了" ) ;
}
}
文件拷贝效率的提升
1、使用一个字节一个字节进行拷贝,效率太低:原因:IO的次数太多,和磁盘进行交互的次数太多了。
2、提升的方式:一次多读取一些数据,一次多写出一些数据。
使用FileInputStream中的read(byte[] arr)和FileOutputStream中的write(byte[] arr)。
将创建的数组的大小和文件的字节个数大小相同。可以使用FileInputStream中的available() 方法,获取要读取文件的字节的个数
3、数组是属于内存的,内存大小有限,如果文件过大,没有办法创建一个和文件一样大小的数组
4、使用小数组的方式:
每次拷贝源文件的一部分,多拷贝几次:将
方法:FileInputStream中的read(byte[] arr)一次将多个字节信息读入到数组中
read(byte[] arr)返回值就是读到的有效的字节个数
FileOutputStream中的write(byte[] arr ,int off,int len) 将字节数组的一部分写出到指定文件中。在输入流中读取多少个数据,就将多少个数据写出到指定的文件中。
数组的大小一般选择1024的倍数,数组越大,拷贝效率就越高
import java. io. FileInputStream;
import java. io. FileNotFoundException;
import java. io. FileOutputStream;
import java. io. IOException;
public class Demo_11 {
public static void main ( String[ ] args) throws IOException {
FileInputStream fis = new FileInputStream ( "C:\\Users\\Administrator\\Desktop\\长沙java\\day15\\视频\\11_编译时异常和运行时异常.wmv" ) ;
FileOutputStream fos = new FileOutputStream ( "视频.wmv" ) ;
byte [ ] arr = new byte [ fis. available ( ) ] ;
fis. read ( arr) ;
fos. write ( arr) ;
fis. close ( ) ;
fos. close ( ) ;
System. out. println ( "复制完成了" ) ;
}
}
import java. io. FileInputStream;
import java. io. FileNotFoundException;
import java. io. FileOutputStream;
import java. io. IOException;
public class Demo_12 {
public static void main ( String[ ] args) throws IOException {
FileInputStream fis = new FileInputStream (
"C:\\Users\\Administrator\\Desktop\\长沙java\\day15\\视频\\11_编译时异常和运行时异常.wmv" ) ;
FileOutputStream fos = new FileOutputStream ( "视频.wmv" ) ;
byte [ ] arr = new byte [ 1024 * 8 ] ;
int i;
while ( ( i = fis. read ( arr) ) != - 1 ) {
fos. write ( arr, 0 , i) ;
}
fis. close ( ) ;
fos. close ( ) ;
System. out. println ( "复制完成了" ) ;
}
}
高效缓冲流
1、BufferedInputStream和BufferedOutputStream流
2、他们是包装类类型,本身不具备读写的功能,就是对一个基础流进行加强,提高基础流的效率
3、构造方法
BufferedInputStream(InputStream in) 将指定的字节输入流传入构造方法中,对字节输入流进行加强,提高基础流的效率
BufferedOutputStream(OutputStream os)将指定的字节输出流传入构造方法中,对字节输出流进行加强,提高基础流的效率
4、使用:
和基础流中的使用一模一样,但是方法效率更高
5、高效的原因:
BufferedInputStream:在该类型中准备了一个8192个大小的数组,当调用read方法的时候,一次会从磁盘中读取8192个字节存到数组中,将第一个字节信息进行返回,再去调用read方法的时候,直接从数组中拿数据,而不再从磁盘中取数据,直到将数组中8192个字节全部读取完之后,下一次再从数组中读数据就没有了,这时候会重新再从磁盘中读取8192个字节到数组中。直到将磁盘中的文件字节信息读完为止。
BufferedOutputStream:在该类型中准备了一个8192个大小的数组,当调用write方法的时候,会先将字节信息写入到数组中,直到将8192个字节数组写满,再一次性将8192个字节信息刷新磁盘中,减少了和磁盘的交互,提升了效率
注意:要注意关流,如果最后没有将8192个数组写满, 不会自动刷新到磁盘中。
import java. io. BufferedInputStream;
import java. io. BufferedOutputStream;
import java. io. FileInputStream;
import java. io. FileOutputStream;
import java. io. IOException;
public class Demo_13 {
public static void main ( String[ ] args) throws IOException {
FileInputStream fis = new FileInputStream ( "a.txt" ) ;
BufferedInputStream bis = new BufferedInputStream ( fis) ;
FileOutputStream fos = new FileOutputStream ( "aa.txt" ) ;
BufferedOutputStream bos = new BufferedOutputStream ( fos) ;
int i;
while ( ( i = bis. read ( ) ) != - 1 ) {
bos. write ( i) ;
}
bis. close ( ) ;
bos. close ( ) ;
System. out. println ( "拷贝完成了" ) ;
}
}
输出流中的close方法和flush方法
1、close方法关闭流资源的
2、包装流中的close方法先调用一下flush方法
3、一旦调用了close方法,流就关闭了,关闭后流就不能再使用了,但是使用flush方法,会将缓冲区中的内容刷新到指定设备中,并不会关闭流对象
flush方法不要频繁的调用否则会丧失缓冲区的作用。
import java. io. BufferedOutputStream;
import java. io. FileInputStream;
import java. io. FileNotFoundException;
import java. io. FileOutputStream;
import java. io. IOException;
public class Demo_14 {
public static void main ( String[ ] args) throws IOException {
FileInputStream fis = new FileInputStream ( "a.txt" ) ;
System. out. println ( fis. read ( ) ) ;
fis. close ( ) ;
FileOutputStream fos = new FileOutputStream ( "flush.txt" ) ;
BufferedOutputStream bos = new BufferedOutputStream ( fos) ;
bos. write ( 91 ) ;
bos. flush ( ) ;
bos. write ( 99 ) ;
bos. flush ( ) ;
}
}
三、字符流
1、使用字节流写字符
将字符串转成字节数组即可
2、使用字节流读字符
如果是纯英文的:可以一次读取一个字节
如果是纯中文:可以一次读取两个字节
如果是中英文混杂:如果想一次读取一个字符,就没有办法了,无论数组的大小指定为多大,都不合适
import java. io. FileInputStream;
import java. io. FileNotFoundException;
import java. io. FileOutputStream;
import java. io. IOException;
public class Demo_15 {
public static void main ( String[ ] args) throws IOException {
FileInputStream fis = new FileInputStream ( "char/char.txt" ) ;
byte [ ] b = new byte [ 3 ] ;
int i;
while ( ( i = fis. read ( b) ) != - 1 ) {
String string = new String ( b) ;
System. out. println ( string) ;
}
}
private static void test_3 ( ) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream ( "char/char.txt" ) ;
byte [ ] b = new byte [ 2 ] ;
int i;
while ( ( i = fis. read ( b) ) != - 1 ) {
String string = new String ( b) ;
System. out. println ( string) ;
}
}
private static void test_2 ( ) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream ( "char/char.txt" ) ;
int i;
while ( ( i = fis. read ( ) ) != - 1 ) {
System. out. println ( ( char ) i) ;
}
fis. close ( ) ;
}
private static void test_1 ( ) throws FileNotFoundException, IOException {
FileOutputStream fos = new FileOutputStream ( "char/ch.txt" ) ;
byte [ ] bytes = "中国,我爱你" . getBytes ( ) ;
fos. write ( bytes) ;
fos. close ( ) ;
}
}
解决方式
1、出现乱码原因:
每次不知道读取多少个字节,转成字符
在创建数组的时候,将每次要读取的字节个数写死了
2、解决:
动态判断每次应该读取多少个字节
在GBK编码中,如果读到的是一个英文,占一个字节,返回的一定是一个正数。直接转成字符即可
在GBK编码中,如果读到的是一个中文,占两个字节,读取到的第一个字节一定是一个byte类型的负数,如果读到的是一个负数了,需要再读取一个字节,将这两个字节信息,转成一个中文字符。
3、在工程中做这些底层的操作没有必要,太复杂,在jdk中给我们提供了好解决方案
使用字符流即可:字符流就是针对字符进行操作的。
不仅能够动态判断GBK编码中每个字符是中文还是英文,还可以判断其他编码表中的
import java. io. FileInputStream;
import java. io. FileNotFoundException;
import java. io. FileOutputStream;
import java. io. IOException;
public class Demo_15 {
public static void main ( String[ ] args) throws IOException {
FileInputStream fis = new FileInputStream ( "char/char.txt" ) ;
int i;
while ( ( i = fis. read ( ) ) != - 1 ) {
byte b = ( byte ) i;
if ( b > 0 ) {
System. out. println ( ( char ) b) ;
} else {
byte read = ( byte ) fis. read ( ) ;
byte [ ] bb = { b, read} ;
String string = new String ( bb) ;
System. out. println ( string) ;
}
}
}
private static void test_4 ( ) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream ( "char/char.txt" ) ;
byte [ ] b = new byte [ 3 ] ;
int i;
while ( ( i = fis. read ( b) ) != - 1 ) {
String string = new String ( b) ;
System. out. println ( string) ;
}
}
private static void test_3 ( ) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream ( "char/char.txt" ) ;
byte [ ] b = new byte [ 2 ] ;
int i;
while ( ( i = fis. read ( b) ) != - 1 ) {
String string = new String ( b) ;
System. out. println ( string) ;
}
}
private static void test_2 ( ) throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream ( "char/char.txt" ) ;
int i;
while ( ( i = fis. read ( ) ) != - 1 ) {
System. out. println ( ( char ) i) ;
}
fis. close ( ) ;
}
private static void test_1 ( ) throws FileNotFoundException, IOException {
FileOutputStream fos = new FileOutputStream ( "char/ch.txt" ) ;
byte [ ] bytes = "中国,我爱你" . getBytes ( ) ;
fos. write ( bytes) ;
fos. close ( ) ;
}
}
字符流的使用
1、抽象顶层父类:Reader Writer
2、子类类型:FileReader,FileWriter
3、常用方法;
Reader:
read();,一次读取一个字符,读到的是-1,表示读到文件末尾
read(char[] ch)将字符流中的内容,读取到ch字符数组中
Writer:
write(int c) 写出单个字符
write(String str)写出字符串
write(char[] arr)将字符数组进行写出
Write(char[] arr,int off,int len)将字符数组的一部分进行写出
import java. io. FileNotFoundException;
import java. io. FileReader;
import java. io. FileWriter;
import java. io. IOException;
import java. io. Reader;
import java. io. Writer;
public class Demo_16 {
public static void main ( String[ ] args) throws IOException {
Reader r = new FileReader ( "char/char.txt" ) ;
int i;
while ( ( i = r. read ( ) ) != - 1 ) {
System. out. println ( ( char ) i) ;
}
Writer w = new FileWriter ( "char/w.txt" ) ;
w. write ( 97 ) ;
w. write ( 23929 ) ;
w. write ( "美国特朗普" ) ;
char [ ] chs = { '喊' , '子' , '我' , '子' , '还' , '域' } ;
w. write ( chs) ;
w. write ( '\n' ) ;
w. write ( chs, 0 , 3 ) ;
w. close ( ) ;
}
}