总体流程图
15.1 输入/输出流
流是一组有序的数据序列,可分为输入流和输出流两种。
程序从指向源的输入流中读取源中数据,源可以是文件、网络、压缩包或者其他数据源
输出流的指向是数据要到达的目的地,输出流的目标可以是文件、网络、压缩包、控制台和其他数据输出目标。
15.1.1输入流
InputStream 类是字节输入流的抽象类,它是所有字节输入流的父类。
read()方法:从输入流中读取数据的下一字节。返回0~255的int字节值。如果因为已经到达流末尾而没有可用的字节,则返回值为-1.
read(byte[]b):从输入流中读入一定长度的字节,并以整数的形式返回字节数。
mark(int readlimit)方法: 在输入流的当前位置放置一个标记,readlimit参数告知此输入流再标记位置失效之前允许读取的字节数。
reset()方法:将输入指针返回到当前所做的标记处。
skip(long n)方法:跳过输入流上的n个字节并返回实际跳过的字节数。
markSupported()方法:如果当前流支持mark()/reset()操作就返回turn。
close方法:关闭此输入流并释放与该流关联的所有系统资源。
并不是所有的 InputStream类的子类都支持 InputStream 类中定义的所有方法、如skip0、mark0、Tset0等方法只对某些子类有用。
Java 中的字符是Unicode 编码,是双字节的。InputStream 类是用来处理字节的,并不适合处理字符文本。Java为字符文本的输入专门提供了一套单独的类,即Reader 类,但Reader 类并不是InputStear类的替换者,只是在处理字符串时简化了编程。Reader 类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。Reader 类的具体层次结构如图所示。
15.1.2 输出流
OutputStream 类是字节输出流的抽象类,此抽象类是表达输出字节流的所有类的超类。
OutputStream类中的所有方法均返回void,在遇到错误时会引发IOException异常,
1.write(intb)方法:将指定的字节写入此输出流。
2. writebyte[]b)方法:将b个字节从指定的byte 数组写入此输出流。
3.write(byte[ b,int off,int len)方法:将指定 byte 数组中从偏移量of开始的len个字节写入此输
出流。
4.fush0方法:彻底完成输出并清空缓存区。
5.close0方法:关闭输出流。
Writer 类是字符输出流的抽象类,所有字符输出类的实现都是它的子类。Writer 类的层次结构如:
15.2 File 类
15.2.1 创建与删除文件
1.File(String pathname)
该构造方法通过将给定的路径名字符串转换为抽象路经名来创建一个新的 File 实例。语法
new File(String pathname)
其中,pathname代表路经名称(包含文件名)。例如:
File file = new File("D:/1.txt")
2.File(String parent,String child)
该构造方法根据定义的父路径和子路经字符串(包含文件名)创建一个新的 File 对象。语法
new File(String parent,String child)
parent:父路径字符串,如D:/或D:/doc
3.File(File f,String child)
package 十五;
import java.io.File;
import java.io.IOException;
public class FileText {
public static void main(String[] args) throws IOException { //抛出异常,以防找不到D盘或者已经存在
File file = new File("D:\\word.txt"); //创建文件对象
if(file.exists()) { //如果该文件存在
file.delete();
System.out.println("该文件已删除");
}else {
file.createNewFile(); //创建文件
System.out.println("该文件已经创建");
}
}
}
15.2.2 获取文件信息
判断是否为隐藏文件
package 十五;
import java.io.File;
import java.io.IOException;
public class FileText {
public static void main(String[] args) {
File file = new File("D:\\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("文件不存在");
}
}
}
打印所有文件
package 十五;
import java.io.File;
import java.io.IOException;
public class FileText {
public static void main(String[] args) {
File file = new File("D:\\学校文件");
Add(file);
}
public static void Add(File f) {
for(File ff : f.listFiles()) { //获取该文件夹下所有文件(含文件夹)
if(ff.isDirectory()) { //判断该文件是否为文件夹
System.out.println("----------" + ff.getName());
Add(ff);
}else {
System.out.println(ff.getName());
}
}
}
}
15.3 文件输入/输出流
15.3.1 FileInputStream 与 FileOutputStream 类
FileInputStream 类与 FileOutputStream类都用来操作磁盘文件。如果用户的文件读取需求比较简单,则可以使用FileInputStream类,该类继承自InputStream 类。FileOutputStream类与FileInputStream 类对应,提供了基本的文件写入能力。FileOutputStream类是OutputStream类的子类。
FileInputStream类常用的构造方法如下:
FileInputStream(String name)。
FileInputStream(File file)。
第一个构造方法使用给定的文件名name创建一个FileInputStream对象,第二个构造方法使用File对象创建FileInputStream对象。第一个构造方法比较简单,但第二个构造方法允许在把文件连接输入流之前对文件做进一步分析。
FileOutputStream 类有与FileInputStream类相同的参数构造方法,创建一个FileOutputStream 对象时,可以指定不存在的文件名,但此文件不能是一个已被其他程序打开的文件。下面的实例就是使用 FileInputStream 类与FileOutputStream类实现文件的读取与写入功能的。
例:
package 十五;
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("D:\\word.txt");
//输出字节流
FileOutputStream out = new FileOutputStream(file);
byte[] by = "hello world".getBytes(); //将字符串类型转换为byte类型
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();
}
}
15.3.2 FileReader 和 FileWriter 类
使用FileOutputStream类向文件中写入数据与使用FileInputStream类从文件中将内容读出来,都存在一点不足,即这两个类都只提供了对字节或字节数组的读取方法。由于汉字在文件中占用两个字节,如果使用字节流,读取不好可能会出现乱码现象, 此时采用字符流FileReader类或FileWriter类即可避免这种现象。
FileReader 类和 FileWriter类对应了 FileInputSt ream 类和 FileOutputStream类。FileReader类顺序地读取文件,只要不关闭流,每次调用read()方法就顺月序地读取源中其余的内容,直到源的末尾或流被关闭。
例:
package 十五;
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 {
File file = new File("D:\\word.txt");
//输出字符流
FileWriter writer = new FileWriter(file);
char[] ch = new char[] {'h','e','l','l','o'}; //将字符串类型转换为byte类型
writer.write(ch); //写入
BufferedWriter bw = new BufferedWriter(writer);
bw.write("春晓");
bw.newLine();
bw.write("春眠不觉晓,");
bw.write("处处闻啼鸟。");
bw.newLine();
bw.write("夜来风雨声,");
bw.write("花落知多少。");
bw.close();
writer.close();
//输入字符流
FileReader reader = new FileReader(file);
char[] ch1 = new char[1024]; //传入长度
int len = reader.read(ch1);
System.out.println(new String(ch1,0,len)); //起始位置,与结束位置
reader.close();
}
}
15.4 带缓冲的输入/输出流
15.4.2 BufferedReader 与 BufferedWriter 类
BufferedReader类与 BufferedWriter 类分另继承 Reader类与Writer类。这两个类同样具有内部缓存机制,并能够以行为单位进行输入/输出。
根据 BufferedReader类的特点,可以总结出如图 15.8所示的带缓存的字符数据读取文件的过程。
BufferedReader类常用的方法如下:
read()方法: 读取单个字符。
readLine()方法: 读取一个文本行,并将其返回为字符串。若无数据可读,则返回null。
BufferedWriter类中的方法都返回void。常常用的方法如下:
write(String s, int off, int len)方法: 写入字符串的某一部分。
flush(方法: 刷新该流的缓存。
newLine()方法: 写入一个行分隔符。
在使用BufferedWriter类的Write()方法时数据并没有立刻被写入输出流,而是首先进入缓存区中。如果想立刻将缓存区中的数据写入输出流, 定要调用 flush()方法。
例:
package 十五;
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) throws IOException {
File file = new File("D: word.txt"); // 创建文件对象
FileWriter fw = new FileWriter(file); //文件字符输出流
BufferedWriter bw = new BufferedWriter(fw); // 换成输出流
bw.write("门前大桥下 游过一群鸭"); //写入字符串
bw.newLine(); //写入一个换行符
bw.write("快来快来数一数 二四六七八"); // 写入字符串
bw.newLine(); //写入一个换行符
bw.write("咕嘎咕嘎 真呀真多鸭"); //写入字符串
bw.newLine(); //写入一个换行符
bw.write("数不清到底多少鸭"); //写入字符串
bw.close(); //关闭缓冲输出流
fw.close(); //关闭文件字符输出流
FileReader fr = new FileReader(file); //文件字符输入流
BufferedReader br = new BufferedReader(fr); // 缓冲输入流
String s = br.readLine( );
System.out.println("第一行数据:" + s);
System.out.println("第二行数据:" + br.readLine());
System.out.println("第三行数据:" + br.readLine());
System.out.println("第四行数据:" + br.readLine());
br.close(); //关闭缓冲输入流
fr.close(); //关闭文件字符输入流
}
}
15.5 数据输入/输出流
数据输入/输出流(DataInputStream类与DataOutputStream类)允许应用程序以与机器无关的方式从底层输入流中读取基本Jaya数据类型。也就是说,当读取一个数据时,不必再关心这个数值应当是哪种字节。DataInputStream类与 DataOutputStream类的构造方法如下。
☑ DataInputStream(InputStream in):使用指定的基础InputStream对象创建DataInputStream对象。
☑DataOutputStream(OutputStream out):创建一个新的数据输出流,将数据写入指定基础输出流。
DataOutputStream 类提供了将字符串、double 数据、int数据、boolean数据写入文件的方法。其中,将字符串写入文件的方法有3种,分别是writeBytes(String s)、writeChars(String s)、writeUTF(String s)。由于Java中的字符是Unicode编码,是双字节的,writeBytes()方法只是将字符串中的每一个字符的低字节内容写入目标设备中;而writeChars()方法将字符串中的每一个字符的两个字节的内容都写到目标设备中; writeUTF()方法将字符串按照UTF编码后的字节长度写入目标设备,然后才是每一个字节的UTF编码。
DataInputStream 类只提供了一个readUTF()方法返回字符串。这是因为要在一个连续的字节流读取一个字符串,如果没有特殊的标记作为一个字符串的结尾,并且不知道这个字符串的长度,就无法知道读取到什么位置才是这个字符串的结束。DataOutputStream类中只有writeUTF()方法向目标设备中写入字符串的长度,所以也能准确地读回写入字符串。
例:
package 十五;
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 DataStreamDemo {
public static void main(String[] args) throws IOException {
File file = new File("D:\\word.txt");
FileOutputStream fos = new FileOutputStream(file);
DataOutputStream dos = new DataOutputStream(fos);
dos.writeBoolean(false);
dos.writeUTF("今天星期三");
dos.writeDouble(13.25);
dos.writeInt(9);
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());
System.out.println(dis.readInt());
dis .close();
fis.close();
}
}