IO流:输入输出流。在java中,IO流用来进行设备之间的设备数据传输(上传,下载都是用到IO流完成),数据在电脑中是以文件的形式存在。所以我们需要在学习IO流之前,学习两个准备知识。
在java中,对于遇到的问题,有一个类来描述(Throwable类)。Throwable
类是 Java 语言中所有错误或异常的父类。两个子类的实例,Error
和 Exception
,通常用于指示发生了异常情况
Exception:异常,描述一般性的问题,它指出了合理的应用程序想要捕获的条件。异常分为两种情况:编译期异常(非RuntimeException及其子类)和运行期异常(RuntimeException及其子类)。编译其异常必须解决,否则程序无法执行。运行期非必需解决。
Error:错误,严重的问题,用于指示合理的应用程序不应该试图捕获的严重问题,既我们无法解决,比如内存溢出等。
运行期异常
当遇到异常时,没有处理异常,java使用默认处理方式,java在遇到异常时会打印异常堆栈信息然后推出虚拟机,不再打印后面的内容,我们可以自己处理运行期异常,使用try catch.
try{}的大括号里面的方式的有可能出现问题的代码,catch()的小括号里面为:一旦出现异常,我们的处理逻辑
int a = 10;
int b = 0;
try{
System.out.println(a / 0);
}catch (ArithmeticException e){
System.out.println("除数为0了");
}
System.out.println("后面代码");
System.out.println("后面代码");
System.out.println("后面代码");
System.out.println("后面代码");
System.out.println("后面代码");
System.out.println("后面代码");
多个等可能的异常出现时
int[] arr = {20, 30};
int a = 10;
int b = 0;
//ArrayIndexOutOfBoundsException
//ArithmeticException
try {
arr = null;
System.out.println(arr[0]);
System.out.println(a / b);
System.out.println(arr[3]);
}catch (ArrayIndexOutOfBoundsException e){
System.out.println("索引越界异常");
}catch (ArithmeticException e){
System.out.println("除数为0了");
}catch (NullPointerException e){
System.out.println("空指针异常");
} catch (Exception e) {
System.out.println("其他异常");
}
注意,能明确的异常尽量明确,不要拿最大的Exception异常一步了之,因为发生异常时我们不知道具体发生了什么相应的异常。捕获的多个异常中,有父子继承关系,父类异常放到最后。try{}的大括号里面的方式的有可能出现问题的代码,没有问题的代码不要放,浪费性能。
jDK1.7之后提供了一种捕获多种异常的语法
//JDK1.7之后提供了一种捕获多种异常的语法
int[] arr = {20, 30};
int a = 10;
int b = 0;
//ArrayIndexOutOfBoundsException
//ArithmeticException
try {
//arr = null;
System.out.println(a / b);
System.out.println(arr[0]);
System.out.println(arr[3]);
} catch (ArrayIndexOutOfBoundsException | NullPointerException | ArithmeticException e) {
if (e instanceof ArrayIndexOutOfBoundsException) {
System.out.println("索引越界异常");
} else if (e instanceof NullPointerException) {
System.out.println("空指针异常");
} else if (e instanceof ArithmeticException) {
System.out.println("数学异常");
}
finally最终的: 不管try里面的代码有没有遇到异常,那么finally里面的代码都会执行。一般我们会在finally善后收尾的的代码写finally里面 比如释放资源
int a=10;
int b=0;
try{
//ctrl+shift+上下方向键,可以上下挪动一样代码
System.out.println(a / 0);
}catch (ArithmeticException e){
System.out.println("除数为0了");
}finally {
System.out.println("不管try里面的代码有没有遇到异常,那么finally里面的代码都会执行");
}
Scanner scanner = null;
try {
//System.out.println(1/0);
scanner = new Scanner(System.in);
System.out.println("请输入第一个整数");
int one = scanner.nextInt();
System.out.println("请输入第二个整数");
int two = scanner.nextInt();
System.out.println(one / two);
} catch (ArithmeticException e) {
System.out.println("除数为0");
} finally {
//释放资源
System.out.println("释放资源");
if (scanner != null) {
scanner.close();
}
}
System.out.println("下面的代码");
}
编译期异常
编译器异常有两种处理方式
方式一:使用throw向上抛出,给调用者处理,谁调用谁处理。
public static void main(String[] args) throws ParseException {
String dateStr="2020-=02-23";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date= simpleDateFormat.parse(dateStr);
System.out.println(date);
System.out.println("下面 代码");
}
}
方式二:使用try catch 捕获处理
public static void main(String[] args) {
String dateStr = "2020-02-23";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = simpleDateFormat.parse(dateStr);
System.out.println(date);
}catch (ParseException e){
System.out.println("解析失败");
}
System.out.println("下面代码");
}
}
一般来说,抛到main方法里面就不再抛出了,而是自己捕获处理,这种方式比较友好一些
工具类里面的异常,你就抛出去,抛给调用工具类的人他去处理
public static Date parseDateStr(String dateStr, String formate) throws ParseException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date = simpleDateFormat.parse(dateStr);
return date;
用异常处理进行键盘录入操作
public static void main(String[] args) {
while (true) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个整数");
try {
int num = sc.nextInt();
System.out.println(num);
break;
} catch (InputMismatchException e) {
System.out.println("输入类型不正确,请重新输入");
}
}
}
}
throws 和 throw的区别
//相同点是都可以进行异常的抛出
//throws用在方法声明上
//throw使用用在方法内部抛出异常
/*
throws和throw的区别
a:throws
用在方法声明后面,跟的是异常类名
可以跟多个异常类名,用逗号隔开
表示抛出异常,由该方法的调用者来处理
throws表示出现异常的一种可能性,并不一定会发生这些异常
b:
throw
用在方法体内,跟的是异常对象名
只能抛出一个异常对象名
这个异常对象可以是编译期异常对象, 可以是运行期异常对象
表示抛出异常,由方法体内的语句处理
throw则是抛出了异常对象,
执行throw则一定抛出了某种异常*/
自定义异常
在我们开发项目中,会遇到各种各样的异常,那么Java给我们提供的这些异常类,并不能完全描述我们所遇到的各种异常。如扫码异常等。
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的取款金额");
double num = scanner.nextDouble();
quKuan(num);
}
private static void quKuan(double num) {
if(num<=money){
money -= num;
System.out.println("取款成功");
}else{
// System.out.println("余额不足");
//余额不足,就要抛出异常,程序终止。
throw new NoMoneyException("余额不足");
1.子类在重写父类方法时,如果父类方法,没有抛出异常,子类不能抛出异常
2.子类在重写父类方法时,子类不能抛出父类没有抛出过的异常。
3.子类在重写父类方法时,子类抛出的异常,可以比父类小,或者与父类相同
4.子类在重写父类方法时,父类抛出异常时,子类不可以抛出异常
快捷捕获异常ctrl+alt+t或者在程序之后:如System.out.printin(1/0).try,即可
File类的概述
java为了描述电脑文件、目录等,提供了File类
File(File parent, String child)
根据 parent 抽象路径名和 child 路径名字符串创建一个新 File
实例。
File file = new File("C:\\Users\\ShenMouMou\\Desktop\\aaa.txt");
File(String pathname)
通过将给定路径名字符串转换为抽象路径名来创建一个新 File
实例。
File fuPath = new File("C:\\Users\\ShenMouMou\\Desktop");
File(String parent, String child)
根据 parent 路径名字符串和 child 路径名字符串创建一个新 File
实例。
File file2 = new File("C:\\Users\\ShenMouMou\\Desktop", "aaa.txt");
绝对路径与相对路径
绝对路径:带有盘符的地址值:如E:\steam\Steam.exe
相对路径:不带有盘符号的路径:如文件夹里面有子文件
//绝对路径
File file1 = new File("E:\\IdeaProjects\\20200523-File-类-下午\\a.txt");
System.out.println(file1);
File file2 = new File("E:\\IdeaProjects\\20200523-File-类-下午\\b.txt");
System.out.println(file2);
//相对路径
File file3 = new File("a.txt");
System.out.println(file3);
File file4 = new File("b.txt");
System.out.println(file4);
用的相对路径 ./ 当前路径 指的是项目文件夹的根目录下
用的相对路径 …/ 表示上一级路径
…/…/ 当前目录的上两级目录
成员方法:
创建文件。
//使用绝对路径,在桌面上创建一个文件夹
File file2 = new File("C:\\Users\\ShenMouMou\\Desktop","demo");
boolean mkdir = file2.mkdir();
System.out.println(mkdir);
//mkdir() 这个方法的不好之处,就是只能创建单级文件夹
//如果要创建多级文件夹,我们可以使用另外一个方法
File file3 = new File("C:\\Users\\ShenMouMou\\Desktop", "aaa/bbb/ccc");
// mkdirs(); 可以创建多级或单级文件夹。
// boolean mkdir1 = file3.mkdir();
boolean mkdirs = file3.mkdirs();
System.out.println(mkdirs);
删除文件
//删除文件或文件夹
File file = new File("a.txt");
//删除文件,删除成功返回true,重复删除返回false
boolean b = file.delete();
System.out.println(b);
File file1 = new File("img");
file1.delete();
}
delete() 删除文件夹的时候,只能删除空文件夹,如果是非空目录,则删除失败。
当调用delete() 方法时,直接删除文件,不管该文件是否存在,一经调用立即执行;
作业:删除非空目录,怎么删除?可以使用递归
File file = new File("C:\\Users\\ShenMouMou\\Desktop\\demo");
//因为demo 不是个空文件夹,所以直接删除不了。我们可以把里面的子文件全部删掉,再回过头来删这个空文件夹
File[] files = file.listFiles();
for (File f : files) {
f.delete();
}
boolean b = file.delete();
System.out.println(b);
重命名文件
File file = new File("aaa.txt");
File mbFile = new File("bbb.txt");
//重命名:源文件和传入进来的这个文件对象,都在相同路径下他就是重命名
boolean b = file.renameTo(mbFile);
System.out.println(b);
System.out.println("======================================");
//renameTo(mbFile)方法 :源文件和传入进来的这个文件,不在同一路径下,就是剪贴并重命名
File file1 = new File("eee.txt");
File file2 = new File("C:\\Users\\ShenMouMou\\Desktop\\fff.txt");
boolean b1 = file1.renameTo(file2);
System.out.println(b1);
判断类功能
//判断是不是个文件
File file = new File("bbb.txt");
boolean file1 = file.isFile();
System.out.println(file1);
//判断是不是目录
File file2 = new File("out");
boolean directory = file2.isDirectory();
System.out.println(directory);
System.out.println("================================");
File file3 = new File("bbb.txt");
//判断文件或文件夹是否存在
boolean exists = file3.exists();
System.out.println(exists);
//判断文件是否可读
File file = new File("C:\\Users\\ShenMouMou\\Desktop\\test.txt");
boolean b = file.canRead();
System.out.println(b);
//判断文件是否可写
boolean b1 = file.canWrite();
System.out.println(b1);
//判断文件是否隐藏
boolean hidden = file.isHidden();
System.out.println(hidden);
//判断文件是否使用的是绝对路径
boolean absolute = file.isAbsolute();
System.out.println(absolute);
File file1 = new File("bbb.txt");
boolean absolute1 = file1.isAbsolute();
System.out.println(absolute1);
获取类功能:
获取文件路径:
File file = new File("a.txt");
//获取文件的绝对路径,返回的是字符串类型
String absolutePath = file.getAbsolutePath();
System.out.println(absolutePath);
System.out.println("==============================");
//获取文件的绝对路径,返回的是File 这个方法比较灵活
File absoluteFile = file.getAbsoluteFile();
System.out.println(absoluteFile.toString());
absoluteFile.delete();
File file = new File("E:\\IdeaProjects\\20200524-File-类-上午", "a.txt");
//获取文件的父路径,返回的是字符串类型
String parent = file.getParent();
System.out.println(parent);
System.out.println("==========================");
///获取文件的父路径,返回的是File类型 这个方法灵活
File parentFile = file.getParentFile();
System.out.println(parentFile.toString());
// File file1 = new File(parentFile, "b.txt");
System.out.println("=========================================");
File file3 = new File("E:\\IdeaProjects\\20200524-File-类-上午\\a.txt");
//获取文件的父路径
String parent1 = file3.getParent();
System.out.println(parent1);
File parentFile1 = file3.getParentFile();
System.out.println(parentFile1);
System.out.println("======================");
//在封装文件时,没有指定父路径,返回就是null
File file1 = new File("a.txt");
String parent2 = file1.getParent();
System.out.println(parent2);
获取磁盘容量类
//获取磁盘的总容量,返回的是字节
File file = new File("D://");
long totalSpace = file.getTotalSpace();
System.out.println((totalSpace/1024/1024/1024.0)+"GB");
//获取磁盘的剩余容量
long freeSpace = file.getFreeSpace();
System.out.println((freeSpace / 1024 / 1024 / 1024.0) + "GB");
文件类获取
File file = new File("a.txt");
//获取文件名
String name = file.getName();
System.out.println(name);
//获取文件大小
long length = file.length();
System.out.println(length);
public String[] list ():获取指定目录下的所有文件或者文件夹的名称数组
File file = new File("C:\\Users\\ShenMouMou\\Desktop\\demo");
String[] arr = file.list();
for (String s : arr) {
if(s.equals("2005691.jpg")){
System.out.println("进来了");
System.out.println(s);
File file1 = new File(file, s);
System.out.println(file1);
file1.delete();
public File[] listFiles ():获取指定目录下的所有文件或者文件夹的File数组
File file = new File("C:\\Users\\ShenMouMou\\Desktop\\demo");
File[] files = file.listFiles();
for (File f : files) {
System.out.println(f.getName());
if (f.isDirectory()) {
f.delete();
作业:删除多级文件夹:文件夹里面套有跟多子文件夹。递归删除可以做到
package IO.delete;
import java.io.File;
public class Delete_Folder {
public static void main(String[] args) {
File srcFile = new File("H:\\daywork\\delete");
deleteFolder(srcFile);
}
public static void deleteFolder(File file){
if(file.isFile()){
System.out.println("删除"+file.getName());
file.delete();
//不是文件的话,就是文件夹
}else{
//获取文件夹中的所有File对象,如果为空,则files.length为0,次处程序不执行
File[] files=file.listFiles();
for (int i = 0; i < files.length; i++) {
//如果不为空,则显示显示删除的文件名称,继续调用递归
System.out.println("删除"+files[i].getName());
deleteFolder(files[i]);
}
}
//最后删除空文件夹!!!
file.delete();
}
}
IO流
我们站在内存的角度看待输入输出流。
输入流:用来读取数据
输出流:用来写出数据
我们根据文件的数据类型,可以把流划分为字节流,和字符流。字节流可以操作任意类型的文件,字符流只能操作文本文件。
字节流
字节流的继承关系:
字节输入流inputStram和字节输出流outputStram。
inputStram:抽象类,是所有字节输入流的父类。常用的子类有:
outputStram:抽象类,是所有字节输出流的父类。常用子类有:
文件输出流FileOutputStram
FileOutputStram(File file)
创建一个向指定File对象表示文件中写入数据的文件输出流。
FileOutputStram(String name)
创建一个具有指定名称的文件中写入数据的输出文件流。
File file = new File("a.txt");
FileOutputStream out = new FileOutputStream(file);
创建文件输出流,来关联文件,当关联的文件不存在时,会自动创建这个文件。
文件中写入数据
方法有:out.write(byte[] b):输出字节数组
out.write(byte[] b, int off(选取的起始位置), int len(要写几个字节)):自顶范围输出子类数组
out.write(int b):输出单个子类
//一次写入一个字节
out.write(97);
out.write(98);
out.write(99);
out.write(100);
//一次可以写入一个字节数组
byte[] bytes = {101, 102, 103, 104};
out.write(bytes);
//写入中文
String str="爱生活";
byte[] bytes1 = str.getBytes();
out.write(bytes1);
out.close();
//最后一定要释放资源
FileOutputStram(File file, boolean append);同下,参数一,文件名,参数二,是否要追加写入数据。true/false
创建一个向指定 File
对象表示的文件中写入数据的文件输出流。
FileOutputStram(String name, boolean append);同上
创建一个向具有指定 name
的文件中写入数据的输出文件流。
FileOutputStream out = new FileOutputStream("c.txt",true);
out.write("康师傅".getBytes());
//写入换行符
/* windows下的换行符只用是 \r\n
Linux \n
Mac \r
*/
out.write("\r\n".getBytes());
out.write("统一".getBytes());
out.write("\r\n".getBytes());
out.close();
FileOutputStram写出数据的异常处理
FileOutputStream out=null;
try{
out = new FileOutputStream("c.txt");
}catch (IOException e){
e.printStackTrace();
}finally {
try {
if (out != null) {
out.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
文件输入流FileinputStram
FileInputStream(File file)
通过打开一个到实际文件的连接来创建一个 FileInputStream
,该文件通过文件系统中的 File
对象 file
指定。
FileInputStream(String name)
通过打开一个到实际文件的连接来创建一个 FileInputStream
,该文件通过文件系统中的路径名 name
指定。
输入流所关联的文件,如果不存在,会报错,不会自动补充。
in.read()
从此输入流中读取一个数据字节。
FileInputStream in= new FileInputStream("a.txt");
//输入输入流,读取文件中的数据
//一次读取一个字节
int by = in.read();
System.out.println(by);
by = in.read();
System.out.println(by);
by = in.read();
System.out.println(by);
by = in.read();
System.out.println(by);
//如果读取不到有效的字节,就会返回-1 ,我们经常使用-1来判断这个文件的数据是否读取完毕。
by = in.read();
System.out.println(by);
//流使用完毕,记得释放资源
in.close();
in.read(byte[] b)
从此输入流中将最多 b.length
个字节的数据读入一个 byte 数组中。
byte[] bytes = new byte[1024];
//把读取到的字节,装进你传进来的这个容器
int len = in.read(bytes); //返回的是你一次实际读取到的有效字节个数
System.out.println("读取到的有效字节个数:"+len);
System.out.println(Arrays.toString(bytes));
//把字节数组转换成字符串
String s = new String(bytes, 2, len);
System.out.println(s);
in.close();
in.read(byte[] b, int off, int len)
从此输入流中将最多 len
个字节的数据读入一个 byte 数组中。
int len = in.read(bytes,0,3);
System.out.println("读取到的有效字节个数:" + len);
len = in.read(bytes, 0, 3);
System.out.println("读取到的有效字节个数:" + len);
len = in.read(bytes, 0, 3);
System.out.println("读取到的有效字节个数:" + len);
System.out.println(Arrays.toString(bytes));
in.close();
}
文件的复制
//进行文件的复制
//方式1:读取一个字节,写入一个字节来复制文本文件
FileInputStream in = new FileInputStream("MyTest.java");
FileOutputStream out=new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\MyTest.java");
int by = 0;
while ((by = in.read()) != -1) {//只要读取还有发现-1即结束,会一直进行读写
out.write(by);
out.flush();
}
//释放资源
in.close();
out.close();
}
}
实例为:
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream("C:\\Users\\LCH\\Desktop\\新建文件夹 (2)");
FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\test");
int by = 0;
long start = System.currentTimeMillis();
while ((by = in.read()) != -1) {
out.write(by);
out.flush();
}
long end = System.currentTimeMillis();
System.out.println("复制完成共耗时"+(end-start)+"毫秒");
//释放资源
in.close();
out.close();
}
}
但是上述方法比较慢,我们可以用一下方法
FileInputStream in = new FileInputStream("MyTest.java");
FileOutputStream out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\MyTest123.java");
//定义一个字节数组,来充当缓冲区
byte[] bytes = new byte[1024 * 8];
//定义一个变量,来记录每次读取到的有效字节个数
int len=0;
//频繁的读写
while ((len=in.read(bytes))!=-1){
out.write(bytes,0,len);
out.flush();
}
//释放资源
in.close();
out.close();
}
}
流的异常处理(抓取 处理)
FileInputStream in = null;
FileOutputStream out = null;
try {
//System.out.println(1 / 0);如果此处发生异常,无法进行以下代码,既用到以下格式
in = new FileInputStream("E:\\课堂录制视频\\录像160.mp4");
out = new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\test.mp4");
byte[] bytes = new byte[1024 * 8];
int len = 0;
long start = System.currentTimeMillis();
while ((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
out.flush();
}
long end = System.currentTimeMillis();
System.out.println("复制完成共耗时" + (end - start) + "毫秒");
} catch (IOException e) {
e.printStackTrace();
} finally {
//释放资源
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
高效的字节输入输出流
BufferdInputStream:输入
创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
BufferdOutputStream:输出
创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
private static void test4() throws IOException{
BufferedInputStream in = new BufferedInputStream(new FileInputStream("C:\\Users\\ShenMouMou\\Music\\音乐\\音乐\\塞任唱片-MSR - Renegade.mp3"));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\塞任唱片-MSR - Renegade.mp3"));
//一次读取一个字节,写入一个字节来复制mp3
byte[] bytes = new byte[1024 * 8];
int by = 0;
long start = System.currentTimeMillis();
while ((by = in.read(bytes)) != -1) {
out.write(bytes,0,by);
out.flush();
}
long end = System.currentTimeMillis();
System.out.println("复制完成共耗时" + (end - start) + "毫秒");
//释放资源
in.close();
out.close();
}
字符流
在学习字符流之前,先学习编码与解码。
编码:把字符串转换成字节数组,但是要按照某种编码方式
解码:按照与编码统一编码方式,把字节数组转换成字符串
但是编解码是码表用的不一致,会乱码。
字符流的存在是因为汉字占两个字节,用字节流操作我们还需要对汉字进行拆分与合并,,所以提供了字符流的操作。
字符流的继承关系:父类输入流抽象类:Reader。父类抽象类输出流:Writer
Reader的常见子类:BufferReader,InputstreamReader,StringReader.
Writer的常见子类:BufferWriter,OutputStreamWriter,StringWriter.
String str="可乐";
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));
String s = new String(bytes);
System.out.println(s);
String str2="中文乱码问题";
//按照GBK来变得码
byte[] gbks = str2.getBytes("UTF-8");
String s1 = new String(gbks, "GBK");
System.out.println(s1);
//乱码出现的原因:就是编解码用的不是同一张码表
OutputStreamWriter
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 码表 将要写入流中的字符编码成字节。
它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
OutputStreamWriter(OutputStream out)
创建使用默认字符编码的 OutputStreamWriter。创建文件输出流,来关联文件,当关联的文件不存在时,会自动创建这个文件。
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("a.txt"));
OutputStreamWriter(OutputStream out, String charsetName)
创建使用指定字符集的 OutputStreamWriter。
OutputStreamWriter out2 = new OutputStreamWriter(new FileOutputStream("a.txt"),"GBK");
在文件中写入数据
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("a.txt"));
//一次写入一个字符
out.write('我');
out.flush();
//写入换行符
out.write("\r\n");
//一次写入一个字符串
out.write("你好,最近怎么样");
out.write("\r\n");
out.flush(); //字符流,要刷新,把缓冲区中的数据,刷新到磁盘中
out.write("你好,最近怎么样");
out.write("\r\n");
//字符流,要刷新,把缓冲区中的数据,刷新到磁盘中
out.flush();
//释放资源
out.close(); //刷新并关闭
追加写入:即在已有文件中追加内容,在相应的文件后追加true即可。(三种写入方法,与输入流类似)
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("c.txt",true));
out.write("文字");
out.write("\r\n");
out.write('文字1');
out.write("\r\n");
//一次写入一个字符数组
out.write(new char[]{'a', 'b', 'c', '既', '去'});
out.write("\r\n");
//一次写入字符串的一部分 从字符串的2索引出开始,写3个字符
out.write("写入字符串的一部分", 2, 3);
out.write("\r\n");
//一次写入字符数组的一部分,从0索引处开始 写3个字符
out.write(new char[]{'a', 'b', 'c', '哈', '哈'}, 0, 3);
out.write("\r\n");
//字符流,记得要刷新
out.flush();
//释放资源
out.close();
输出流的异常处理:
OutputStreamWriter out = null;
try {
out = new OutputStreamWriter(new FileOutputStream("c.txt", true));
out.write("文字");
out.write("\r\n");
out.write('文字1');
out.write("\r\n");
//一次写入一个字符数组
out.write(new char[]{'a', 'b', 'c', '以', '撒'});
out.write("\r\n");
//一次写入字符串的一部分 从字符串的2索引出开始,写3个字符
out.write("写入字符串的一部分", 2, 3);
out.write("\r\n");
//一次写入字符数组的一部分,从0索引处开始 写3个字符
out.write(new char[]{'a', 'b', 'c', '哈', '哈'}, 0, 3);
out.write("\r\n");
//字符流,记得要刷新
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
//释放资源
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
文件的读取:
InputStreamReader in = new InputStreamReader(new FileInputStream("e.txt"));
//一次读取一个字符
int ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println(ch);
ch = in.read();
System.out.println((char) ch);
ch = in.read();
System.out.println((char) ch);
ch = in.read();
System.out.println((char)ch);
//如果读取不到,就返回-1 我们就可以使用 -1 来判断这个文件是否读取完毕
ch = in.read();
System.out.println(ch);
in.close();
InputStreamReader in = new InputStreamReader(new FileInputStream("e.txt"));
//定义一个字符数组来充当容器,可以一次取到这个容器中
char[] chars=new char[1000];
//一次读取1000个字符,放到字符数组中。返回值是实际读取到的字符个数
int len = in.read(chars);
System.out.println(len);
System.out.println(Arrays.toString(chars));
InputStreamReader in = new InputStreamReader(new FileInputStream("e.txt"));
//定义一个字符数组来充当容器,可以一次取到这个容器中
char[] chars = new char[1000];
//一次读取一部分字符,放到字符数组中 从0索引处开始把读取到字符放进去 4 就是一次读去4个字符
int len = in.read(chars,0,4);
System.out.println(len);
System.out.println(Arrays.toString(chars));
in.close();
字符流的文件复制
//使用字符流来复制文本文件
InputStreamReader reader = new InputStreamReader(new FileInputStream("MyTest.java"));
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\aaa.java"));
//读取一个字符,写一个字符来复制
int ch=0;//用来记录每次读取到的字符
while ((ch=reader.read())!=-1){
writer.write(ch);
writer.flush();//字符流记得读取一些字符就刷新
}
reader.close();
writer.close();
//为单个读取,效率底下,不建议。
//建议为一个数组的形式进行
InputStreamReader reader = new InputStreamReader(new FileInputStream("MyTest.java"));
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\bbb.java"));
char[] chars = new char[2000]; //定义一个字符数组,充当缓冲区
int len=0;//用来记录实际读取到的字符个数
int count=1;
while ((len=reader.read(chars))!=-1){
System.out.println("循环次数"+(count++));
writer.write(chars,0,len);
writer.flush();
}
reader.close();
writer.close();
System.out.println("复制完成");
文件复制时流的异常处理模块(同理)
InputStreamReader reader = null;
OutputStreamWriter writer = null;
try {
reader = new InputStreamReader(new FileInputStream("MyTest.java"));
writer = new OutputStreamWriter(new FileOutputStream("C:\\Users\\ShenMouMou\\Desktop\\bbb.java"));
char[] chars = new char[2000];
int len = 0;
int count = 1;
while ((len = reader.read(chars)) != -1) {
System.out.println("循环次数" + (count++));
writer.write(chars, 0, len);
writer.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("复制完成");
}
}
FileWriter和FileReader复制文本文件
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化我们的书写,转换流提供了对应的子类。FileWriter与FileReader的便捷字符流
转换流 父类 便捷类 子类
OutputStreamWriter ------- FileWriter
InputStreamReader ------- FileReader
但是,便捷字符流,唯一就是不能指定编码 他自己也没有特有的方法,用的是继承下来的方法。
高效字符流:
BufferedReader (Reader in)
创建一个使用默认大小输入缓冲区的缓冲字符输入流
BufferedReader reader = new BufferedReader(new FileReader("MyTest.java"));
char[] chars = new char[2000]; //定义一个字符数组,充当缓冲区
int len = 0;//用来记录实际读取到的字符个数
int count = 1;
while ((len = reader.read(chars)) != -1) {
System.out.println("循环次数" + (count++));
writer.write(chars, 0, len);
writer.flush();
}
reader.close();
writer.close();
}
}
BufferedWriter (Writer out)
创建一个使用默认大小输出缓冲区的缓冲字符输出流
BufferedWriter writer= new BufferedWriter(new FileWriter(“haha.java”));
高效的字符流BufferedReader 里面有特有的方法 String readLine() 一次读一行文本。
BufferedWriter void newLine() 写入一个换行符,具有平台兼容性。
BufferedReader reader = new BufferedReader(new FileReader("MyTest.java"));
BufferedWriter writer = new BufferedWriter(new FileWriter("hehe.java"));
//循环的进行读取一行,写入一行
//一行一行读取,读取不到返回的是null
String line=null; //定义一个变量,来记录每次读取到的一行文本
while ((line=reader.readLine())!=null){
writer.write(line);
//writer.write("\r\n");
writer.newLine();
writer.flush();
}
writer.close();
reader.close();
}
}