概念
java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。
Java 的 I/O 大概可以分成以下几类:
- 磁盘操作:File
- 字节操作:InputStream 和 OutputStream
- 字符操作:Reader 和 Writer
- 对象操作:Serializable
- 网络操作:Socket
- 新的输入/输出:NIO
File
public class File extends Object implements Serializable, Comparable<File>
File 类是 java.io 包中唯一代表磁盘文件本身的对象,是文件和目录路径名的抽象形式,该类不具有从文件读取信息和向文件写入信息的功能,它仅描述文件本身的属性。File 类定义了一些与平台无关的方法来操作文件,主要用来获取或处理与磁盘文件相关的信息,像文件名、 文件路径、访问权限和修改日期等,还可以浏览子目录层次结构。
构造方法:
1、File(File parent,String child):根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
2、File(String pathname):通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例。如果给定字符串是空字符串,则结果是空的抽象路径名。
3、File(String parent,String child):根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
注意:在各个操作系统中,路径的分隔符是不一样的,例如:Windows中使用反斜杠:"\
",Linux|Unix中使用正斜杠:"/
"。在使用反斜杠时要写成"\\
"的形式,因为反斜杠要进行转义。如果要让Java保持可移植性,应该使用File类的静态常量File.pathSeparator。
方法:
(一)获取文件属性
例:获取并显示该文件的长度、是否可写、最后修改日期以及文件路径等属性信息
import java.io.File;
import java.util.Date;
public class Iotest {
public static void main(String[] args) {
File f = new File("E:\\test","test.txt");
System.out.println("文件长度:"+f.length()+"字节");
System.out.println("文件或者目录:"+(f.isFile()?"是文件":"不是文件"));
System.out.println("文件或者目录:"+(f.isDirectory()?"是目录":"不是目录"));
System.out.println("是否可读:"+(f.canRead()?"可读取":"不可读取"));
System.out.println("是否可写:"+(f.canWrite()?"可写入":"不可写入"));
System.out.println("是否隐藏:"+(f.isHidden()?"是隐藏文件":"不是隐藏文件"));
System.out.println("最后修改日期:"+new Date(f.lastModified()));
System.out.println("文件名称:"+f.getName());
System.out.println("文件路径:"+f.getPath());
System.out.println("绝对路径:"+f.getAbsolutePath());
}
}
运行如下:
文件长度:0字节
文件或者目录:是文件
文件或者目录:不是目录
是否可读:可读取
是否可写:可写入
是否隐藏:不是隐藏文件
最后修改日期:Mon Jul 08 11:19:28 CST 2019
文件名称:test.txt
文件路径:E:\test\test.txt
绝对路径:E:\test\test.txt
(二)创建和删除文件
例:判断文件是否存在,存在删除,不存在则创建
import java.io.File;
import java.io.IOException;
public class Iotest {
public static void main(String[] args) {
File f = new File("E:\\test","test.txt");
if(f.exists()) {
f.delete();
}
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
(三)创建和删除目录
例:判断目录是否存在,存在删除,不存在则创建
import java.io.File;
public class Iotest {
public static void main(String[] args) {
File f=new File("E:\\test1");
if(f.exists()) {
f.delete();
}
f.mkdir();
}
}
(四)遍历目录
File 类的 list() 方法提供了遍历目录功能,该方法有如下两种重载形式。
1、String[] list()
该方法表示返回由 File 对象表示目录中所有文件和子目录名称组成的字符串数组,如果调用的 File 对象不是目录,则返回 null。
提示:list() 方法返回的数组中仅包含文件名称,而不包含路径。但不保证所得数组中的相同字符串将以特定顺序出现,特别是不保证它们按字母顺序出现。
2、 String[] list(FilenameFilter filter)
该方法的作用与 list() 方法相同,不同的是返回数组中仅包含符合 filter 过滤器的文件和目录,如果 filter 为 null,则接受所有名称。
例:遍历C盘根目录下的所有文件和目录,并显示文件或目录名称、类型及大小
import java.io.File;
public class Iotest {
public static void main(String[] args) {
File f = new File("C:/");
String[] fileList = f.list();
for(int i = 0; i< fileList.length; i++) {
System.out.print(fileList[i] + "\t\t");
System.out.print((new File("C:/",fileList[i])).isFile()?"文件"+ "\t\t":"文件夹"+"\t\t");
System.out.println((new File("C:/",fileList[i])).length()+"字节");
}
}
}
由于 list() 方法返回的字符数组中仅包含文件名称,因此为了获取文件类型和大小,必须先转换为 File 对象再调用其方法。如下所示的是实例的运行效果:
$Recycle.Bin 文件夹 0字节
Boot 文件夹 4096字节
bootmgr 文件 399860字节
Documents and Settings 文件夹 4096字节
DRIVERS 文件夹 0字节
Foxmail 7.2 文件夹 4096字节
Intel 文件夹 0字节
pagefile.sys 文件 8262529024字节
PerfLogs 文件夹 0字节
Program Files 文件夹 4096字节
Program Files (x86) 文件夹 4096字节
ProgramData 文件夹 4096字节
System Volume Information 文件夹 0字节
Users 文件夹 4096字节
Windows 文件夹 12288字节
嗨格式录屏文件 文件夹 0字节
迅雷下载 文件夹 0字节
例:假设希望只列出目录下的某些文件,这就需要调用带过滤器参数的 list() 方法。首先需要创建文件过滤器,该过滤器必须实现 java.io.FilenameFilter
接口,并在 accept() 方法中指定允许的文件类型。
如下所示为允许 SYS、TXT 和 BAK 格式文件的过滤器实现代码:
import java.io.File;
import java.io.FilenameFilter;
public class FileTest implements FilenameFilter{
@Override
public boolean accept(File dir, String name) {
// TODO Auto-generated method stub
return name.endsWith(".sys")||name.endsWith(".txt")||name.endsWith(".bak");
}
}
import java.io.File;
public class Iotest {
public static void main(String[] args) {
File f = new File("C:/");
String[] fileList = f.list(new FileTest());
for(int i = 0; i< fileList.length; i++) {
System.out.print(fileList[i] + "\t\t");
System.out.print((new File("C:/",fileList[i])).isFile()?"文件"+ "\t\t":"文件夹"+"\t\t");
System.out.println((new File("C:/",fileList[i])).length()+"字节");
}
}
}
运行如下:
pagefile.sys 文件 8262529024字节
RandomAccessFile
public class RandomAccessFile extends Object implements DataOutput, DataInput, Closeable
RandomAccessFile既可以读取文件内容,也可以向文件输出数据。同时支持“随机访问”的方式,可以直接跳转到文件的任意地方来读写数据。与OutputStream、Writer等输出流不同的是RandomAccessFile允许自由定义文件记录指针,RandomAccessFile可以不从开始的地方开始输出,因此RandomAccessFile可以向已存在的文件后追加内容。如果程序需要向已存在的文件后追加内容,则应该使用RandomAccessFile。
RandomAccessFile的一个重要使用场景就是网络请求中的多线程下载及断点续传。
构造方法:
1、RandomAccessFile(File file, String mode)
2、RandomAccessFile(String name, String mode)
RandomAccessFile类有两个构造函数,其实这两个构造函数基本相同,只不过是指定文件的形式不同——一个需要使用String参数来指定文件名,一个使用File参数来指定文件本身。除此之外,创建RandomAccessFile对象时还需要指定一个mode参数,该参数指定RandomAccessFile的访问模式,一共有4种模式:
1)r:表示以只读方式打开,调用结果对象的任何write方法都将导致抛出IOException
2)rw:打开以便读取和写入,如果该文件尚不存在,则尝试创建该文件
3)rws:打开以便读取和写入,相对于"rw",还要求对文件内容或元数据的每个更新都同步写入到底层存储设备
4)rwd:打开以便读取和写入,相对于"rw",还要求对文件内容的每个更新都同步写入到底层存储设备
示例:读写文件
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Iotest {
public static void main(String[] args) throws IOException {
File file=new File("E:\\test\\words.txt");
if(file.exists()) {
file.delete();
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
RandomAccessFile raf=new RandomAccessFile(file,"rw");
String str1="晴天,阴天,多云,小雨,大风,中雨,小雪,雷阵雨";
String str2=new String(str1.getBytes("GBK"),"iso8859-1"); //如果不转换编码,写入文件的是乱码
raf.writeBytes(str2);
System.out.println("当前文件指针的位置:"+raf.getFilePointer());
raf.seek(6); //移动文件指针
System.out.println("从文件头跳过6个字节,现在文件内容如下:");
byte[] buffer=new byte[2];
int len=0;
while((len=raf.read(buffer,0,2))!=-1)
{
System.out.print(new String(buffer,0,len)); //输出文件内容
}
}
}
运行如下:
当前文件指针的位置:48
从文件头跳过6个字节,现在文件内容如下:
阴天,多云,小雨,大风,中雨,小雪,雷阵雨