本章知识框架:
流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种。I/0(Input/Output,输入输出)流提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。虽然IO流通常与磁盘文件存取有关,但是程序的源和目的地也可以是键盘、鼠标、内存或显示器窗口等。
Java有数据源处理输入/输出模式,程序从指向源的输入流中读取源中的数据,如图15.1所示源可以是文作,网络、压缩包或其他数据源。
一、输入/输出流
1.输入流
InputStream类是字节输入流的抽象类,它是所有字节输入流的父类。InputStream类的具体层次结构如图所示。
2.输出流
OutputStream类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。OutputStream类的具体如下图。
二、File类
File类是java.io包中唯一代表磁盘文件本身的类。File类定义了一些与平台无关的方法来操作文件,可以通过调用File类中的方法,实现创建、删除、重命名文件等操作。File类的对象主要用来获取文件本身的一些信息,如文件所在的目录、文件的长度、文件读写权限等。数据流可以将数据写入文件中,文件也是数据流最常用的数据媒体。
1.文件的创建与删除
可以使用File类创建一个文件对象。通常使用以下三种构造方法来创建文件对象。
1.File(String pathname)
该构造方法通过将给定的路径名字符串转换为抽象路径名来创建一个新File实例。语法如下:
new File(String pathname)
2.File(String parent,String child)
该构造方法根据定义的父路径和子路径字符串(包括文件名)创建一个新的File对象。语法如下:
new File(String parent,String child)
parent:父路径字符串,如D:/或D:/doc。
child:子路径字符串,如violet.txt。
3.File(File f,String child)
该构造方法根据f抽象路径名和child路径名字符串创建一个新File实例,语法如下:
new File(File f,String child)
f:父路径对象,如D:/doc/。
child:子路径字符串,如letter.txt。
说明:对于Microsoft Windows平台,包含盘符的路径名前缀由驱动器号和一个“:”组成。如果路径名是绝对路径名,还可能后跟“\\”。
当使用File类创建一个文件对象后,例如:
File file = new File("word.txt");
如果当前目录中不存在名称为word的文件,File类对象可通过调用createNewFile()方法创建一个名称为word.txt的文件;如果存在word.txt,可以通过文件对象的delete()方法将其删除。
import java.io.File;
import java.io.IOException;
public class FileTest {
public static void main(String[] args){
File file = new File("C:\\happy\\word.txt");//创建文件对象
if(file.exists()){//如果该文件存在
file.delete();
System.out.println("文件已删除");
}else{
try{
file.cteateNewFile();
System.out.println("文件已创建");
}catch(Exception e){
e.printStackTrace();
}
}
}
}
如果c盘下没有word.txt文件,则会创建该文件并输出如下内容:
文件已创建
如果c盘下有word.txt文件,则会创建该文件并输出如下内容:
文件已删除
2.获取文件信息
序号 | 方法描述 |
---|---|
1 | public String getName() 返回由此抽象路径名表示的文件或目录的名称。 |
2 | public String getParent()、 返回此抽象路径名的父路径名的路径名字符串,如果此路径名没有指定父目录,则返回 null 。 |
3 | public File getParentFile() 返回此抽象路径名的父路径名的抽象路径名,如果此路径名没有指定父目录,则返回 null 。 |
4 | public String getPath() 将此抽象路径名转换为一个路径名字符串。 |
5 | public boolean isAbsolute() 测试此抽象路径名是否为绝对路径名。 |
6 | public String getAbsolutePath() 返回抽象路径名的绝对路径名字符串。 |
7 | public boolean canRead() 测试应用程序是否可以读取此抽象路径名表示的文件。 |
8 | public boolean canWrite() 测试应用程序是否可以修改此抽象路径名表示的文件。 |
9 | public boolean exists() 测试此抽象路径名表示的文件或目录是否存在。 |
10 | public boolean isDirectory() 测试此抽象路径名表示的文件是否是一个目录。 |
11 | public boolean isFile() 测试此抽象路径名表示的文件是否是一个标准文件。 |
12 | public long lastModified() 返回此抽象路径名表示的文件最后一次被修改的时间。 |
13 | public long length() 返回由此抽象路径名表示的文件的长度。 |
14 | public boolean createNewFile() throws IOException 当且仅当不存在具有此抽象路径名指定的名称的文件时,原子地创建由此抽象路径名指定的一个新的空文件。 |
15 | public boolean delete() 删除此抽象路径名表示的文件或目录。 |
16 | public void deleteOnExit() 在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。 |
17 | public String[] list() 返回由此抽象路径名所表示的目录中的文件和目录的名称所组成字符串数组。 |
18 | public String[] list(FilenameFilter filter) 返回由包含在目录中的文件和目录的名称所组成的字符串数组,这一目录是通过满足指定过滤器的抽象路径名来表示的。 |
19 | public File[] listFiles() 返回一个抽象路径名数组,这些路径名表示此抽象路径名所表示目录中的文件。 |
20 | public File[] listFiles(FileFilter filter) 返回表示此抽象路径名所表示目录中的文件和目录的抽象路径名数组,这些路径名满足特定过滤器。 |
21 | public boolean mkdir() 创建此抽象路径名指定的目录。 |
22 | public boolean mkdirs() 创建此抽象路径名指定的目录,包括创建必需但不存在的父目录。 |
23 | public boolean renameTo(File dest) 重新命名此抽象路径名表示的文件。 |
24 | public boolean setLastModified(long time) 设置由此抽象路径名所指定的文件或目录的最后一次修改时间。 |
25 | public boolean setReadOnly() 标记此抽象路径名指定的文件或目录,以便只可对其进行读操作。 |
26 | public static File createTempFile(String prefix, String suffix, File directory) throws IOException 在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。 |
27 | public static File createTempFile(String prefix, String suffix) throws IOException 在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。 |
28 | public int compareTo(File pathname) 按字母顺序比较两个抽象路径名。 |
29 | public int compareTo(Object o) 按字母顺序比较抽象路径名与给定对象。 |
30 | public boolean equals(Object obj) 测试此抽象路径名与给定对象是否相等。 |
31 | public String toString() 返回此抽象路径名的路径名字符串。 |
import java.io.File;
import java.io.IOException;
public class FileTest {
public static void main(String[] args) throws IOException {
File file = new File("C:\\happy\\word.txt");//创建文件对象
if(file.exists()) {//如果该文件存在
String name = file.getName();//获取文件名称
long length = file.length();//获取文件长度
boolean hidden = file.isHidden();//判断文件是否为隐藏文件
System.out.println("文件名称"+name);//输出信息
System.out.println("文件长度"+length);
System.out.println("该文件是隐藏文件吗?"+hidden);
}else {
System.out.println("该文件不存在");
}
}
}
输出结果:
文件名称word.txt
文件长度26
该文件是隐藏文件吗?false
三、文件输入/输出流
1.FileInputStream与FileOutputStream类
FileInputStream类与FileOutputStream类都用来操作磁盘文件。如果用户的文件读取需求比较简单,则可以使用FileInputStream类,该类继承自| InputStream 类。FileOutputStream类与FileInputStream类对应,提供了基本的文件写入能力。FileOu tputStream 类是OutputStream类的子类。
FileInputStream类常用的构造方法如下
FileInputStream(String name)。 FileInputStream(File file)。
第一个构造方法使用给定的文件名nam ne 创建一个FileInputStream对象,第二个构造方法使用File对象创建FileInputStream对象。第一个构途造方法比较简单,但第二个构造方法允许在把文件连接输入流之前对文件做进一步分析。
FileOutputStream类有与FileInputStrear m类相同的参数构造方法,创建一个FileOutputStream对象时,可以指定不存在的文件名,但此文件不下能是一个已被其他程序打开的文件。下面的实例就是使用 FileInputStream 类与FileOutputStream类实理现文件的读取与写入功能的。
例题:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileStreamDemo {
public static void main(String[] args) throws IOException {
File file = new File("C:\\happy\\word.txt");//创建文件对象
FileOutputStream out = new FileOutputStream(file);
byte[] by = "hello world".getBytes();
out.write(by);
out.close();
FileInputStream in = new FileInputStream(file);
byte[] by1 = new byte[1024];
int len = in.read(by1);
System.out.println(new String(by1,0,len));
in.close();
}
}
结果:
hello world
2.FileReader和FileWrite类
使用FileOutputStream类向文件中写入数据与使用FilelnputStream类从文件中将内容读出来都在一点不足,即这两个类都只提供了对字节或字节数组的读取方法。由于汉字在文件中占用两个字节如果使用字节流,读取不好可能会出现乱码现象,此时采用字符流FieReader类或FileWriter类即可免这种现象。
FileReader类和FileWriter类对应了 FilenputStream 类和FileOutputStream 类FileReader 类顺序地取文件,只要不关闭流,每次调用read0方法就顺序地读取源中其余的内容,直到源的末尾或流被关闭。
例题:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
//字符流 FileWriter输出流,FileReader输入流
File file = new File("C:\\happy\\word.txt");//创建文件对象
FileWriter write = new FileWriter(file);
//char[] ch = new char[] {'h','e','l','l','o'};
//带缓存的输出流
BufferedWriter bw = new BufferedWriter(write);
bw.write("门前大桥下,游过一群鸭");
bw.newLine();
bw.write("门前大桥下,游过一群鸭");
bw.newLine();
bw.write("门前大桥下,游过一群鸭");
bw.close();
write.close();
FileReader reader = new FileReader(file);
BufferedReader br = new BufferedReader(reader);
String s1 = br.readLine();
System.out.println("第一行:"+s1);
System.out.println("第二行:"+br.readLine());
System.out.println("第三行:"+br.readLine());
reader.close();
}
}
结果:
第一行:门前大桥下,游过一群鸭
第二行:门前大桥下,游过一群鸭
第三行:门前大桥下,游过一群鸭
四、带缓存的输入/输出流
1.BufferedInputStream与BufferedOutputStream类
2.BufferedReader与BufferedWrite类
例题:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedDemo {
public static void main(String args[]) {
String content[] = { "好久不见", "最近好吗", "常联系" };// 写入的内容
File file = new File("c:\\happy\\word.txt"); // 创建文件对象
try {
FileWriter fw = new FileWriter(file); // 文件字符输出流
BufferedWriter bw = new BufferedWriter(fw); // 换成输出流
for (int k = 0; k < content.length; k++) { // 遍历要输入的内容
bw.write(content[k]); // 写入字符串
bw.newLine(); // 写入一个换行符
}
bw.close(); // 关闭缓冲输出流
fw.close(); // 关闭文件字符输出流
} catch (IOException e) {
e.printStackTrace();
}
try {
FileReader fr = new FileReader(file); // 文件字符输入流
BufferedReader br = new BufferedReader(fr);// 缓冲输入流
String tmp = null; // 作为缓冲的临时字符串
int i = 1; // 行数
// 从文件中读出一行,如果读出的内容不为null,则进入循环
while ((tmp = br.readLine()) != null) {
System.out.println("第" + i + "行:" + tmp); // 输出读取的内容
i++; // 行数递增
}
br.close(); // 关闭缓冲输入流
fr.close(); // 关闭文件字符输入流
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果:
第1行:好久不见
第2行:最近好吗
第3行:常联系
五、数据输入/输出流
数据输入/输出流(DatalnputStream类与 DataOutputStream类)允许应用程序以与机器无关的方从底层输入流中读取基本Java数据类型。也就是说,当读取一个数据时,不必再关心这个数值应当哪种字节。DataInputStream类与 DataOutputStream类的构造方法如下。
DataInputStream(InputStream in):使用指定的基础IputStream对象创建一个DatalnputStrean
对象。
DataOutputStream(OutputStreamout):创建一个新的数据输出流,将数据写入指定基础输出流。
DataOutputStream类提供了将字符串double数据、int数据、boolean 数据写入文件的方法。其中将字符串写入文件的方法有3种,分别是 writeBytes(String s)writeChars(String s)、writeUTF(Sting s)。由于Java中的字符是Unicode编码,是双字节的,writeBytes0方法只是将字符串中的每一个字符的低字节容写入目标设备中,而writeChars0方法将字符串中的每一个字符的两个字节的内容都写到目标设备中writeUTF()方法将字符串按照UTF编码后的字节长度写入目标设备,然后才是每一个字节的UTF编码.
DatalnputStream类只提供了一个readUTFO方法返回字符。这是因为要在一个连续的字节流读取一个字符串,如果没有特殊的标记作为一个字符串的结尾,并且不知道这个字符串的长度,就无法知道读取到什么位置才是这个字符串的结束DataOutputStream类中只有writeUTFO方法向目标设备中入字符串的长度,所以也能准确地读回写入字符串。
例题:
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DateStreamDemo {
public static void main(String[] args) throws IOException {
File file = new File("C:\\happy\\Word.txt");//创建文件对象
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
dos.writeBoolean(false);
dos.writeUTF("放学后茶会");
dos.writeDouble(13.33);
dos.close();
fos.close();
FileInputStream fis = new FileInputStream(file);
DataInputStream dis = new DataInputStream(fis);
System.out.println(dis.readBoolean());
System.out.println(dis.readUTF());
System.out.println(dis.readDouble());
}
}
输出结果:
false
放学后茶会
13.33