练习题:
1、列出某个目录的所有下一级,如果它的下一级仍然是目录,再列出下一级的下一级,依次类推
2、求出某个目录的总大小
length()只能得到文件的大小。目录的大小无法直接用它得到。
目录的总大小:把它的下一级的大小累加起来就是它的总大小
3、删除一个非空目录
delete()只能删除文件或空目录
非空目录的删除:把它的下一级先请空,然后删除自己。
public class TestDigui {
@Test
public void test01(){
File dir = new File("D:\\尚硅谷_191213Java班_柴林燕_JavaSE");
listAllSubs(dir);
}
/*
第一次调用listAllSubs()时,f代表的是D:\\尚硅谷_191213Java班_柴林燕_JavaSE
File[] files = f.listFiles(); 得到的是
D:\尚硅谷_191213Java班_柴林燕_JavaSE\API
D:\尚硅谷_191213Java班_柴林燕_JavaSE\english_words
D:\尚硅谷_191213Java班_柴林燕_JavaSE\libs
D:\尚硅谷_191213Java班_柴林燕_JavaSE\ppt
D:\尚硅谷_191213Java班_柴林燕_JavaSE\resources
D:\尚硅谷_191213Java班_柴林燕_JavaSE\software
D:\尚硅谷_191213Java班_柴林燕_JavaSE\预习笔记
D:\尚硅谷_191213Java班_柴林燕_JavaSE\预装软件
for (File sub : files) {
System.out.println(sub);
}
每一次循环,sub依次代表一个
第二次调用: listAllSubs(),f可能代表 D:\尚硅谷_191213Java班_柴林燕_JavaSE\API
File[] files = f.listFiles(); 得到的是
Java Platform SE 8.chm
JAVA_API_1.8_CHS.CHM
....
for (File sub : files) {
System.out.println(sub);
}
每一次循环,sub依次代表一个
....
*/
public void listAllSubs(File f){
//如果f是目录,就要获取f的下一级
if(f.isDirectory()){
File[] files = f.listFiles();
for (File sub : files) {
listAllSubs(sub);
}
}
System.out.println(f);
}
@Test
public void test02(){
File dir = new File("D:\\尚硅谷_191213Java班_柴林燕_JavaSE");
long directorySize = getDirectorySize(dir);
System.out.println(dir + "的大小是:" + directorySize + "字节");//2,102,328,630 字节
}
public long getDirectorySize(File f){
if(f.isDirectory()){
//f是目录,把它的下一级的大小累加起来就是f的总大小
//(1)得到f的下一级
File[] files = f.listFiles();
long sum = 0;
for (File sub : files) {
// sum += sub.length();//错误的,因为sub可能是文件,也可能是目录
sum += getDirectorySize(sub);
}
return sum;
}
return f.length();
}
@Test
public void test03(){
// File dir = new File("d:/尚硅谷_191213Java班_柴林燕_JavaSE - 副本");
File dir = new File("d:/img");
forceDeleteDir(dir);
}
public void forceDeleteDir(File f){
//如果f是非空目录,先删除非空目录的下一级
if(f.isDirectory()){
//(1)获取f的下一级
File[] files = f.listFiles();
//(2)遍历files,挨个儿删除下一级
for (File sub : files) {
//调用forceDeleteDir删除每一个下一级
forceDeleteDir(sub);
}
//(3)经过上面的代码f,不管是空目录还是非空目录,现在都变成空目录
}
//如果f是文件,或空目录
f.delete();
}
}
4、目录的遍历
(1)String[] list():列出目录的所有子目录或文件的名称,包括隐藏的文件和目录
(2)File[] listFiles():列出目录的所有子目录或文件的路径名,包括隐藏的文件和目录
(3)File[] listFiles(FileFilter filter) :可以过滤不满足条件的目录或文件
(4)File[] listFiles(FilenameFilter filter)
public class TestDirectoryList {
@Test
public void test04() {
File dir = new File("d:/");
File[] list = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
//pathname就是代表dir目录的下一级的子目录名或文件名
//当目录中的子目录或文件满足条件时,就返回true,表示保留这个子目录或文件
return pathname.isFile() && pathname.getName().endsWith(".java");
}
});//匿名内部类实现FileFilter接口
for (File s : list) {
System.out.println(s );
}
//d:\Hello.java
}
@Test
public void test03() {
File dir = new File("d:/");
File[] list = dir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
//pathname就是代表dir目录的下一级的子目录名或文件名
//当目录中的子目录或文件满足条件时,就返回true,表示保留这个子目录或文件
return pathname.isFile();
}
});//匿名内部类实现FileFilter接口
for (File s : list) {
System.out.println(s );
}
/*
d:\Hello.java
d:\hello.txt
d:\pagefile.sys
*/
}
@Test
public void test02() {
File dir = new File("d:/");
File[] list = dir.listFiles();
for (File s : list) {
System.out.println(s + "是文件吗?" + s.isFile());
}
}
/* @Test
public void test02() {
File dir = new File("d:/");
String[] list = dir.list();
for (String s : list) {
System.out.println(s + "是文件吗?" + s.isFile());//s是String类型
}
}*/
@Test
public void test(){
File dir = new File("d:/");
String[] list = dir.list();
for (String s : list) {
System.out.println(s);
}
/*
$RECYCLE.BIN
1213
atguigu
hello.txt
LocalRepository
pagefile.sys
prepare
ProgramFiles
ProgramFiles (x86)
QMDownload
software
System Volume Information
work
尚硅谷_191213Java班_柴林燕_JavaSE
尚硅谷_191213Java班_柴林燕_MySQL_JDBC
*/
}
}
集合章的重要性:*****
IO整章的重要性:***
为什么没那么重要?后期开发都把它这张的API给再次封装了,封装到各种工具包里了。
面试题中出现的频率没有集合等章节高,主要集中在:编码解码IO流,对象序列化IO流。
一、java.io.File类
1、File类:文件和目录路径名的抽象表示形式。
解读:(1)File类的对象,是代表一个文件或者是目录(文件夹)。
当然这个文件或目录可能在硬盘中是存在的,也可能是不存在的。但是这个对象在内存中是存在的。
(2)如何表示一个文件或目录,不管它是否存在呢?
使用文件或目录的路径名来表示。
例如:d:/1.txt d:/atguigu
2、常用的API
(1)getName():获取文件或目录名 不管文件或目录是否存在都可以获取,因为在new File对象是我们已经指定了。
以下这些属性,当文件/目录不存在时,都是默认值,如果文件或目录存在,就取真实的值
(2)long length():获取文件的大小,单位是字节 不能获取目录的的大小
(3)long lastModified():获取文件或目录的最后修改时间,单位是毫秒
(4)boolean isFile():是否是文件
(5)boolean isDirectory():是否是目录
(6)boolean canRead():是否可读
(7)boolean canWrite():是否可写
(8)boolean isHidden():是否隐藏
(9)boolean exists():是否存在
(10)路径问题
A:构造路径:在你new File对象时指定的路径,就是构造路径,和这个文件或目录是否存在无关
B:绝对路径:
从根目录开始导航就是绝对路径
C:相对路径:相对于当前项目/模块开始导航的路径
例如:D:\atguigu\javaee\JavaSE20191213\code\1213Javacode\day23_teacher_code
D:规范路径:会把路径中类似于:…或.或/开头等路径进行解析
…:代表上一级
/开头:代表根目录,这个在web开发,或者linux,mac IOS中的/都是代表根目录
.:代表当前目录
结论:构造路径:在你new File对象时指定的路径,就是构造路径,和这个文件或目录是否存在无关
绝对路径:一定是从根目录开始导航的,如果你new对象时传入的是相对路径,那么就会从项目根目录开始导航。
规范路径:如果你new File对象时,指定的就是规范路径,那么它和绝对路径一样,
如果你new File对象时,指定的是非规范路径,那么会对…等进行解析
public class TestFile {
@Test
public void test06() throws IOException {
//Java中\是需要转义的
File file = new File("..\\..\\..\\Download\\2.txt");//相对路径:并没有从根目录开始,从任意一级目录开始
System.out.println("文件的路径信息,构造路径:" + file.getPath());//..\..\..\Download\2.txt
System.out.println("绝对路径:" + file.getAbsolutePath());//D:\atguigu\javaee\JavaSE20191213\code\1213Javacode\day23_teacher_code\..\..\..\Download\2.txt
System.out.println("规范路径:" + file.getCanonicalPath());//D:\atguigu\javaee\JavaSE20191213\Download\2.txt
}
@Test
public void test05() throws IOException {
//Java中\是需要转义的
File file = new File("Download\\2.txt");//相对路径:并没有从根目录开始,从任意一级目录开始
System.out.println("文件的路径信息,构造路径:" + file.getPath());//Download\2.txt
System.out.println("绝对路径:" + file.getAbsolutePath());//D:\atguigu\javaee\JavaSE20191213\code\1213Javacode\day23_teacher_code\Download\2.txt
System.out.println("规范路径:" + file.getCanonicalPath());//D:\atguigu\javaee\JavaSE20191213\code\1213Javacode\day23_teacher_code\Download\2.txt
}
@Test
public void test04() throws IOException {
//Java中\是需要转义的
File file = new File("D:\\QMDownload\\Download\\2.txt");//绝对路径:从根目录开始一直往下导航到对应的文件夹或目录
System.out.println("文件的路径信息,构造路径:" + file.getPath());//D:\QMDownload\Download\2.txt
System.out.println("绝对路径:" + file.getAbsolutePath());//D:\QMDownload\Download\2.txt
System.out.println("规范路径:" + file.getCanonicalPath());//D:\QMDownload\Download\2.txt
}
@Test
public void test03(){
//表示D盘下atguigu文件夹
File dir = new File("d:/atguigu");
System.out.println("atguigu文件夹的大小:" + dir.length());
}
@Test
public void test02(){
//表示D盘下1.txt文件
File file = new File("d:/1.txt");//这个文件不存在,不影响我new对象
System.out.println("文件的名称:" + file.getName());
System.out.println("文件的大小:" + file.length());
/*
和大小/长度有关:数组的大小/长度:数组.length属性
字符串的长度:字符串.length();
集合的大小:集合.size()
文件的大小:文件.length()
*/
System.out.println("最后修改时间:" + file.lastModified());
System.out.println("file是代表一个文件吗?" + file.isFile());
System.out.println("file是代表一个目录吗?" + file.isDirectory());
System.out.println("文件可读吗:" + file.canRead());
System.out.println("文件可写吗:" + file.canWrite());
System.out.println("是隐藏文件吗?" + file.isHidden());
System.out.println("文件存在码?" + file.exists());
/*
当文件不存在时:
文件的名称:1.txt
文件的大小:0
最后修改时间:0
file是代表一个文件吗?false
file是代表一个目录吗?false
文件可读吗:false
文件可写吗:false
是隐藏文件吗?false
文件存在码?false
当文件存在的时候:
文件的名称:1.txt
文件的大小:22
最后修改时间:1578965853497 毫秒值,距离1970年1月1日凌晨的毫秒值
file是代表一个文件吗?true
file是代表一个目录吗?false
文件可读吗:true
文件可写吗:true
是隐藏文件吗?false
文件存在码?true
*/
}
@Test
public void test01(){
//表示D盘下1.txt文件
File file = new File("d:/1.txt");//这个文件不存在,不影响我new对象
//表示D盘下atguigu文件夹
File dir = new File("d:/atguigu");
}
}
3、文件和目录的创建、删除、重命名等操作
(1)createNewFile():只能创建文件,不能创建目录
(2)mkdir():创建目录
(3)mkdirs():创建目录,但是如果这个目录的父目录不存在,也一并创建
(4)delete():删除文件或目录
如果目录非空,使用delete是无法直接删除的
(5)renameTo(File dest)
(6)static File createTempFile(String prefix, String suffix) :创建临时目录
在默认临时目录中生成:C:\Users\Irene\AppData\Local\Temp
static File createTempFile(String prefix, String suffix, File directory)
在指定目录中生成临时文件
(7)void deleteOnExit() :在退出程序时删除
一般会配合void deleteOnExit() 使用
public class TestFileCreate {
@Test
public void test08() throws IOException, InterruptedException {
File file = File.createTempFile("atguigu", null);
Thread.sleep(3000);
file.deleteOnExit();
}
@Test
public void test07() throws IOException {
File file =new File("d:/1.txt");
File dest = new File("d:/hello.txt");
System.out.println("重名名之前:"+ file.length());//46
file.renameTo(dest);
System.out.println("重名名之后:"+ file.length());//0 file对象已经被重名了,不存在了
}
@Test
public void test06() throws IOException {
File file =new File("d:/QMDownload");
file.delete();
}
@Test
public void test05() throws IOException {
File file =new File("d:/1.txt");
file.delete();
}
@Test
public void test04() throws IOException {
File file =new File("d:/chailinyan");
file.delete();
}
@Test
public void test03() throws IOException {
//file对象代表的是code这个目录,不能代表三个目录
//其中1213,java是为了描述code目录的路径,它是父目录
File file =new File("d:/1213/java/code");
// file.mkdir();
file.mkdirs();
}
@Test
public void test02() throws IOException {
File file =new File("d:/chailinyan");
file.mkdir();
}
@Test
public void test01() throws IOException {
File file =new File("d:/1.txt");
file.createNewFile();//当路径有问题,或者说没有权限等原因会导致文件创建失败,就报异常
}
}
二、java.io包的各种IO流
1、什么是IO流?
I:Input:数据的读取、输入
O:Output:数据的写、输出
IO:数据的输入和输出、数据的读和写
数据的读取:可以从指定的文件读取,可以从网络接收,可以从一块内存读取到另一块内存…
数据的写:可以写入指定的文件,可以发送到网络的某个端点(服务器端或客户端),也可以从一块内存写到另一块内存…
后面要学习的web,数据库都要用到IO,只不过是它们底层用到了,我们上层看不见这个代码,除非看底层源码。
IO流:数据的输入、输出的“通道”,即相关的类型
2、传统的IO流的分类
(1)按照方向分:
输入流和输出流。
输入流:我们的程序只能从输入流中读取数据。
输出流:我们的程序只能把数据写到输出流中,不能从输出流中读数据。
(2)按照处理的数据的方式不同
字节流和字符流。
字节流:适用于处理任意类型的数据。以字节为单位。可以一个字节一个字节处理,也可以多个字节一起处理。
字符流:只能用于处理纯文本数据。以字符为单位。可以一个字符一个字符处理,也可以多个字符一起处理。
纯文本的数据:就是字符串(String)、字符char
纯文本文件:.txt, .html, .css, .js, .xml, .java 等
非纯文本文件:.class, .jpg等图片, .avi等视频, .doc,.ppt,.xls等文档,.exe等
(3)按照IO流的作用不同
节点流和处理流。
节点流:从数据节点读取数据,或把数据写到数据节点中。
数据节点:例如:文件,数组等可以装数据的容器。
处理流:用于装饰节点流,在节点流的基础上增加辅助的功能,例如:缓冲功能、序列化和反序列化、编码与解码功能等
处理流是必须结合节点流才能使用的。
反过来,节点流可以单独工作。
3、IO流的四大抽象基类:
InputStream:字节输入流,只能从这个系列的类型的IO中读取字节数据
OutputStream:字节输出流,针对它,只能写出,输出字节数据。
Reader:字符输入流,只能从这个系列的类型的IO中读取字符数据
Writer:字符输出流,针对它,只能写出,输出字符数据。
4、派生其他的IO流
(1)文件IO流
FileInputStream:文件字节输入流,以字节的方式从文件中读取数据
FileOutputStream:文件字节输出流,以字节的方式把数据写到文件中,输出到文件中
FileReader:文件字符输入流,以字符的方式从文件中读取数据
FileWriter:文件字符输出流,以字符的方式把数据写到文件中,输出到文件中
(2)缓冲IO流
BufferedInputStream:字节缓冲输入流,专门给InputStream系列的输入流增加缓冲功能
BufferedOutputStream:字节缓冲输出流,专门给OutputStream系列的输出流增加缓冲功能
BufferedReader:字符缓冲输入流,专门给Reader系列的输入流增加缓冲功能
BufferedWriter:字符缓冲输出流,专门给Writer系列的输出流增加缓冲功能
(3)编码与解码IO流
InputStreamReader:解码IO流,把原先InputStream系列字节输入流的字节数据转换为Reader系列字符输入流的字符数据,读入。
OutputStreamWriter:编码IO流,把原先Writer系列字符输出流的字符数据转为为OutputStream系列字节输出流的字节数据,写出。
(4)数据IO流
DataInputStream:数据字节输入流,以字节的方式读取Java的各种基本数据类型的数据和字符串。
DataOutputStream:数据字节输出流,以字节的方式写出Java的各种基本数据类型的数据和字符串。
(5)对象IO流
ObjectInputStream:对象的字节输入流,以字节的方式读取一个Java对象。
ObjectOutputStream:对象的字节输出流,以字节的方式输出一个Java对象。
(6)打印流
PrintStream:字节输出流
PrintWriter:字符输出流
(8)文本扫描仪:
Scanner:从指定的输入流中读取数据
例如:System.in中读取数据
三、文件IO流
1、FileInputStream:
是InputStream的子类,用于从文件读取数据,按字节的方式读取
字节输入流既可以读取纯文本文件,也可以读取其他类型的文件。
步骤:
(1)创建IO流对象
创建FileInputStream的对象,并且指定从哪个文件读取数据
(2)读取
从输入流中读取
A:int read():一次读取一个字节,如果有数据,返回读取到的字节数据的值,如果流中已经没有数据了,返回-1
B:int read(byte[] data):一次读取多个字节。返回的是本次读取的字节的数量。如果流中已经没有数据了,返回-1
一次最多读取data.length个,如果流中的数据没有data.length个,那就有几个读取几个。
把数据从流中读取后,临时存储到data数组中,从data[0]开始存。
C:int read(byte[] data, int off, int count):一次读取多个字节。返回的是本次读取的字节的数量。如果流中已经没有数据了,返回-1
一次最多读取count个,如果流中的数据没有count个,那就有几个读取几个。
把数据从流中读取后,临时存储到data数组中,从data[off]开始存。
(3)关闭IO流
close()
public class TestFileInputStream {
@Test
public void test04() throws IOException {
FileInputStream fis = new FileInputStream("D:\\QMDownload\\img\\下载.jpg");
int result;
byte[] data = new byte[1024];
while((result = fis.read(data))!=-1){
System.out.println(result);
// System.out.println(new String(data,0,result));//在控制台无法用字符显示图片的内容,除非把字节数据,传给图片查看工具才可以显示图片
}
fis.close();
}
@Test
public void test03() throws IOException {
//读取d:/1.txt文件
//路径:d:/1.txt 或 d:\\1.txt
FileInputStream fis = new FileInputStream("d:/1.txt");
//读取时文件不存在会报错
int result;
byte[] data = new byte[4];
while((result = fis.read(data))!=-1){
// System.out.println(result);//读取的字节数
// System.out.println(Arrays.toString(data));//显示字节的值
//String(byte[] bytes)
//String(byte[] bytes, int offset, int length)
System.out.println(new String(data,0,result));//字节数组的数据,如何显示为字符串
}
fis.close();
}
@Test
public void test02() throws IOException {
//读取d:/1.txt文件
//路径:d:/1.txt 或 d:\\1.txt
FileInputStream fis = new FileInputStream("d:/1.txt");
int result;
while((result = fis.read())!=-1){
System.out.println(result);
}
fis.close();
}
//FileNotFoundException是IOException的子类,都是编译时异常
@Test
public void test01() throws IOException {
//读取d:/1.txt文件
//路径:d:/1.txt 或 d:\\1.txt
FileInputStream fis = new FileInputStream("d:/1.txt");
System.out.println(fis.read());//104 104是h的编码值
System.out.println(fis.read());//101 101是e的编码值
System.out.println(fis.read());//108 108是l的编码值
System.out.println(fis.read());//108 108是l的编码值
System.out.println(fis.read());//111 111是o的编码值
System.out.println(fis.read());//-1 -1表示流中没有数据了
fis.close();
}
}
2、FileOutputStream:
是OutputStream的子类,按照字节输出内容到文件中
步骤:
(1)创建IO流对象
创建FileOutputStream对象,告知写出到哪个文件中
(2)输出内容
A:write(int b):写一个字节
B:write(byte[] data):写整个字节数组
C:write(byte[] data,int offset, int count):写出data[offset]开始的count个字节
(3)关闭IO流
close()
public class TestFileOutputStream {
@Test
public void test02() throws IOException {
//写 今天是放假倒数第三天 到 项目的day23_teacher_code模块的根目录下的2.txt文件中
FileOutputStream fos = new FileOutputStream("upload/2.txt");//相对路径表示方式
//文件不存在,会自动创建
//目录不存在,会报错
String str = "今天是放假倒数第三天";
//如何把字符串转为字节数组?
//byte[] getBytes()
byte[] bytes = str.getBytes();
fos.write(bytes);
fos.close();
}
@Test
public void test01() throws IOException {
//写 今天是放假倒数第三天 到 项目的day23_teacher_code模块的根目录下的2.txt文件中
FileOutputStream fos = new FileOutputStream("2.txt");//相对路径表示方式
//文件不存在,会自动创建
//目录不存在,会报错
String str = "今天是放假倒数第三天";
//如何把字符串转为字节数组?
//byte[] getBytes()
byte[] bytes = str.getBytes();
fos.write(bytes);
fos.close();
}
}
3、FileReader:
是Reader的子类,只能读取纯文本文件
步骤:
(1)创建FileReader对象
(2)读取
从输入流中读取
A:int read():一次读取一个字符,如果有数据,返回读取到的字符数据的值,如果流中已经没有数据了,返回-1
B:int read(char[] data):一次读取多个字符。返回的是本次读取的字符的数量。如果流中已经没有数据了,返回-1
一次最多读取data.length个,如果流中的数据没有data.length个,那就有几个读取几个。
把数据从流中读取后,临时存储到data数组中,从data[0]开始存。
C:int read(char[] data, int off, int count):一次读取多个字符。返回的是本次读取的字符的数量。如果流中已经没有数据了,返回-1
一次最多读取count个,如果流中的数据没有count个,那就有几个读取几个。
把数据从流中读取后,临时存储到data数组中,从data[off]开始存。
乱码的原因:
(1)缺字节
(2)编码方式不对
public class TestFileReader {
@Test
public void test02() throws IOException {
FileReader fr = new FileReader("d:/1.txt");
char[] data = new char[3];
int len;
while((len = fr.read(data)) != -1){
System.out.println(new String(data,0,len));//len表示读取了几个字符
}
fr.close();
}
@Test
public void test01() throws IOException {
FileReader fr = new FileReader("d:/1.txt");
System.out.println(fr.read());//读取一个字符,读取的是字符的编码值,如果是汉字也是整个汉字的Unicode编码值
}
}
4、FileWriter:
是Writer的子类,把数据以字符、字符串的方式写到文件中
步骤:
(1)创建IO流对象
创建FileWriter对象,告知写出到哪个文件中
(2)输出内容
A:write(int b):写一个字符
B:write(char[] data):写整个字符数组
C:write(char[] data,int offset, int count):写出data[offset]开始的count个字符
(3)关闭IO流
close()
public class TestFileWriter {
@Test
public void test01() throws IOException {
//true:表示追加方式,即在原来文件末尾接着写
FileWriter fw = new FileWriter("1.txt",true);//相对路径
//输出一句话,电脑该换了
String str = "过年等着大家发红包买电脑";
fw.write(str);
fw.close();
}
@Test
public void test02() throws IOException {
FileWriter fw = new FileWriter("1.txt");//相对路径
//输出一句话,电脑该换了
String str = "过年等着大家发红包买电脑";
fw.write(str);
fw.close();
}
}
四、缓冲IO流
1、BufferedInputStream:
字节缓冲输入流,专门给InputStream系列的输入流增加缓冲功能
2、BufferedOutputStream:
字节缓冲输出流,专门给OutputStream系列的输出流增加缓冲功能
3、BufferedReader:
字符缓冲输入流,专门给Reader系列的输入流增加缓冲功能
比父类增加了一个方法:String readLine()
4、BufferedWriter:
字符缓冲输出流,专门给Writer系列的输出流增加缓冲功能
比父类增加了一个方法:void newLine()
作用:提高效率
private static int DEFAULT_BUFFER_SIZE = 8192;默认缓冲大小
byte[]
char[]
public class TestBuffer {
@Test
public void test01() throws IOException {
FileInputStream fis = new FileInputStream("1.txt");
//给fis这个字节输入流,增加缓冲功能,把数据先放到bis的缓冲区中
BufferedInputStream bis = new BufferedInputStream(fis);
//数据:1.txt==>fis==>bis
//接下来的程序,应该从bis输入流中读取数据
byte[] data = new byte[1024];
int len;
while((len = bis.read(data))!=-1){
System.out.println(new String(data,0,len));
}
// BufferedInputStream bis = new BufferedInputStream(fis);bis是外面的,fis是里面的
//关闭的顺序,先关外面的,再关里面的
bis.close();
fis.close();
}
@Test
public void test02() throws IOException{
FileOutputStream fos = new FileOutputStream("1.txt",true);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//数据:程序==>bos==>fos==>1.txt
bos.write("马上放假了".getBytes());
bos.close();
fos.close();
}
@Test
public void test03() throws IOException{
FileReader fr = new FileReader("1.txt");
BufferedReader br = new BufferedReader(fr);
//数据:1.txt==>fr==>br==>程序data
char[] data = new char[1024];
int len;
while((len = br.read(data))!=-1){
System.out.println(new String(data,0,len));
}
br.close();
fr.close();
}
@Test
public void test033() throws IOException{
FileReader fr = new FileReader("1.txt");
BufferedReader br = new BufferedReader(fr);
//数据:1.txt==>fr==>br==>程序
String str;
//null表示到达流末尾了,不是说空行
while((str = br.readLine()) != null){
System.out.println(str);
}
br.close();
fr.close();
}
@Test
public void test04() throws IOException {
FileWriter fw = new FileWriter("1.txt",true);
BufferedWriter bw = new BufferedWriter(fw);
//数据:程序==>bw==>fw==>1.txt
// bw.write("\r\n");//输出换行符
bw.newLine();//输出换行符
bw.write("玩游戏必须上报");
bw.flush();//刷新
bw.close();//如果没有刷新,没有关闭缓冲流,很可能数据在缓冲区中没有正式写出
fw.close();
}
}
public class FileUtils {
/**
* 从srcFilePath文件中复制生成destFilePath
* @param srcFilePath String:源文件的路径名
* @param destFilePath String:目标文件的路径名
*/
public static void copy(String srcFilePath, String destFilePath)throws IOException {
long start = System.currentTimeMillis();
//选择什么IO流:字节流还是字符流,这里选择字节流,因为没有说一定是纯文本文件
//复制文件:既需要读取又需要写
FileInputStream fis = new FileInputStream(srcFilePath);
FileOutputStream fos = new FileOutputStream(destFilePath);
//一边读从fis输入流中读取数据,一边写到fos输出流中
//每次读取多个字节
byte[] data = new byte[1024];
int len;
//从fis读取的数据临时存储在data中
while((len = fis.read(data)) != -1){
//从data数组中取出来,写到fos中
fos.write(data,0,len);
}
//关闭
fis.close();
fos.close();
long end = System.currentTimeMillis();
System.out.println("没有使用缓冲流的时间:" + (end-start));
}
public static void copyBuffer(String srcFilePath, String destFilePath)throws IOException {
long start = System.currentTimeMillis();
//选择什么IO流:字节流还是字符流,这里选择字节流,因为没有说一定是纯文本文件
//复制文件:既需要读取又需要写
FileInputStream fis = new FileInputStream(srcFilePath);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(destFilePath);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//srcFilePath文件==>fis==>bis ==>程序的data==> bos==>fos==>destFilePath
//每次读取多个字节
byte[] data = new byte[1024];
int len;
//从fis读取的数据临时存储在data中
while((len = bis.read(data)) != -1){
//从data数组中取出来,写到fos中
bos.write(data,0,len);
}
//关闭
bis.close();
fis.close();
bos.close();
fos.close();
long end = System.currentTimeMillis();
System.out.println("使用缓冲流的时间:" + (end-start));
}
}
public class TestFileUtils {
public static void main(String[] args) throws IOException {
FileUtils.copy("D:\\software\\IDEA\\ideaIU-Ultimate-2019.2.3.exe","d:\\1.exe");
//没有使用缓冲流的时间:23048毫秒
FileUtils.copyBuffer("D:\\software\\IDEA\\ideaIU-Ultimate-2019.2.3.exe","d:\\2.exe");
//使用缓冲流的时间:4947毫秒
}
}
五、编码与解码IO流
1、解码IO流:InputStreamReader
从字节流中读取数据,按照指定的编码方式,解码为字符流
2、编码IO流
从字符流中写出数据,按照指定的编码方式,编码为字节流
编码:
把字符/字符串==>字节序列的过程
解码:
把字节==>字符/字符串的过程
人只能看懂字符/字符串,机器只识别字节。
public class TestTransfer {
@Test
public void test04() throws IOException {
FileOutputStream fos = new FileOutputStream("d:/1.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");
//数据:程序==》osw ==>按照指定的编码,把数据从字符转为字节==> fos ==> d:/1.txt
osw.write("大家都着急了");
osw.close();
fos.close();
}
@Test
public void test03() throws IOException {
FileWriter fw = new FileWriter("d:/1.txt",true);
fw.write("大家都着急了");
fw.close();
}
@Test
public void test02() throws IOException {
//如果需要解码,按照GBK进行解码
//在内存中解码,不是在文件中间解码
//先把文件中的数据 原样(按照字节读取) 读取到内存,然后再内存中进行解码
FileInputStream fis = new FileInputStream("d:/1.txt");
//数据已经从d:/1.txt ==> fis(字节)在内存中
//从fis读取字节数据的过程中进行解码为字符
InputStreamReader isr = new InputStreamReader(fis,"GBK");//isr从fis中读取数据,并按照指定的编码方式进行解码为字符
//接下来的程序就要重isr中读取数据
char[] data = new char[10];
int len;
while((len = isr.read(data))!=-1){
System.out.println(new String(data,0,len));
}
isr.close();
fis.close();
}
@Test
public void test01() throws IOException {
//d:/1.txt是GBK
//程序是UTF-8
//FileReader只会按照程序中的编码方式进行解码,无法手动指定编码
FileReader fr = new FileReader("d:/1.txt");
char[] data = new char[10];
int len;
while((len = fr.read(data))!=-1){
System.out.println(new String(data,0,len));
}
fr.close();
}
}
六、数据IO流
DataInputStream:
数据字节输入流,以字节的方式读取Java的各种基本数据类型的数据和字符串。
DataOutputStream:
数据字节输出流,以字节的方式写出Java的各种基本数据类型的数据和字符串。
DataInputStream给InputStream系列的IO流增加辅助功能,可以处理Java的各种基本数据类型的数据
DataOutputStream给OutputStream系列的IO流增加辅助功能,可以处理Java的各种基本数据类型的数据
public class TestDataIO {
@Test
public void test04() throws IOException {
FileInputStream fis = new FileInputStream("d:/ban.txt");
DataInputStream dis = new DataInputStream(fis);
//数据:d:/ban.txt==》fis==>dis==>程序
String name = dis.readUTF();
int age = dis.readInt();
char gender = dis.readChar();
double weight = dis.readDouble();
boolean marry = dis.readBoolean();
System.out.println(name);
System.out.println(age);
System.out.println(gender);
System.out.println(weight);
System.out.println(marry);
dis.close();
fis.close();
}
@Test
public void test03() throws IOException {
//写到文件中,并且要按照对应的数据类型写出
String name = "小张";
int age = 28;
char gender = '男';
double weight = 65.5;
boolean marry = true;
FileOutputStream fos = new FileOutputStream("d:/ban.txt");
DataOutputStream dos = new DataOutputStream(fos);
//数据:程序==>dos==>fos==>d:/ban.txt
//这里写出去的不是纯文本数据,使用.txt的后缀,用文本编辑打开,也是无法还原数据,即看不懂
//只有再次使用Java的程序读取到程序中才能正确识别。因为它里面不仅有数据,还有Java的数据类型的信息
//所以使用普通的文本编辑是无法打开。
dos.writeUTF(name);
dos.writeInt(age);
dos.writeChar(gender);
dos.writeDouble(weight);
dos.writeBoolean(marry);
dos.close();
fos.close();
}
@Test
public void test02() throws IOException {
FileReader fr = new FileReader("d:/ban.txt");
// fr.read()//无法区分每一项数据有几个字符
}
@Test
public void test01() throws IOException {
//写到文件中,并且要按照对应的数据类型写出
String name = "小张";
int age = 28;
char gender = '男';
double weight = 65.5;
boolean marry = true;
/* FileOutputStream fos = new FileOutputStream("d:/ban.txt");
fos.write(name.getBytes());
fos.write(age);
fos.write(gender);
fos.write(weight);
fos.write(marry);*/
FileWriter fw = new FileWriter("d:/ban.txt");
fw.write(name);
fw.write(age);//把age的值当成字符编码值写出
fw.write(gender);
fw.write(weight+"");
fw.write(marry+"");
fw.close();
}
}