java.io
包里的核心组成就是五个类(File
、OutputStream
、InputStream
、Writer
、Reader
)。
1. File文件操作类
1.1 文件操作
在Java.io
包之中,File
类是唯一一个与文件本身操作(创建、删除、取得信息等)有关的程序类。
-
File
类中关于文件有如下方法::
① 设置文件路径:File(String pathname)
② 设置父路径和子路径:File(String parent, String child)
③ 判断文件是否存在:exists()
④ 新建文件:createNewFile()
,只是创建文件本身,对于其内容并不做处理!
⑤ 删除文件:delete()
对于文件路径有以下要注意的点:
Windows
平台下使用的是 反斜杠,而在Linux
系统下使用的是 “/” 。所以在使用路径分隔符时都会采用File类的一个常量separator
来描述。它会根据平台而选定使用哪种分隔符。
package www.bittech.com.file;
import java.io.File;
import java.io.IOException;
public class TestFile {
public static void main(String[] args) {
//将本地文件系统关联到Java的File对象,设置文件路径
File file = new File("D:" + File.separator + "test.txt");
//判断文件是否存在,如果存在则删除,如果不存在则新建
if(file.exists()) {
if(file.delete()) {
System.out.println("文件已经存在并且删除成功");
} else {
System.out.println("文件已经存在但是删除失败");
}
} else {
try {
if(file.createNewFile()) {
System.out.println("文件不存在并且新建成功");
} else {
System.out.println("文件不存在但是新建失败");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
1.2 目录操作
-
File
类中关于目录有如下方法:
①mkdir()
:只会创建当前目录,如果父目录不存在,则创建失败
②mkdirs()
:创建目录时,如果父目录不存在,则一并创建
package www.bittech.com.file;
import java.io.File;
public class TestFile {
public static void main(String[] args) {
File file = new File("D:" + File.separator + "a"
+ File.separator + "b");
//mkdirs连a目录和b目录一起创建
//如果目录存在则删除,如果不存在则创建
if(file.exists()) {
file.delete();
} else {
if(file.mkdirs()) {
System.out.println("目录创建成功");
} else {
System.out.println("目录创建失败");
}
}
}
}
1.3 获取文件信息
① 获得父路径:getParent()
② 获得父File
对象:getParentFile()
③ 判断是否是文件:isFile()
④ 判断是否是目录:isDirectory()
⑤ 判断是否是隐藏文件:isHidden()
⑥ 获取文件大小(字节数):length()
⑦ 最后一次修改日期:lastModified()
⑧ 列出目录中的全部组成:listFiles()
package www.bittech.com.file;
import java.io.File;
import java.util.Date;
public class TestFile {
public static void main(String[] args) {
File file = new File("D:" + File.separator + "a" + File.separator + "b");
//文件信息
System.out.println("是否存在:" + file.exists());
System.out.println("是否是文件:" + file.isFile());
System.out.println("是否是目录:" + file.isDirectory());
System.out.println("是否是隐藏文件:" + file.isHidden());
System.out.println("文件大小(字节):" + file.length());
System.out.println("最近的修改时间:" + new Date(file.lastModified()));
//遍历目录(在a/b里面又手动添加了一个test.txt文件后进行此过程)
if (file != null && file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
System.out.println("父路径:" + f.getParent() + " 文件名:" + f.getName() + " 文件绝对路径:" + f.getAbsolutePath());
}
}
}
}
}
2. 字节流与字符流
在java.io
包中,流分为两种:字节流(InputStream
、OutputStream
)和字符流(Reader
、Writer
)。又或者分为输入流(InputStream
、Reader
)和输出流(OutputStream
、Writer
)。
File
类本身不支持文件内容处理,如果要处理文件内容,则必须要通过流的操作模式来完成。字节流与字符流操作的本质区别只有一个:字节流是原生的操作,而字符流是经过处理后的操作。
- 不管使用的是字节流还是字符流,其基本的操作流程几乎是一样的,以
File
类文件操作为例:
① 根据文件路径创建File
类对象
② 根据字节流或字符流的子类实例化父类对象
③ 进行数据的读取或写入操作
④ 关闭流(close()
)(对于IO操作属于资源处理,所有的资源处理操作(IO操作、数据库操作、网络)最后必须要进行关闭)
2.1 字节输出流(OutputStream)
OutputStream类的定义结构:
public abstract class OutputStream implements Closeable, Flushable
OutputStream类实现了Closeable,Flushable两个接口,这两个接口中的方法有:
1. Closeable: public void close() throws IOException;
2. Flushable: public void flush() throws IOException;
-
我们可以看到
OutputStream
是一个抽象类,所以要想实例化,就必须要使用子类。如果要进行文件的操作,可以使用FileOutputStream
类来处理,这个类的构造方法如下:
① 接收File
类(覆盖):FileOutputStream(File file)
② 接收File
类(追加):FileOutputStream(File file, boolean append)
,默认是false
!! -
在
OutputStream
类中进行定义的方法还有:
① 将给定的字节数组内容全部输出:write(byte b[])
② 将部分字节数组内容输出:write(byte b[], int off, int len)
③ 输出单个字节:write(int b)
package www.bittech.com.file;
import java.io.*;
public class TestOutputStream {
public static void main(String[] args) {
String directory = "D:" + File.separator + "a" + File.separator + "b";
File file = new File(directory, "test.txt");
OutputStream out = null;
try {
out = new FileOutputStream(file);
//将给定的字节数组内容全部输出
out.write("Java is best".getBytes());
//单个字节
out.write("\n".getBytes());
//ASCII int
out.write(49);
//将部分字节数组内容输出
byte[] buff = "HelloWorld".getBytes();
out.write(buff, 2, 5);
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
AutoCloseable自动关闭资源
从JDk1.7
开始追加了一个AutoCloseable
接口,这个接口的主要目的是自动进行关闭处理。这种自动关闭处理是需要结合try
语句进行调用,必须在try中定义对象。
下述操作直接使用自动关闭官员的形式,所以这里不再详细赘述!!
2.2 字节输入流(InputStream)
InputStream类的定义结构:
public abstract class InputStream implements Closeable
InputStream类只实现了Closeable接口。
-
同
OutputStream
的使用一样,InputStream
也是一个抽象类,如果要对其实例化,同样也需要使用子类。如果要对文件进行处理,则使用FileInputStream
类。 -
在
InputStream
类中提供的方法有:
① 读取数据到字节数组中:read(byte b[])
② 读取部分数据到字节数组中:read(byte b[], int off, int len)
③ 读取单个字节:read()
package www.bittech.com.file;
import java.io.*;
public class TestInputStream {
public static void main(String[] args) {
String directory = "D:" + File.separator + "a" + File.separator + "b";
File file = new File(directory, "test.txt");
try(InputStream in = new FileInputStream(file)) {
byte[] data = new byte[7];
int len = in.read(data);
System.out.println("读取数据的长度:" + len);
System.out.println("读取的数据:" + new String(data));
System.out.println(in.read());//空格 -> ascii 32
System.out.println(in.read());//b -> ascii 98
//把剩下的逐个儿读完
int d = -1;
while ((d = in.read()) != -1) {
System.out.print((char) d);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 问题:怎样一下子可以把数据全部读取完?
package www.bittech.com.file;
import java.io.*;
public class TestInputStream {
public static void main(String[] args) {
String directory = "D:" + File.separator + "a" + File.separator + "b";
File file = new File(directory, "test.txt");
try(InputStream in = new FileInputStream(file)) {
//采用缓存的方式
byte[] buff = new byte[1024];
int len = -1;
while ((len = in.read(buff)) != -1) {
System.out.print(new String(buff, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.3 字符输出流(Writer)
Writer类的定义结构:
public abstract class Writer implements Appendable, Closeable, Flushable
与OutputStream类相比多了一个Appendable接口。
Writer
类提供了一个直接输出字符串的方法:write(String str)
package www.bittech.com.file;
import java.io.*;
public class TestWriter {
public static void main(String[] args) {
String directory = "D:" + File.separator + "a" + File.separator + "b";
File file = new File(directory, "test.txt");
try(Writer writer = new FileWriter(file)) {
writer.write("Java is best!");
writer.write("\n");
writer.write(65);
writer.write("\n");
writer.write(new char[]{'A', 'B', 'C'});
writer.write("\n");
writer.append("Hello World");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.4 字符输入流(Reader)
在上面提到的Writer
类中提供有方法直接向目标源写入字符串,而在Reader
类中没有方法可以直接读取字符串类型,这个时候只能通过字符数组进行读取操作。
package www.bittech.com.file;
import java.io.*;
public class TestReader {
public static void main(String[] args) {
String directory = "D:" + File.separator + "a" + File.separator + "b";
File file = new File(directory, "test.txt");
try(Reader reader = new FileReader(file)) {
System.out.println((char) reader.read());
System.out.println((char) reader.read());
char[] buff = new char[10];
int len = -1;
while ((len = reader.read(buff)) != -1) {
System.out.print(new String(buff, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. 流的转化
① OutputStreamWriter
:将字节输出流变为字符输出流
② InputStreamReader
:将字节输入流变为字符输入流
package www.bittech.com.file;
import java.io.*;
public class TestStream {
public static void main(String[] args) {
File file = new File("D:" + File.separator + "test.txt");
//字节输出流转换成字符输出流
try(OutputStream out = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(out)) {
writer.write("你好Java!");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
//字节输入流转换成字符输入流
try(InputStream in = new FileInputStream(file);
InputStreamReader reader = new InputStreamReader(in)) {
char[] buff = new char[1024];
int len = -1;
while ((len = reader.read(buff)) != -1) {
System.out.print(new String(buff, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}