IO流(一)
1、File、IO流概述、File文件对象的创建
File
File是java.io.包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件、或文件夹)。
获取文件信息(大小,文件名,修改时间)
创建文件/文件夹
删除文件/文件夹
判断文件的类型
注意:File只能对文件本身进行操作,不能读写文件里面的数据
IO流:
用于读写数据的(可以读文件、网络中的数据...)
创建File类的对象
构造器 | 说明 |
public File(String pathname) | 根据文件路径创建文件对象 |
public File(String parent, String child) | 根据父路径和子路径名字创建文件对象 |
public File(Fileparent, String child) | 根据父路径对应文件对象和子路径名称创建文件对象 |
package Demo04;import java.io.File;public class Test {public static void main(String[] args) {//1、创建一个File对象指代某个具体文件//File f1 = new File("/Users/harry/JavaStudy/untitled/src/Demo04/abc.txt");System.out.println(f1.length());File f2 = new File("D:/resources");System.out.println(f2.length());//注意File对象可以指代一个人不存在的文件路径File f3 = new File("D:/aaa.txt");System.out.println(f3.length());}
}
2、File类常用方法
package Demo01;import java.io.File;public class Test {public static void main(String[] args) {//1.创建文件对象,指代某个文件File f1 = new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test");//2.判断文件是否存在System.out.println(f1.exists());//3.判断是否是文件System.out.println(f1.isFile());//4.判断是否是目录System.out.println(f1.isDirectory());//5.获取文件名称System.out.println(f1.getName());//6.获取文件大小System.out.println(f1.length());//7.获取文件最后一次修改时间System.out.println(f1.lastModified());//8.获取文件路径System.out.println(f1.getPath());//9.获取绝对路径System.out.println(f1.getAbsolutePath());}
}
File类创建文件的功能
方法名称 | 说明 |
public boolean createNewFile() | 创建一个新的空的文件 |
public boolean mkdir() | 只能创建一级文件夹 |
public boolean mkdirs() | 可以创建多级文件夹 |
File类删除文件的功能
方法名称 | 说明 |
public boolean delete() | 删除文件、空文件夹 |
注意:delete方法默认只能删除文件和空文件夹,删除后的文件不会进入回收站。
package Demo02;import java.io.File;
import java.io.IOException;public class Test2 {public static void main(String[] args) throws Exception {File f1 = new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo02\\test.txt");System.out.println(f1.createNewFile());File f2 = new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo02\\aaa");System.out.println(f2.mkdir());File f3 = new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo02\\aaa\\bbb");System.out.println(f3.mkdir());System.out.println(f1.delete());System.out.println(f2.delete());File f4 = new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo02");System.out.println(f4.delete());}
}
File类提供的遍历文件夹的功能
方法名称 | 说明 |
public String[] list() | 获取当前目录下所有的”一级文件名称“到一个字符串数组中去返回。 |
public File[] listFiles() | 获取当前目录下所有的"一级文件对象“到一个文件对象数组中去返回(重点) |
使用listFiles方法时的注意事项:
1、当主调是文件,或者路径不存在时,返回null
2、当主调是空文件夹时,返回一个长度为0的数组
3、当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回
4、当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中 返回,包含隐藏文件
5、当主调是一个文件夹,但是没有权限访问该文件夹时,返回null
package Demo02;import java.io.File;
import java.util.Arrays;public class Test {public static void main(String[] args) {File f1 = new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test");String[] names = f1.list();for (String name : names) {System.out.println(name);}System.out.println("-------------------------------------------------------");// File[] files = f1.listFiles();
// for (File file : files) {
// file.delete();
// }File[] files = f1.listFiles();for (File file : files) {System.out.println(file.getAbsolutePath());}System.out.println("-------------------------------------------------------");File f = new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\a");File[] files1 = f.listFiles();System.out.println(Arrays.toString(files1));System.out.println("-------------------------------------------------------");}
}
3、前置内容(方法递归)
什么是方法递归?
递归是一种算法,在程序设计语言中广泛应用。
从形式上说:方法调用自身的形式称为方法递归(recursion)
递归的形式
直接递归:方法自己调用自己。
间接递归:方法调用其他方法,其他方法又回调方法自己。
package Demo03;public class Test1 {public static void main(String[] args) {test1();test2();}//直接方法递归public static void test1() {System.out.println("-----test1-----");test1(); }//间接方法递归public static void test2(){System.out.println("-----test2-----");test3();}public static void test3(){test2();}
}
猴子吃桃问题:
猴子第一天摘下若干桃子,当即吃了一半,觉得好不过瘾,于是又多吃了一个
第二天又吃了前天剩余桃子数量的一半,觉得好不过瘾,于是又多吃了一个
以后每天都是吃前天剩余桃子数量的一半,觉得好不过瘾,又多吃了一个
等到第10天的时候发现桃子只有1个了。
需求:请问猴子第一天摘了多少个桃子?
package Demo03;public class Test3 {public static void main(String[] args) {/*f(2)=f(1)-f(1)/2+1;f(3)=f(2)-f(2)/2+1;...f(9)=f(8)-f(8)/2+1;f(10)=f(9)-f(9)/2+1;f(10)=1;f(x) =f(x-1)-f(x-1)/2+1;2f(x)=2f(x-1)-f(x-1)+2;f(x-1)=2f(x)+2f(x)=2f(x+1)+2*/System.out.println(f(1));}public static int f(int n) {if (n == 10) {return 1;} else {return 2 * f(n + 1) + 2;}}
}
4、文件搜索
需求:从C:盘中,搜索“QQ.exe”这个文件,找到后直接输出其位置。
package Demo03;import java.io.File;public class Test4 {public static void main(String[] args) throws Exception {searchFile(new File("C:\\"), "QQ.exe");}/*** 去目录下搜索某个文件** @param dir 目录* @param fileName 文件名称*/public static void searchFile(File dir, String fileName) throws Exception {//1、先把非法的情况拦截住if (dir == null || !dir.exists() || dir.isFile()) {return;}//2、dir不是null、存在、一定是目录//获取当前目录下的全部一级文件对象File[] files = dir.listFiles();//3、判断当前目录下是否存在一级文件对象,一级是否可以拿到一级文件对象if (files != null && files.length > 0) {//4、遍历全部一级文件对象for (File file : files) {//5、判断文件是否为文件对象if (file.isFile()) {//是文件 判断文件名if (file.getName().equals(fileName)) {System.out.println("找到了:" + file.getAbsolutePath());//启动程序Runtime runtime = Runtime.getRuntime();runtime.exec(file.getAbsolutePath());}} else {//是文件夹 继续重复这个过程searchFile(file, fileName);}}}}
}
需求:删除文件
package Demo03;import java.io.File;public class Test5 {public static void main(String[] args) {//目标:删除非空文件夹File dir = new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo03\\Test");deleteDir(dir);}public static void deleteDir(File dir) {//dir为null或dir不存在 if (dir == null || !dir.exists()) {return;}//dir是文件直接删除if (dir.isFile()) {dir.delete();return;}//1、dir存在,且是文件夹File[] files = dir.listFiles();//为空直接返回if (files == null) {return;}//空文件夹if (files.length == 0) {dir.delete();return;}//有内容的文件夹for (File file : files) {//有文件直接删除if (file.isFile()) {file.delete();} else {//还是文件夹 递归deleteDir(file);}}//删除本文件夹dir.delete();}
}
需求: 啤酒问题:啤酒2元一瓶 4个盖子可以换一瓶啤酒 2个空瓶可以换一瓶 10元可以和多少瓶?
package Demo03;public class Test6 {public static int totalNumber;//总酒数public static int lastBottleNumber; //剩余空瓶数public static int lastCoverNumber; //剩余盖子数public static void main(String[] args) {
// 啤酒问题:啤酒2元一瓶 4个盖子可以换一瓶啤酒 2个空瓶可以换一瓶 10元可以和多少瓶?buy(10);System.out.println("总数:" + totalNumber);System.out.println("剩余瓶子数:" + lastBottleNumber);System.out.println("剩余盖子数:" + lastCoverNumber);}public static void buy(int money) {// if (money < 2 && lastBottleNumber < 2 && lastCoverNumber < 4) {
// return;
// }int buyNumber = money / 2;totalNumber += buyNumber;//本轮剩余空瓶int allBottleNumber = buyNumber + lastBottleNumber;//本轮剩余盖子int allCoverNumber = buyNumber + lastCoverNumber;//空瓶换钱int allMoney = 0;if (allBottleNumber >= 2) {allMoney += (allBottleNumber / 2) * 2;}//换钱后剩余空瓶lastBottleNumber = allBottleNumber % 2;//盖子换钱if (allCoverNumber >= 4) {allMoney += (allCoverNumber / 4) * 2;}lastCoverNumber = allCoverNumber % 4;//继续买啤酒if (money >= 2) {buy(allMoney);}}public static void MyBuy(int money) {if (money < 2 && lastBottleNumber < 2 && lastCoverNumber < 4) {return;}int buyNumber = money / 2;
// 总瓶数totalNumber += buyNumber;// 本轮剩余空瓶int allBottleNumber = buyNumber + lastBottleNumber;// 本轮总剩余盖子int allCoverNumber = buyNumber + lastCoverNumber;//空瓶换钱int allMoney = 0;if (allBottleNumber >= 2) {allMoney += (allBottleNumber / 2) * 2;}//换钱后剩余空瓶lastBottleNumber = allBottleNumber % 2;//瓶盖换钱if (allCoverNumber >= 4) {allMoney += (allCoverNumber / 4) * 2;}//换钱后剩余瓶盖lastCoverNumber = allCoverNumber % 4;//继续买啤酒if (allMoney >= 2) {MyBuy(allMoney);}}
}
5、IO流概述、FileInputStream
IO流概述
IO流的分类
IO流总体来看就有四大流
IO流的体系
FilelnputStream(文件字节输入流)
作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
构造器 | 说明 |
public FileInputStream(File file) | 创建字节输入流管道与源文件接通 |
public FileInputStream(String pathname) | 创建字节输入流管道与源文件接通 |
方法名称 | 说明 |
public int read() | 每次读取一个字节返回,如果发现没有数据可读会返回-1. |
public int read(byte[] buffer) | 每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1 |
package Demo04;import java.io.FileInputStream;
import java.io.InputStream;public class FileInputStreamTest1 {public static void main(String[] args) throws Exception {//1、创建文件字节输入流,与源文件接通//简化写法,推荐使用InputStream is = new FileInputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\test\\test.txt");//2、读取文件的字节数据// int b1 = is.read();
// System.out.println((char) b1);
//
// int b2 = is.read();
// System.out.println((char) b2);
//
// //没有数据返回-1
// int b3 = is.read();
// System.out.println(b3);//3、使用循环改造上述代码int b; //用于记住读取的字节while ((b = is.read()) != -1) {System.out.print((char) b);}//读取数据的性能差//读取汉字输出会乱码,无法避免的//流使用完毕后 必须关闭,释放资源is.close();}
}
6、字节流-FileInputStream
FilelnputStream(文件字节输入流)
构造器 | 说明 |
public FileInputStream(File file) | 创建字节输入流管道与源文件接通 |
public FileInputStream(String pathname) | 创建字节输入流管道与源文件接通 |
方法名称 | 说明 |
public int read() | 每次读取一个字节返回,如果发现没有数据可读会返回-1. |
public int read(byte[] buffer) | 每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1. |
package Demo04;import java.io.FileInputStream;
import java.io.InputStream;public class FileInputStreamTest2 {public static void main(String[] args) throws Exception {//1、c创建一个字节流输入对象代表字节输入流管道与源文件接通InputStream is = new FileInputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\Test02.txt");//2、开始读取文件中的字节数据,,每次读取多个字节//每次读取多个字节到字节数组中,返回读取的字节数量,读取完毕会返回-1byte[] buffer = new byte[3];int len = is.read(buffer);String rs = new String(buffer);System.out.println(rs);System.out.println("当次读取的字节数量:" + len);//buffer[]=[abc]//buffer[]=[66c]int len2 = is.read(buffer);String rs2 = new String(buffer, 0, len2);System.out.println(rs2);System.out.println("当次读取的字节数量:" + len2);int len3 = is.read(buffer);System.out.println(len3); //-1// //3、使用循环改造
// byte[] buffer = new byte[3];
// int len;
// while ((len = is.read(buffer)) != -1) {
// String rs = new String(buffer, 0, len);
// System.out.println(rs);
// }
//
// //性能明显提升
// //不能解决中文乱码问题
//
// is.close();}
}
使用循环改造
package Demo04;import java.io.FileInputStream;
import java.io.InputStream;public class FileInputStreamTest2 {public static void main(String[] args) throws Exception {//1、c创建一个字节流输入对象代表字节输入流管道与源文件接通InputStream is = new FileInputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\Test02.txt");//2、开始读取文件中的字节数据,,每次读取多个字节//每次读取多个字节到字节数组中,返回读取的字节数量,读取完毕会返回-1
// byte[] buffer = new byte[3];
// int len = is.read(buffer);
// String rs = new String(buffer);
// System.out.println(rs);
// System.out.println("当次读取的字节数量:" + len);
//
// //buffer[]=[abc]
//
// //buffer[]=[66c]
// int len2 = is.read(buffer);
// String rs2 = new String(buffer, 0, len2);
// System.out.println(rs2);
// System.out.println("当次读取的字节数量:" + len2);
//
// int len3 = is.read(buffer);
// System.out.println(len3); //-1//3、使用循环改造byte[] buffer = new byte[3];int len;while ((len = is.read(buffer)) != -1) {String rs = new String(buffer, 0, len);System.out.println(rs);}//性能明显提升//不能解决中文乱码问题is.close();}
}
注意事项
使用FilelnputStream每次读取多个字节,读取性能得到了提升,但读取汉字输出还是会乱码。
使用字节流读取中文,如何保证输出不乱码,怎么解决?
定义一个与文件一样大的字节数组,一次性读取完文件的全部字节。
文件字节输入流:一次读取完全部字节
方式一:
自己定义一个字节数组与被读取的文件大小一样大,然后使用该字节数组,一次读完文件的全部字节。
方法名称 | 说明 |
public int read[byte[]buffer) | 每次用一个字节数组去读取,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1. |
package Demo04;import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;public class FileInputStreamTest3 {public static void main(String[] args) throws Exception {//1、一次性读取完文件的全部字节到一个字节数组中去//创建一个字节流输入管道与源文件接通InputStream is = new FileInputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\test\\test2");//2、准备一个字节数组,大小与文件的大小正好一样大File f = new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\test\\test2");long size = f.length();byte[] buffer = new byte[(int) size];int len = is.read(buffer);System.out.println(new String(buffer));System.out.println(size);System.out.println(len);// byte[] buffer = is.readAllBytes();
// System.out.println(new String(buffer));}
}
方式二:
Java官方为lnputStream提供了如下方法,可以直接把文件的全部字节读取到一个字节数组中返回。
方法名称 | 说明 |
public byte[]readAllBytes(throwsIoException) | 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回 |
1、直接把文件数据全部读取到一个字节数组可以避免乱码,是否存在问题?
如果文件过大,创建的字节数组也会过大,可能引起内存溢出。
读写文本内容更适合用 字符流
字节流适合做数据的转移,如:文件复制等。
7、字节流-FileOutputStream
作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去
构造器 | 说明 |
public FileoutputStream(File file) | 创建字节输出流管道与源文件对象接通 |
public FileOutputStream(Sting filepath) | 创建字节流输出管道与源文件路径接通 |
public FileOutputStream(File file, boolean append) | 创建字节输出流管道与源文件对象接通,通,可追加数据 |
public FileOutputStream(String filepath, boolean append) | pub创建字节输出流管道与源文件路径接通,可追加数据 |
方法名称 | 说明 |
public void write(int a) | 写一个字节出去 |
public void write(byte[] buffer) | 写一个字节数组出去 |
public void write(byte[] buffer,int pos,int len) | 写一个字节数组的一部分出去 |
public void close() throws IOException | 关闭流 |
package Demo01;import java.io.FileOutputStream;
import java.io.OutputStream;public class FileOutputStreamTest4 {public static void main(String[] args) throws Exception {//1、创建一个字节输出流管道与目标文件接通//true表示追加数据,如果为false,则每次都会覆盖原有的数据。默认为false。OutputStream os = new FileOutputStream("/Users/harry/JavaStudy/JavaStudy/src/Test/test.txt", true);//2、开始学字节数据出去os.write(97);os.write('b');
// os.write('涵'); [ooo] 默认只能写一个字节出去byte[] bytes = "我爱你中国abc".getBytes();os.write(bytes, 0, 15);//换行符os.write("\r\n".getBytes());os.close();//关闭流}
}
文件复制
package Demo01;import java.io.*;public class CopyTest5 {public static void main(String[] args) throws Exception {InputStream is = new FileInputStream("/Users/harry/JavaStudy/JavaStudy/src/Demo01/test.txt");OutputStream os = new FileOutputStream("/Users/harry/JavaStudy/JavaStudy/src/Test/test.txt");int len;byte[] bytes = new byte[1024];while ((len = is.read(bytes)) != -1) {os.write(bytes, 0, len);}is.close();os.close();System.out.println("照片复制成功!!!");}
}
8、释放资源的方式
try-catch-finally
finally代码区的特点:
无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非VM终止。
package Demo05;public class Test1 {public static void main(String[] args) {try {System.out.println(10 / 0);return; //跳出放的执行} catch (Exception e) {e.printStackTrace();} finally {System.out.println("==finally执行了一次===");}System.out.println(division(10,2));}public static int division(int a, int b) {try {return a/b;}catch(Exception e){e.printStackTrace();return -1;}finally {return 111; //千万不要在finally中返回数据}}
}
作用:
一般用于在程序执行完成后进行资源的释放操作(专业级做法)。
package Demo05;import java.io.*;public class Test2 {public static void main(String[] args) {InputStream is = null;OutputStream os = null;try {System.out.println(10 / 0);//异常new FileInputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\ab.txt");new FileOutputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\ab.txt");System.out.println(10 / 0);//异常byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) != -1) {os.write(buffer, 0, len);}System.out.println("复制成功!");} catch (IOException e) {e.printStackTrace();} finally {try {if (os != null) os.close();} catch (IOException e) {throw new RuntimeException(e);}try {if (is != null) is.close();} catch (IOException e) {throw new RuntimeException(e);}}}
}
try-with-resource
该资源使用完毕后,会自动调用其close(方法,完完成对资源的释放!
上面的代码过于臃肿,进行优化
package Demo05;import java.io.*;public class Test3 {public static void main(String[] args) {try (InputStream is = new FileInputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\ab.txt");OutputStream os = new FileOutputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\ab.txt");//这里只能放资源对象(流对象)//资源都会实现AutoCloseable接口//用完之后会自动调用其close方法完成资源的释放操作MyConnection myConnection =new MyConnection();) {byte[] buffer = new byte[1024];int len;while ((len = is.read(buffer)) != -1) {os.write(buffer, 0, len);}System.out.println("复制成功!");} catch (IOException e) {e.printStackTrace();} catch (Exception e) {throw new RuntimeException(e);}}
}
package Demo05;public class MyConnection implements AutoCloseable {@Overridepublic void close() throws Exception {System.out.println("释放连接~");}
}
IO流(二)
1、字符流
FileReader(文件字符输入流)
作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
构造器 | 说明 |
public FileReader(File file) | 创建字符输入流管道与源文件接通 |
publicFileReader(Stringpathname) | 创建字符输入流管道与源文件接通 |
方法名称 | 说明 |
public int read() | 每次读取一个字符返回,如果发现没有数据可读会返回-1. |
public int read(char[] buffer) | 每次用一个字符数组去读取数据,返回字符数组读取了多少个字符, public int read(char[] buffer) 如果发现没有数据可读会返回-1. |
package Demo06;import java.io.FileReader;
import java.io.Reader;public class FileReader01 {public static void main(String[] args) {try {//1.创建一个文件字符输入流管道与文件接通Reader fr = new FileReader("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\ab.txt");/* //2、读文件文件内容int c; //记住每次读取的字符编号while ((c = fr.read()) != -1) {System.out.print((char) c);}
*///3、每次读取多个字符char[] buffer = new char[3];int len; //记住每次读取了多少了字符while ((len = fr.read(buffer)) != -1) {//读取类多少倒出多少System.out.print(new String(buffer, 0, len));}//性能是比较不错的!} catch (Exception e) {e.printStackTrace();}}
}
FileWriter(文件字符输出流)
作用:以内存为基准,把内存中的数据以字符的形式写出到文件中去
构造器 | 说明 |
public FileWriter(File file) | 创建字节输出流管道与源文件对象接通 |
public FileWriter(String filepath) | 创建字节输出流管道与源文件路径接通 |
public FileWriter(File file, boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileWriter(String filepath, boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
方法名称 | 说明 |
void write(int c) | 写一个字符 |
void write(String str) | 写一个字符串 |
void write(String str,int off,int len) | 写一个字符串的一部分 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
package Demo06;import java.io.FileWriter;
import java.io.Writer;public class FileWriter02 {public static void main(String[] args) {//追加try (Writer fw = new FileWriter("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\test01.txt", true)) {//写入单个字符fw.write('a');fw.write(97);fw.write('涵');fw.write("\r\n");//写入字符串fw.write("我爱你中国abc");fw.write("\r\n");//写入字符串的子串fw.write("我爱你中国abc", 0, 5);fw.write("\r\n");//写入字符数组char[] buffer = {'黑', '马', 'a', 'b', 'c'};fw.write(buffer);fw.write("\r\n");//写入字符数组的子串fw.write(buffer, 0, 2);fw.write("\r\n");} catch (Exception e) {e.printStackTrace();}}
}
字符输出流使用时的注意事项
字符输出流写出数据后,必须刷新流,或者关闭流,写出去的数据才能生效
package Demo06;import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;public class FileWriter03 {public static void main(String[] args) throws Exception {Writer fw = new FileWriter("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\test03.txt");fw.write('a');fw.write('b');fw.write('c');fw.write('d');fw.write("\r\n");fw.write("我爱你中国");fw.write("\r\n");fw.write("我爱你中国");// fw.flush();//刷新流
// fw.write("张三");
// fw.flush();
//fw.close();//关闭流 含有刷新操作}
}
2、缓冲流
2.1缓冲字节流
BufferedInputStream缓冲字节输入流
作用:可以提高字节输入流读取数据的性能
原理:缓冲字节输入流自带了8KB缓冲池;缓冲字节输出流也自带了8KB缓冲池。
构造器 | 说明 |
public BufferedInputStream(InputStream is) | 把低级的字节输入流包装成一个高级的缓冲字节输入流,从而提高读数据的性能 |
public BufferedOutputStream(OutputStream os) | 把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能 |
package Demo08;import java.io.*;public class CopyDemo {public static void main(String[] args) {copyFile("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo08\\abc.txt", "C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\abc.txt");}public static void copyFile(String scrpath, String destPath) {try (InputStream fis = new FileInputStream(scrpath);//低级的字节流包装成高级的缓冲流InputStream bis = new BufferedInputStream(fis);OutputStream fos = new FileOutputStream(destPath);//低级的字节流包装成高级的缓冲流OutputStream bos = new BufferedOutputStream(fos);) {byte[] buffer = new byte[1024];int len;while ((len = bis.read(buffer)) != -1) {bos.write(buffer, 0, len);}System.out.println("复制成功");} catch (Exception e) {e.printStackTrace();}}
}
2.2缓冲字符流
BufferedReader缓冲字符输入流
作用:自带8K(8192)的字符缓冲池,可以提高字符输入流读取字符数据的性能。
构造器 | 说明 |
public BufferedReader(Reader r) | 把低级的字符输入流包装成字符缓冲输入流管道,从而提高字符输入流读字符数据的性能 |
字符缓冲输入流新增的功能:按照行读取字符
方法 | 说明 |
public String readLine() | 读取一行数据返回,如果没有数据可读了,会返回nul1 |
package Demo09;import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;public class BufferedReaderDemo1 {public static void main(String[] args) {try ( //创建文件与字符流接通Reader fr = new FileReader("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\text01.txt");//创建一个字符缓冲输入流包装原始的字符输入流BufferedReader br = new BufferedReader(fr);) {/* //定义一个字符数组,每次读取多个字符char[] buffer = new char[1024];int len; //用于记录每次读了多少个字符while ((len = br.read(buffer)) != -1) {//将字符数组转换为字符串String str = new String(buffer, 0, len);System.out.print(str);}*///定义一个字符串,每次读取一行String line;while ((line = br.readLine()) != null){System.out.println(line);}//目前读取文本最好的方案} catch (Exception e) {e.printStackTrace();}}
}
BufferedWriter缓冲字符输出流
作用:自带8K的字符缓冲池,可以提高字符输出流写字符数据的性能。
构造器 | 说明 |
public BufferedWriter(Writer r) | 把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能 |
字符缓冲输出流新增的功能:换行
方法 | 说明 |
public void newLine() | 换行 |
package Demo10;import java.io.*;public class BufferedWriterDemo1 {public static void main(String[] args) {try (Writer fw = new FileWriter("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\text01.txt", true);BufferedWriter bw = new BufferedWriter(fw);) {bw.write('a');bw.write(98);bw.write('涵');bw.newLine();} catch (IOException e) {e.printStackTrace();}}
}
案例:
需求:按首字母的顺序进行恢复到一个新文件中。
分析:
定义一个缓存字符输入流管道与源文件接通。
定义一个List集合存储读取的每行数据。
定义一个循环按照行读取数据,存入到List集合中去。
对List集合中的每行数据按照首字符编号升序排序。
定义一个缓存字符输出管道与目标文件接通。
遍历List集合中的每个元素,用缓冲输出管道写出并换行。
package Demo10;import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public class BufferedTest {public static void main(String[] args) {try (//1、创建一个字符缓冲流对象与源文件链接BufferedReader br = new BufferedReader(new FileReader("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\abc.txt"));BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\abcText.txt"));) {//2、提前准备一个List集合List<String> data = new ArrayList<>();//3.添加到集合中String line;while ((line = br.readLine()) != null) {data.add(line);}//4.添加到集合中排序Collections.sort(data, (String o1, String o2) -> o1.charAt(0) - o2.charAt(0));for (String datum : data) {bw.write(datum);bw.newLine(); //换行}System.out.println("处理完毕");} catch (Exception e) {e.printStackTrace();}}
}
3、其他流
3.1、字符输入转换流
解决不同编码时,字符流读取文本内容乱码的问题。
解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
构造器 | 说明 |
public InputStreamReader(InputStream is) | 把原始的字节输入流,按照代码默认编码转成字符输入流(与直接用FileReader的效果一样) |
public InputStreamReader(InputStream is ,String charset) | 把原始的字节输入流,按照指定字符集编码转成字符输入流(重点) |
package Demo12;import java.io.*;public class Demo1 {public static void main(String[] args) {try (InputStream is = new FileInputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\text01.txt");//指定字符集把原始字节流转为换成的字符输入流InputStreamReader reader = new InputStreamReader(is, "utf-8");Reader isr = new InputStreamReader(is, "GBK");BufferedReader br = new BufferedReader(isr);) {String line;while ((line = br.readLine()) != null) {System.out.println(line);}} catch (Exception e) {e.printStackTrace();}}
}
3.2、打印流
作用:打印流可以实现更方便、更高效的打印数据出去,能实现打印啥出去就是啥出去。
PrintStream提供的打印数据的方案
构造器 | 说明 |
publicPrintstream(outputStream/File/String) | 打印流直接通向字节输出流/文件/文件路径 |
public PrintStream(String fileName,Charset charset) | 可以指定写出去的字符编码 |
public PrintStream(OutputStream out, boolean autoFlush) | 可以指定实现自动刷新 |
public PrintStream(OutputStream out, boolean autoFlush, String encoding) | 可以指定实现自动刷新,并可指定字符的编码 |
package Demo13;import java.io.PrintStream;public class PrintStreamDemo1 {public static void main(String[] args) {try (PrintStream ps = new PrintStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo13\\test.txt")) {ps.println(97);ps.println('a');ps.println("字符串");} catch (Exception e) {e.printStackTrace();}}
}
3.3、数据输出流
允许把数据和其类型一并写出去。
构造器 | 说明 |
public DataoutputStream(OutputStream out) | 创建新数据输出流包装基础的字节输出流 |
方法 | 说明 |
public final void writeByte(int v) throws IOException | 将byte类型的数据写入基础的字节输出流 |
public final void writeInt(int v) throws IOException | 将int类型的数据写入基础的字节输出流 |
public final void writeDouble(Double v))throws IOException | 将double类型的数据写入基础的字节输出流 |
public final void writeUTE(String str) throws IOException | 将字符串数据以UTF-8编码成字节写入基础的字节输出流 |
publicvoid write(int/byte[]/byte[]一部分) | 支持写字节数据出去 |
package Demo13;import java.io.DataOutputStream;
import java.io.FileOutputStream;public class DataStreamDemo2 {public static void main(String[] args) {try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo13\\data.txt"))) {dos.writeByte(1);dos.writeUTF("你好");dos.writeInt(123);dos.writeDouble(9.9);} catch (Exception e) {e.printStackTrace();}}
}
package Demo13;import java.io.DataInputStream;
import java.io.FileInputStream;public class DataStreamDemo3 {public static void main(String[] args) {try (DataInputStream dis = new DataInputStream(new FileInputStream("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo13\\data.txt"));) {System.out.println(dis.readByte());System.out.println(dis.readUTF());System.out.println(dis.readInt());System.out.println(dis.readDouble());} catch (Exception e) {e.printStackTrace();}}
}
4、IO流框架
Commons-io是apache开源基金组织提供的一组有关Io操作的小框架,目的是提高Io流的开发效率。
FileUtils类提供的部分方法展示 | 说明 |
public static void copyFile(File srcFile,File destFile) | 复制文件 |
public static void copyDirectory(File srcDir,File destDir) | 复制文件夹 |
public static void deleteDirectory(File directory) | 删除文件夹 |
public static String readFileTostring(File file, String encoding) | 读数据 |
public static void writeStringToFile(File file, String data, String charname, boolean append) | 写数据 |
IOUtils类提供的部分方法展示 | 说明 |
public static int copy(InputStream inputStream,OutputStream outputStream) | 复制文件。 |
public static int copy(Reader reader, Writer writer) | 复制文件。 |
public static void write(String data, OutputStream output,String charsetName) | 写数据 |
package Demo14;import org.apache.commons.io.FileUtils;import java.io.File;
import java.io.IOException;public class java {public static void main(String[] args) throws Exception {FileUtils.copyFile(new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Test\\abc.txt"), new File("C:\\JavaStudy\\Test\\heimaJavaStudy\\src\\Demo14\\abc.txt"));}
}