在Java中File类对象,可以用来操作文件,但是不能处理文件内容
为了处理文件内容,进行 I/O 操作,必须使用流的操作模式来完成
I/O流体系结构图:
I/0流分类:
1)根据处理的数据类型分为:字节流和字符流
2)根据处理的数据流向分为:输入流和输出流
字节流与字符流的区别:
字节流和字符流操作的本质区别只有一个:字节流是原生的操作,而字符流是经过处理后的操作。
在进行网络数据传输、磁盘数据保存所支持的数据类型都是:字节 ;而所有磁盘中的数据,必须先读到内存后才能进行操作,此时内存会帮助我们把字节变为字符。
不管使用的是字节流还是字符流,其基本的操作流程是一样的:
- 根据文件路径创建File类对象 ;
- 根据字节流或字符流的子类实例化父类对象 ;
- 进行数据的读取或写入操作
- 关闭流(close())
字节流和字符流的具体区别总结如下:
- 字节流处理单元为1个字节,操作字节和字节数组;字符流处理单元为2个字节的Unicode字符,操作字符、字符数组、字符串等。字符流就是Java虚拟机把字节流转换为2个字节为单元的Unicode字符。
- 字节流在操作时不会用到缓冲区,是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区来操作文件。
- 字符流适合处理中文,字节流适合处理一切数据类型(对中文支持不好)。
那么根据上面的分类,就可以得到以下四种基本I/O流
- 字节输入流 OutputStream
- 字节输出流 InputStream
- 字符输入流 Reader
- 字符输出流 Writer
接下来,让我们来依次了解这四种基本I/O流的使用方法
一、字节输入流 OutputStream
如果想通过程序输出内容到文件,则可以使用java.io.OutputStream
OutputStream类主要方法:
1. 将给定的字节数组内容全部输出:public void write(byte b[]) throws IOException
2. 将部分字节数组内容输出:public void write(byte b[], int off, int len) throws IOException
3. 输出单个字节:public abstract void write(int b) throws IOException
范例:实现文件的内容输出
import java.io.*;
public class Test1 {
public static void main(String[] args) {
File file =new File("C:"+File.separator+"Users"+File.separator+"10320"+
File.separator+"ideaProjects"+File.separator+"file.txt");
if(!file.getParentFile().exists()){//判断父目录存在
file.getParentFile().mkdirs();//创建多级父目录
}
// OutputStream是一个抽象类,所以需要通过子类进行实例化,此时只能操作File类
try {
OutputStream output=new FileOutputStream(file);
//此构造方法会不断覆盖内容
//如果变为以下构造方法,即可实现追加内容
// OutputStream output=new FileOutputStream(file,true);
String message="hello word";
output.write(message.getBytes());//将内容变为字节数组
output.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:由于OutputStream是一个抽象类,不能实例化对象,所以要想为父类实例化,就必须要使用子类(子类实现抽象父类的方法,但是自身并不是抽象类,所以可以实例化对象)。由于方法名称都由父类声明好了,所以我们在此处只需要关系子类的构造方法。如果要进行文件的操作,可以使用FileOutputStream类来处理。
FileOutputStream类的构造方法如下:
1. 接收File类(覆盖):public FileOutputStream(File file) throws FileNotFoundException
2. 接收File类(追加):public FileOutputStream(File file, boolean append)
二、字节输出流 InputStream
使用InputStream类,可以在程序中读取文件内容
InputStream类主要方法:
1. public int read(byte b[]) throws IOException
读取数据到字节数组中,返回数据的读取个数。如果此时开辟的字节数组大小大于读取的数据大小,则返
回的就是读取个数;如果要读取的数据大于数组的内容,那么这个时候返回的就是数组长度;如果没有
数据了还在读,则返回-12. public int read(byte b[], int off,int len) throws IOException
读取部分数据到字节数组中,每次只读取传递数组的部分内容,如果读取满了则返回长度(len),如果没有
读取满则返回读取的数据个数,如果读取到最后没有数据了返回-13. public abstract int read() throwsIOException
读取单个字节,每次读取一个字节的内容,直到没有数据了返回-1
范例:实现文件信息的读取
public class Test1 {
public static void main(String[] args) {
//定义文件路径
File file = new File("C:" + File.separator + "Users" + File.separator + "10320" + File.separator + "ideaProjects" + File.separator + "file.txt");
if(file.exists()){
try {
// InputStream类是抽象类,必须利用其子类FileInputStream实例化对象,此时只能处理File类
InputStream input=new FileInputStream(file);
byte[] data =new byte[1024];//每次可以读取的最大数量
int len=input.read(data);//此时的数据读取到了数组当中
String result = new String(data,0,len) ; // 将字节数组转为String
System.out.println("读取内容【"+result+"】") ;
input.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三、字符输入流 Reader
Reader是字符输入流的处理类,可以通过程序实现读取文件内容
在Reader类中没有方法可以直接读取字符串类型,这个时候只能通过字符数组进行读取操作
范例:通过Reader类读取文件内容
public class Test1 {
public static void main(String[] args) {
//定义文件路径
File file = new File("C:" + File.separator + "Users" + File.separator
+ "10320" + File.separator + "ideaProjects" + File.separator + "file.txt");
if(file.exists()){
try {
// Reader类是抽象类,必须利用其子类FileReader实例化对象,此时只能处理File类
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();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
四、字符输出流 Writer
字符流适合于处理中文数据,Writer是字符输出流的处理类,可以通过程序实现向文件写入内容
Writer类主要方法:
public void write(String str) throws IOException
该方法可以直接输出字符串
范例:通过Writer类实现输出
public class Test1 {
public static void main(String[] args) {
//定义文件路径
File file = new File("C:" + File.separator + "Users" + File.separator + "10320" + File.separator + "ideaProjects" + File.separator + "file.txt");
if (!file.getParentFile().exists()) { // 必须保证父目录存在
file.getParentFile().mkdirs() ; // 创建多级父目录
}
String message = "hello world";
try (Writer out = new FileWriter(file)) {
out.write(message);
out.close();
}catch(Exception e){
e.printStackTrace();
}
}
}