Java IO流
1. File类
一个File类可以表示一个具体的文件。
文件包括两大类:文件夹和文件。
文件夹也是文件的一种,区别是文件夹可以包含很多个文件。
1.1 创建文件/文件夹
注意要抛出异常或者捕获异常。
import java.io.File;
import java.io.IOException;
public class FileDemo1 {
public static void main(String[] args) throws IOException { //IO流一般都要抛异常
//创建一个新的普通文件
File file1 = new File("E:\\1234.txt"); //只是赋予了一个路径值,但文件不一定存在
boolean flag1 = file1.createNewFile(); //若已经存在,则创建失败
System.out.println(flag1?"创建成功":"创建失败");
//创建一个新的文件夹
File file2 = new File("E:\\我的文件夹");
boolean flag2 = file2.mkdir(); //若已经存在,则创建失败
System.out.println(flag2?"创建成功":"创建失败");
//创建多级文件夹
File file3 = new File("E:\\我的文件夹\\这又是\\这还是");
boolean flag3 = file3.mkdirs(); //若已经存在,则创建失败
System.out.println(flag3?"多级文件夹创建成功":"多级文件夹创建失败");
}
}
1.2 删除和查询
删除格式:
file1.delete();
import java.io.File;
import java.io.IOException;
public class FileDemo2 {
public static void main(String[] args) throws IOException {
//1. 判断某个文件是否存在
File file4 = new File("E:\\哈哈哈");
boolean flag4 = file4.exists();
if(flag4){//存在
System.out.println("文件已经存在");
}else{//不存在
file4.mkdir();
}
//2. 获取文件的大小
File file5 = new File("E:\\111.txt");
file5.createNewFile();
//file5.length(); //文件的字节大小
System.out.println( file5.length());
//3. 获取文件名和路径名
//file5.getName();//文件的名字,返回类型为字符串
//file5.getPath();//文件的路径,返回类型为字符串
System.out.println( file5.getName());
System.out.println( file5.getPath());
}
}
注: File中有个length方法,作用是返回文件的字节数。
关于 length 技巧如下:
类名中的都是方法。
存在的类 | 类型 | 作用 |
---|---|---|
String | 方法 length() | 返回字符串中字符的个数 |
数组 | 属性 length | 返回数组中元素的个数 |
集合 | 方法 size() | 返回集合中元素的个数 |
File | 方法 length() | 返回文件对象的字节数 |
1.3 递归遍历
递归:自己调用自己。
两个方法:
- isDirectory() 判断文件是否是文件夹。
- ListFiles() 查询某个文件夹下的所有文件。
- package com.java.IOliu;
import java.io.File;
public class FileDemo3 {
//找出某个文件夹下所有的文件
public static void showFile(String pathname){
File file6 = new File(pathname);
//1.判断文件是否是文件夹
boolean flag = file6.isDirectory();
//选择某个文件夹下的所有文件
if (flag){//是文件夹
File[] files0 = file6.listFiles();
for(File tempFile:files0){
boolean flag2 = tempFile.isDirectory();
if (flag2){
showFile(tempFile.getPath());
}else{
//不是文件夹
//获取此文件的路径
String filePath = file6.getPath();
System.out.println("普通文件,路径是:"+filePath);
}
}
}else{//不是文件夹
//获取此文件的路径
String filePath = file6.getPath();
System.out.println("普通文件,路径是:"+filePath);
}
}
public static void main(String[] args) {
FileDemo3.showFile("D:\\IDEA 安装包");
//FileDemo3.showFile("D:\\"); 若是直接写盘符根目录,会报空指针异常
}
}
1.4 递归BUG的解决
在上述代码中,若遍历的目录是盘符根目录,会报空指针异常。
原因是在遍历根目录的时候由于根目录没有上级文件夹,所以会导致files0 数组为null。
解决方法是添加一个if判断条件,需要把高级for循环 改为传统for循环。
需要改动的代码:
for(int i=0;files0!=null&&i<files0.length;i++){
boolean flag2 = files0[i].isDirectory();
if (flag2){
showFile(files0[i].getPath());
则,主函数里传入实参路径可以为:
public static void main(String[] args) {
FileDemo3.showFile("E:\\");
}
测试通过。
2. 输入流和输出流
2.1 字节流
字节流可以读取一切文件。
2.1.1字节输入流 FileInputStream
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class IODemo1 {
public static void main(String[] args) {
//字节输入流
Scanner input = new Scanner(System.in);
try {
//1.在文件和程序之间铺设管道
//1.1 直接传
FileInputStream fis = new FileInputStream("E:\\111.txt");
//1.2 形参传
// File f1 = new File("E:\\111.txt");
// FileInputStream fis = new FileInputStream(f1);
//2.开水龙头
//2.1 读取单个字符
int ch =fis.read(); //read()方法一次只读一个字节,所以读中文时容易乱码
System.out.println("ch="+(char)ch); //基本数据类型可以强转
//2.2 读取所有字符
int ch1 =0;
while((ch1=fis.read())!=-1 ){
System.out.print((char)ch1);
}
//3.关水龙头(关闭流)
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.1.2字节输出流 FileOutputStream
import java.io.FileOutputStream;
public class IODemo2 {
public static void main(String[] args) {
try {
//1、创建水厂
String data = "hello html,hello,ps";
//2、铺设管道
FileOutputStream fos = new FileOutputStream("E:\\000.txt");
//3、开水龙头,放水
byte[] tempbyte = data.getBytes();
//write()。如果文件不存在,会自动创建文件
fos.write(tempbyte);
//4、关水龙头
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
注: FileOutputStream方法多次写入时,
FileOutputStream fos = new FileOutputStream(“E:\000.txt”): 覆盖。
FileOutputStream fos = new FileOutputStream(“E:\000.txt”,true): 追加。
2.1.3字节缓冲输入流 BufferedInputStream
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
public class IODemo4 {
public static void main(String[] args) {
try {
long startTime = System.currentTimeMillis();
//1、水厂(E:\\000.txt)
//2、铺设管道
//注意:FileInputStream是细管道,速度慢,但是可以直接传入盘符参数
//BufferedInputStream是粗管道,读写速度快,但是不能直接接受盘符参数
//仍需要细管道传入进来实参,粗管道用形参接收
InputStream fis = new FileInputStream("E:\\jdk api 1.8_google.CHM");
BufferedInputStream bis = new BufferedInputStream(fis);
//2、开水龙头
//创建一辆车,车的大小为1kb,1024字节
byte[] car = new byte[1024*4]; //车的大小越大,速度越快(不是无限大,很容易达到上限,一般1024*1024就可以了。看电脑内存)
int len =0;
// len = bis.read(car); //read()方法可以把字节先存入到car,再一次性读取。len=-1,代表读取完毕。
while((len = bis.read(car))!=-1){
System.out.println(len); //字节数
}
//4、关水龙头
bis.close();
long endTime = System.currentTimeMillis();
System.out.println("共消耗了"+(endTime-startTime)+"ms");
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.1.4字节缓冲输出流 BufferedOutputStream
import java.io.*;
public class IODemo5 {
public static void main(String[] args) {
try {
long startTime = System.currentTimeMillis();
//1、水厂(E:\\000.txt)
//2、铺设管道
//注意:FileInputStream是细管道,速度慢,但是可以直接传入盘符参数
//BufferedInputStream是粗管道,读写速度快,但是不能直接接受盘符参数
//仍需要细管道传入进来实参,粗管道用形参接收
InputStream fis = new FileInputStream("E:\\jdk api 1.8_google.CHM");
BufferedInputStream bis = new BufferedInputStream(fis);
//将jdk api 1.8_google.CHM 复制到D盘并命名为jdk.chm
OutputStream fos = new FileOutputStream("D:\\jdk.chm");
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] car = new byte[1024*1024];
int len =0;
while((len = bis.read(car))!=-1){
bos.write(car,0,len); //0代表car的下标,len代表每辆车装的量
}
//4、关水龙头
bis.close();
bos.close();
long endTime = System.currentTimeMillis();
System.out.println("共消耗了"+(endTime-startTime)+"ms");
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.2 字符流
字符流适合读取纯文本文件,尤其是在读取包含汉字的文本时不会出现乱码问题。
只适合读文本,不适合读 图片,视频等文件。
2.2.1 读取
import java.io.FileReader;
public class ReaderDemo1 {
public static void main(String[] args) {
try {
//1、水厂(数据):E:\\111.txt
//2、铺水管:盘符----->程序
FileReader fr = new FileReader("E:\\111.txt");
//3、放水
char[] car = new char[1024];
int len =0;
while((len=fr.read(car))!=-1){
System.out.println(len);
System.out.println((char)car[0]);
}
//4、关水龙头
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.2.2 写入
import java.io.FileWriter;
import java.io.IOException;
public class ReaderDemo2 {
public static void main(String[] args) {
try {
//1、水厂(数据)
String str = "java真的很简单?";
//2、铺水管
FileWriter fw = new FileWriter("E:\\text.txt");
// FileWriter fw = new FileWriter("E:\\text.txt",true); // 追加
//3、放水
fw.write(str);
//4、关水龙头
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedReader/BufferedWriter的用法和FileReader/FileWriter的用法类似。