Java I/O
核心组成
Java I/O的核心组成就是五个类:File, OutputStream, InputStream, Reader, Writer和一个接口:Serializable.
1. File
(1)java.io.File是一个普通的类,直接产生实例化对象。实例化对象有两个构造方法:
---- public File(String pathname);
---- public File(String parent,String child),设置父路径和子路径;
(2)对文件的基本操作
----创建一个新的文件(D盘创建一个名为b的文件):
import java.io.File;
import java.io.IOException;
public class Test1{
public static void main(String[] args){
File file = new File("D:/b");
try{
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建好了之后可以去对应的地方查看是否创建成功,如图:创建成功:

----判断文件是否存在:public boolean exists();
----删除文件:public boolean delete();
----例子:如果文件不存在则创建,存在则删除:
import java.io.File;
import java.io.IOException;
public class Test1{
public static void main(String[] args) throws IOException {
//文件的路径
File file = new File("D:/b");
//判断文件是否存在,存在则删除
if(file.exists()){
file.delete();
//否则创建
}else{
file.createNewFile();
}
}
}
在这里可以注意到一个问题就是:开发环境不同的话,路径的表示也就不一样,所以为了解决这个问题,使用路径分隔符时都会采用File类的一个常量public static final String separator来描述。那么上述例子就可以改为:
import java.io.File;
import java.io.IOException;
public class Test1{
public static void main(String[] args) throws IOException {
//主要就是这里分隔符的不同
//separator由不同操作系统下的JVM来决定路径分隔符到底是怎样的形式
File file = new File(File.separator+"D:"+File.separator+"b");
if(file.exists()){
file.delete();
}else{
file.createNewFile();
}
}
}
(3)对目录的操作
----取得父路径或父File对象:public String getParent(), public File getParentFile();
----创建目录:public boolean mkdirs();无论多少级父目录都会创建;
如:
import java.io.File;
import java.io.IOException;
public class Test1{
public static void main(String[] args) throws IOException {
File file = new File(File.separator+"D:"+File.separator+"b");
//创建父目录,如果不存在,则创建
if(!file.getParentFile().exists()){
//有多少级父目录就创建多少级
file.getParentFile().mkdir();
}
//如果文件存在则删除
if(file.exists()){
file.delete();
//不存在则创建
}else {
file.createNewFile();
}
}
}
(4)文件信息
----判断路径是否是文件:public boolean isFile();
----判断路径是否是目录:public boolean isDirectory();
----取得文件的大小(字节):public long length();
----最后一次修改时间:public long lastModified();
如:获取文件信息:
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class Test1{
public static void main(String[] args) throws IOException {
File file = new File(File.separator+"D:"+File.separator+"a");
if(file.exists()&&file.isFile()){
System.out.println("文件大小:"+file.length());
System.out.println("文件最后一次修改日期:"+new Date(file.lastModified()));
}
}
}


可以对照一下,对于文件信息的获取,结果没有任何问题。那么对于目录呢?举个例子:列出目录的全部组成:
import java.io.File;
import java.io.IOException;
public class Test1{
public static void main(String[] args) throws IOException {
File file = new File(File.separator+"D:"+File.separator+"ideaIU2018");
//是目录且存在的前提
if(file.exists()&&file.isDirectory()){
//列出目录中的全部内容
File[] result = file.listFiles();
//加强版的for循环,foreach
for(File f : result){
System.out.println(f);
}
}
}
}
D:\ideaIU2018\IDEAworkplace
D:\ideaIU2018\IntelliJ IDEA 2018.1

对照一下结果,很显然没有任何问题。
(5)应用举例
虽然File中提供了listFiles()方法,但是该方法只能列出本目录中第一级信息,若要列出目录中所有级的信息,就必须自己来处理,而要完成这个操作,必须通过递归模式解决。如:打印一下当前目录下的所有层级的文件信息。
import java.io.File;
public class Test1{
public static void main(String[] args){
File file = new File(File.separator+"D:"+File.separator+"a");
listAllFiles(file);//开始递归
}
private static void listAllFiles(File file) {
//先判断是否为目录
if(file.isDirectory()){
//是的话,列出所有的子目录
File[] f = file.listFiles();
if(f != null){
//子目录不为空,打印文件信息
//加强的for循环
for(File ff : f){
//递归
listAllFiles(ff);
}
}
//假如不是目录,就是文件,直接输出即可
}else{
System.out.println(file);
}
}
}
这里有个问题,所有的代码都是在main线程下完成的,假如listAllFiles()方法没有完成,那么对于main后续的执行将无法完成。这种耗时的操作让主线程出现了阻塞,而导致后续代码无法正常执行完毕,那么应该怎么解决这个问题呢?那就是再产生一个新的线程去处理。
2. OutputStream,InputStream,Reader,Writer
File类不支持文件内容的处理,若要处理文件内容,则需要通过流来处理。
(1)流的分类:输入流,输出流;
(2)java.io包中,流分为两种:字节流InputStream, OutputStream和字符流Reader, Writer;
(3)区别:字节流是原生的操作;而字符流是经过处理后的操作;在进行网络数据传输、磁盘数据保存时支持的类型只有字节,所以磁盘中的数据必须先读取到内存后才能进行操作,而内存会把字节变为字符,同时字符也更加适合处理中文;
(4)流程:字节流与字符流流程类似,以文件操作为例,先根据文件路径创建File类对象;再根据字节流或字符流的子类实例化父类对象;再进行数据的读写操作;最后关闭流close();
(5)字节输出流(OutputStream)
实现了两个接口:
public abstract class OutputStream implements Closeable,Flushable
可以看出OutputStream是一个抽象类,所以想要实例化父类,只能使用子类。在这里看几个例子,更容易表达意思,也更容易理解一些。
----实现文件内容的输出:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Test1{
public static void main(String[] args) throws IOException {
File file = new File(File.separator+"D:"+File.separator+"a");
//判断文件的父目录是否存在
if(!file.getParentFile().exists()){
//存在则创建多级父目录
file.getParentFile().mkdirs();
}
//抽象类,需通过子类实例化
OutputStream output = new FileOutputStream(file);
//输出到文件的内容
String msg = "hahhahahahahworld";
//以字节数组输出
output.write(msg.getBytes());
//最后一定要关闭输出
output.close();
}
}
在这里可以看到在文件输出的时候没有createFile()仍然会创建文件,这是因为文件在输出的时候,所有文件会自动帮用户创建,不需要手工创建。
----文件内容的追加:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Test1{
public static void main(String[] args) throws IOException {
File file = new File(File.separator+"D:"+File.separator+"a");
//判断文件的父目录是否存在
if(!file.getParentFile().exists()){
//存在则创建多级父目录
file.getParentFile().mkdirs();
}
//抽象类,需通过子类实例化,追加(append),并不会覆盖之前的内容
OutputStream output = new FileOutputStream(file,true);
//追加的内容
String msg = "hahhahahahahworldabcdefg";
output.write(msg.getBytes());
//最后一定要关闭输出
output.close();
}
}
----部分内容的输出:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Test1{
public static void main(String[] args) throws IOException {
File file = new File(File.separator+"D:"+File.separator+"a");
//判断文件的父目录是否存在
if(!file.getParentFile().exists()){
//存在则创建多级父目录
file.getParentFile().mkdirs();
}
//抽象类,需通过子类实例化,追加(append),并不会覆盖之前的内容
OutputStream output = new FileOutputStream(file,true);
String msg = "HELLOWORLD";
//追加len=5的内容,从下表为零处开始
output.write(msg.getBytes(),0,5);
//最后一定要关闭输出
output.close();
}
}
(6)字节输入流(InputStream)
实现了程序输出内容到文件的处理,只实现了Closeable接口:
public abstract class InputStream implements Closeable
例如:实现文件信息的读取:
import java.io.*;
public class Test1{
public static void main(String[] args) throws IOException {
File file = new File(File.separator+"D:"+File.separator+"a");
//判断文件是否存在
if(file.exists()){
InputStream input = new FileInputStream(file);
//读取的最大信息量1024
byte[] data = new byte[1024];
//将数据读取到数组中
int len = input.read(data);
//将数组转换为String
String result = new String(data,0,len);
System.out.print("读取内容:"+result);
//关闭流
input.close();
}
}
}
与OutputStream用法类似。
(7)字符输出流(Writer)
字符适合处理中文数据,相比OutputStream()多了一个Appendable接口:
public abstract class Writer implements Appendable,Closeable,Flushable
Writer类提供了一个直接输出字符串的方法:
public void write(String str) throws IOException
如:通过Writer实现输出:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Test1{
public static void main(String[] args) throws IOException {
File file = new File(File.separator+"D:"+File.separator+"a");
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
String msg = "haha";
Writer out = new FileWriter(file);
out.write(msg);
out.close();
}
}
(8)字符输入流(Reader)
Reader类中没有方法可以直接读取字符串类型,只能通过字符数组进行读取操作。
如:通过文件读取数据:
import java.io.*;
public class Test1{
public static void main(String[] args) throws IOException {
File file = new File(File.separator+"D:"+File.separator+"a");
//先判断文件是否存在
if(file.exists()){
//Reader是一个抽象类,若要读取文件,需要使用FileReader
Reader in = new FileReader(file);
//没有直接的读取方法,所以借助字符数组
char[] data = new char[1024];
int len = in.read(data);
String result = new String(data,0,len);
System.out.println("读取内容:"+result);
in.close();
}
}
}
(9)转换流
OutputStreamWriter将字节输出流变为字符输出流;
InputStreamReader将字节输入流变为字符输入流。
3. Serializable
对象序列化指的是:将内存中保存的对象变为二进制数据流的形式进行传输,或者将其保存在文本中。但是并不意味着所有类的对象都可以被序列化,严格来说,需要被序列化的类对象往往需要传输使用,同时这个类必须实现java.io.Serializable接口。但是该接口并没有任何的方法定义,只是一个标识而已。
如:实现对象序列化
import java.io.*;
class Person implements Serializable{
private String name;
private int age;
public Person(String name,int age){
super();
this.name = name;
this.age = age;
}
public String toString(){
return "Person name = "+name+" ,age = "+age;
}
}
public class Test1{
public static final File FILE = new File(File.separator+"D:"+File.separator+"a");
public static void main(String[] args) throws IOException {
ser(new Person("zhang",23));
}
public static void ser(Object obj) throws IOException {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(FILE));
os.writeObject(obj);
os.close();
}
}
4396

被折叠的 条评论
为什么被折叠?



