文章目录
前言(转载请说明作者!)4.30~5.7编写
- 2020.5.5 发布
File类
File类,表示文件或者文件夹,负责文件的本身,而不负责文件的内容。
即它可以获取位置、名字、长度等不涉及内容的操作。
File类的构造方法
方法 | 描述 |
---|---|
File(String pathname) | 传入一个字符串类型的文件路径来创建一个新的File对象 |
File(String parent,String child) | 传入一个字符串类型的父路径和一个字符串类型的子路径(包括文件名称)来创建一个File对象 |
File(File parent,String child) | 传入指定的File类的父路径和字符串类型的子路径(包括文件名称)创建一个File对象 |
File类常用方法
方法 | 描述 |
---|---|
boolean exists() | 判断文件是否存在 |
boolean canWrite() | 判断文件是否可写 |
boolean canRead() | 判断文件是否可读 |
boolean isFile() | 判断是否为文件 |
boolean isDirectory() | 判断当前文件是否是目录 |
long lastModified() | 获取文件最后一次修改时间 |
long length() | 获取文件的长度 以字节为单位 |
boolean delete() | 删除当前文件 |
boolean renameTo(File dest) | 重命名当前File对象表示的文件 |
String getAbsolutePath() | 获取文件的绝对路径 |
String getName() | 获取文件的名称 |
---------------------- | ----------------- |
boolean mkdir() | 创建当前File对象指定的目录 |
public String[] list() | 以字符串数组返回当前文件夹下的所有文件 |
public File[] listFiles() | 以文件数组返回当前文件夹下的所有文件 |
public String[] list(FilenameFilter filter) public File[] listFiles(FilenameFilter filter) | FilenameFilter是一个接口。 boolean accept(File dir,String filename) 来限制由list()方法返回的文件数量 使之只返回符合某一过滤器的文件。 |
File类的一些常用方法实例
- e.g. 1
import java.io.File;
import java.io.IOException;
public class FileDemo {
public static void main(String[] args) {
File file1 = new File("newFile.txt");
char mark = File.separatorChar;
File file2 = new File("D:" + mark);
if(!file1.exists()) {
try {
file1.createNewFile();
} catch(IOException ex) {
ex.printStackTrace();
}
}
System.out.println(file1.canRead());
System.out.println(file1.length());
System.out.println(file1.getAbsolutePath());
System.out.println(file1.getName());
System.out.println(file2.isDirectory());
String[] stringList = file2.list();
System.out.println("指定目录下的文件为:");
for (String file : stringList) {
System.out.println(file);
}
File[] fileList = file2.listFiles();
System.out.println("指定目录下的文件为:");
for (File file : fileList) {
System.out.println(file);
}
}
}
- e.g. 2 显示过滤后的文件
import java.io.File;
import java.io.FilenameFilter;
public class FileNameFilterDemo {
public static void main(String[] args) {
File file = new File("D:");
File[] files = file.listFiles(new NameFilter());
if (files != null) {
for (File tempFile : files) {
System.out.println(tempFile);
}
}
}
}
class NameFilter implements FilenameFilter {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".doc") || name.endsWith(".docx");
}
}
IO流
IO流的分类
按数据流的方向分类
-
输入流
如果数据是从外界流入程序的,就是输入流,反之为输出流。
-
输出流
按是否直接操作源或目标节点
-
节点流 节点流中,数据源直接关联程序
-
装饰流
按处理数据单位不同
-
字节流
字节(Byte):1Byte = 8bit(位),是最基础的存储单位之一。
-
字符流
字符:例如:a、b、c、8000、学……
字节流
无论是文本、图片……,计算机文件都是以二进制(字节)形式存在的,Java的IO流中对字节的输入输出提供了一系列的流,统称为字节流。
字节流是程序中最常用的流,根据数据的传输方向可将其分为字节输入流和字节输出流。
在io包中,提供了两个抽象类InputStream和OutputStream,它们是字节流的顶级父类。
- inputStream的一些方法
方法声明 | 功能描述 |
---|---|
int read() | 从输入流读取一个8位的字节,把它转换为0~255之间的整数,并返回这一整数。 |
int read(byte[] b) 等同:read(byte[] b, 0 , b.length) | 从输入流读取若干字节,把它们保存到参数b指定的字节数组中,返回的整数表示读取字节的数目。b叫做读取数据的缓冲区 |
int read(byte[] b,int off, int len) | 从输入流读取若干字节,把它们保存到参数b指定的字节数组中,off指定字节数组开始保存数据的起始下标,len表示读取的字节数目。 |
void close() | 关闭此输入流 并释放与该流关联的所有系统资源。 |
- OutputStream的一些方法
方法名 | 说明 |
---|---|
write(int b) | 将指定的字节b写入此输出流。 要写入的字节是参数b的八个低位。 b的24个高位被忽略。 |
write(byte[] b) | 将b.length个字节从指定的byte数组写入此输出流。 |
write(byte[] b, int off, int len) | 将指定byte数组中从偏移量off开始的len个字节写入此输出流。 |
flush() | 刷新输出流,即使缓冲区未满强制输出缓冲区中的字节。 |
close() | 关闭此输出流并释放与此流有关的所有系统资源。 |
由于计算机中的数据基本都保存在硬盘的文件中,因此操作文件中的数据是一种很常见的操作。针对文件的读写,io包中提供了两个类,分别是FileInputStream
和FileOutputStream
。
包:com.s12
FileInputStreamDemo.java
package com.s12;
import java.io.File;
import java.io.FileInputStream;
public class FileInputStreamDemo {
public static void main(String[] args) throws Exception {
String dir = System.getProperty("user.dir"), sep = File.separator;
// 文件字节输入流
FileInputStream in = new FileInputStream(dir + sep + "src" + sep + "com"
+ sep + "s12" + File.separator + "word.txt");
int b = 0;
while (true) {
b = in.read();
// 如果读不出,则为-1
if (b == -1) {
break;
}
System.out.print(b + " ");
}
in.close();
}
}
word.txt
HelloInputStream!
FileOutputStreamDemo.java
package com.s12;
import java.io.File;
import java.io.FileOutputStream;
public class FileOutputStreamDemo {
public static void main(String[] args) throws Exception {
String str = "信息工程学院", sep = File.separator;
// FOS后面的true的意思是追加
FileOutputStream fos = new FileOutputStream(
"src" + sep + "com" + sep + "s12" + sep + "out.txt", true);
byte[] bytes = str.getBytes();
for (byte b : bytes) {
fos.write(b);
}
fos.close();
}
}
缓冲区
文件复制程序的思路
FileCopyDemo.java
package com.s12;
import java.io.*;
public class FileCopyDemo {
public static void main(String[] args) throws Exception {
String sep = File.separator,
thisDir = "src" + sep + "com" + sep + "s12" + sep;
// 创建一个字节输入流,读取当前目录下out.txt文件
InputStream in = new FileInputStream(thisDir + "out.txt");
// 创建一个文件字节输出流,将读取的数据写入到目录中
OutputStream out = new FileOutputStream(thisDir + "outout.txt");
try {
// 记住每个读取的字节
int b;
// 获取复制前的系统时间
long beginTime = System.currentTimeMillis();
for (; (b = in.read()) != -1; out.write(b))
;
// 获取结束时间
long endTime = System.currentTimeMillis();
System.out.println("复制文件所用时间:" + (endTime - beginTime) + "ms。");
} finally {
in.close();
out.close();
}
}
}
一个一个字节的读写,效率非常低。像从北京运一万个包裹到上海,如果每次运送一个,就必须运输一万次,这样的效率显然非常低。
为了减少运输次数,可以先把一批包裹装在车厢中,这时的车厢就相当于一个临时缓冲区。当通过流的方式拷贝文件时,为了提高效率也可以定义一个字节数组作为缓冲区。在拷贝文件时,可以一次性读取多个字节的数据,并保存在字节数组中,然后将字节数组中的数据一次性写入文件。
- 方案1
package com.s12;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class NewFileCopyDemo {
public static void main(String[] args) throws Exception {
String sep = File.separator,
thisDir = "src" + sep + "com" + sep + "s12" + sep;
// 这里使用了Java7后的语法:try-with-resources(try括号里面声明的资源在try后都会关闭)
try (InputStream in = new FileInputStream(thisDir + "out.txt");
OutputStream out = new FileOutputStream(
thisDir + "outout.txt")) {
byte[] buff = new byte[1024];
int len;
long beginTime = System.currentTimeMillis();
for (; (len = in.read(buff)) != -1; out.write(buff, 0, len))
;
long endTime = System.currentTimeMillis();
System.out.println("复制文件所用时间:" + (endTime - beginTime) + "ms。");
} catch (Exception e) {
e.printStackTrace();
}
}
}
- 方案2
package com.s12;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class BufferedCopyDemo {
public static void main(String[] args) {
String sep = File.separator,
thisDir = "src" + sep + "com" + sep + "s12" + sep;
try (BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(thisDir + "out.txt"));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(thisDir + "outBuffered.txt"))) {
int b;
long beginTime = System.currentTimeMillis();
// bis里面的read无参方法读取的是缓冲区内容
for (; (b = bis.read()) != -1; bos.write(b))
;
long endTime = System.currentTimeMillis();
System.out.println("复制文件所用时间:" + (endTime - beginTime) + "ms。");
} catch (Exception e) {
e.printStackTrace();
}
}
}
这次课带着你认识了缓冲区,用两种方式实现了缓冲区
使用字节缓冲流,读写大文件尤其离不开它。
字符流
InputStream类和OutputStream类在读写文件时操作的都是字节 。 如果希望在程序中操作字符,使用这两个类就不太方便。
io包提供了字符流。同字节流一样,字符流也有两个抽象的顶级父类,分别是Reader
和Writer
。
如需对文本文件的内容 进行读取,想从文件中直接读取字符可以使用字符输入流FileReader
,通过此流可以从关联的文件中读取一个或一组字符。
程序演示
package com.s12;
import java.io.File;
import java.io.FileReader;
public class FileReaderDemo {
public static void main(String[] args) {
String sep = File.separator,
thisDir = "src" + sep + "com" + sep + "s12" + sep;
// FileReader用来读取文件中的字符
try (FileReader reader = new FileReader(thisDir + "word.txt")) {
// 变量用于记录读取的字符
int ch;
// 不是字符流末尾就转为字符打印
for (; (ch = reader.read()) != -1; System.out.println((char) ch))
;
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.s12;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {
public static void main(String[] args) {
String sep = File.separator,
thisDir = "src" + sep + "com" + sep + "s12" + sep;
// FileWriter用于向文件写入数据
try (FileWriter writer = new FileWriter(thisDir + "writer.txt")) {
String str = "信工";
writer.write(str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
转换流
有时字节流和字符流之间需要进行转换
这时就要用到InputStreamReader
和OutputStreamWriter
package com.s12;
import java.io.*;
public class TransferStreamDemo {
public static void main(String[] args) throws Exception {
String sep = File.separator,
thisDir = "src" + sep + "com" + sep + "s12" + sep;
FileInputStream in = new FileInputStream(thisDir + "word.txt");
Reader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
FileOutputStream out = new FileOutputStream(thisDir + "dest.txt");
Writer osw = new OutputStreamWriter(out);
BufferedWriter bw = new BufferedWriter(osw);
String line;
while ((line = br.readLine()) != null) {
bw.write(line + '\n');
}
br.close();
bw.close();
}
}
虽然Java中的流很多,但是使用起来并不复杂,要么直接关联源或目标要么一层层的包装流。
装饰设计模式
e.g.
-
FilelnputStream fis= new FileInputStream(new File( “in.txt” );
文件输入流对象关联了文件
-
DatalnputStream dis= new DatalnputStream(fis);
数据流包装文件输入流
-
InputStreamReader isr = new InputStreamReader(dis);
转换流转为Reader类型的对象,包装FileInputStream对象
-
BufferedReader br= new Buffered Reader(isr);
缓冲流
通过层层装饰,流的功能不断增强。**
Eclipse IDE的主体部分就是Eclipse,我们可以通过安装插件的方式使其功能不断增强。
装饰设计模式就是将程序的主体部分和装饰部分分离,即将变化较小的部分和容易变化的部分分开。