1) Java流操作有关的类或接口:
Java流类图结构:
1. InputStream/OutputStream
字节流的抽象类。
2. Reader/Writer
字符流的抽象类。
3. FileInputStream/FileOutputStream
节点流:以字节为单位直接操作“文件”。
4. ByteArrayInputStream/ByteArrayOutputStream
节点流:以字节为单位直接操作“字节数组对象”。
5. ObjectInputStream/ObjectOutputStream
处理流:以字节为单位直接操作“对象”。
6. DataInputStream/DataOutputStream
处理流:以字节为单位直接操作“基本数据类型与字符串类型”。
7. FileReader/FileWriter
节点流:以字符为单位直接操作“文本文件”(注意:只能读写文本文件)。
8. BufferedReader/BufferedWriter
处理流:将Reader/Writer对象进行包装,增加缓存功能,提高读写效率。
9. BufferedInputStream/BufferedOutputStream
处理流:将InputStream/OutputStream对象进行包装,增加缓存功能,提高 读写效率。
10. InputStreamReader/OutputStreamWriter
处理流:将字节流对象转化成字符流对象。
11. PrintStream
处理流:将OutputStream进行包装,可以方便地输出字符,更加灵活。
2)流的概念和作用
流是一个抽象、动态的概念,是一连串连续动态的数据集合。
对于输入流而言,数据源就像水箱,流(stream)就像水管中流动着的水流,程序就是我们最终的用户。我们通过流(A Stream)将数据源(Source)中的数据(information)输送到程序(Program)中。
对于输出流而言,目标数据源就是目的地(dest),我们通过流(A Stream)将程序(Program)中的数据(information)输送到目的数据源(dest)中。
输入/输出流的划分是相对程序而言的,并不是相对数据源。
IO流的分类
1.按流的方向分类:
1. 输入流:数据流向是数据源到程序(以InputStream、Reader结尾的流)。
2. 输出流:数据流向是程序到目的地(以OutPutStream、Writer结尾的流)。
2.按处理的数据单元分类:
1. 字节流:以字节为单位获取数据,命名上以Stream结尾的流一般是字节流,如FileInputStream、FileOutputStream。
2. 字符流:以字符为单位获取数据,命名上以Reader/Writer结尾的流一般是字符流,如FileReader、FileWriter。
3.按处理对象不同分类:
1. 节点流:可以直接从数据源或目的地读写数据,如FileInputStream、FileReader、DataInputStream等。
2. 处理流:不直接连接到数据源或目的地,是”处理流的流”。通过对其他流的处理提高程序的性能,如BufferedInputStream、BufferedReader等。处理流也叫包装流。
节点流处于IO操作的第一线,所有操作必须通过它们进行;处理流可以对节点流进行包装,提高性能或提高程序的灵活性
3.File类
File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。
3.1File 类的概述和构造方法:
要想实现IO的操作,就必须知道硬盘上文件的表现形式,而java中就提供了一个File类。
构造方法:
public File(String pathname):根据一个路径得到一个File对象
File(String parent, String child) : 根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(File parent, String child) : 根据 parent 抽象路径名和 child 路径名字符串创建一个新 File 实例。
方式一:File file1 = new File(“e:\\demo\\test.txt”);
方式二:File file2 = new File(“e:\\demo”,”test.txt”);
方式三:File file3 = new File(“e:\\demo”);
File file4 = new File(file3,”test.txt”);
注意:以上三种方式其实效果一样
3.2File 类的创建功能
创建功能: boolean mkdir():创建文件夹,如果存在此文件夹,则不创建,返回结果为false;
boolean createNewFile():创建文件,如果此文件存在,则不创建,返回结果为false;
注意:如果需要在某个文件夹下创建文件,则此文件依赖的文件夹必须存在,否则会出现IO异常,系统找不到指定路径。
如果创建文件或文件夹时忘记写盘符路径,默认在项目路径下。
boolean mkdirs():用于创建文件夹,如果父文件夹不存在时,其可以自动创建父文件夹,即用于创建多级文件的。
例如:
File file = new File(“e:\\test\\test.txt”);
System.out.println(“mkdir:”+file.mkdirs());
以上两行代码执行正确。
3.3File类的删除功能:
public boolean delete();此方法可以删除文件或文件夹。
注意:java中的删除不走回收站;
被删除文件夹中不能包含子文件或文件夹
3.4File类的判断功能:
public boolean isDirectory();判断是否是目录
public boolean isFile();判断是否是文件
public boolean exists();判断是否存在
public boolean canWrite();判断是否可写
public boolean canRead();判断是否可读
public boolean isHidden();判断是否隐藏
3.5File类的重命名功能:
public boolean renameTo(File file);
如果路径名相同,改名,如果路径名不同,相当于改名并剪切
注意:路径以盘符开始:绝对路径
路径不以盘符开始:相对路径
需求:使用程序修改某个文件的名称。
File file = new File(“xxx.txt”);
File newFile = new File(“test.txt”);
System.out.println(“renameTo:”+ file.renameTo(newFile));
File file2 = new File(“xxx.txt”);
File newFile2 = new File(“e:\\test.txt”);
System.out.println(“renameTo:”+ file2.renameTo(newFile2));
3.6File 类的基本获取功能
获取功能:
public String getAbsolutePath();获取绝对路径
public String getPath();获取相对路径
public String getName();获取名称
public long length();获取长度,字节数
public long lastModified();获取最后一次的修改时间,毫秒值
3.7File类的高级获取功能:
public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
public file[] listFiles(): 获取指定目录下的所有文件或者文件夹的File数组
4)Java IO流对象
1.输入字节流InputStreamio 中输入字节流的继承图可见上图,可以看出:InputStream 是所有的输入字节流的父类,它是一个抽象类。
ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍。
ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
为了保证出现异常后流的正常关闭,通常要将流的关闭语句要放到finally语句块中,并且要判断流是不是null。
5)输出字节流OutputStream
http://2.IO 中输出字节流的继承图可见上图,可以看出:OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,
ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
3.字节流的输入与输出的对应
3.1.字节流的输入流(InputStream)
构造方法:
FileInputStream(File file)
FileInputStream(String name)
成员方法:
int read()从该输入流读取一个字节的数据。
int read(byte[]b)从该输入流读取最多b.length个字节的数据到一个字节数组。
int read(byte[]b,intoff,intlen)从该输入流读取最多len个字节的数据到字节数组。
//需求:使用字节输入流将文件中的内容读取并在控制台输出 //目标文件对象 File file = new File("d:\\test.txt");
// //创建输入流对象 FileInputStream fis=new FileInputStream(file);
FileInputStream fis =new FileInputStream("d:\\test.txt"); byte [] b =new byte[(int)file.length()];
//读取内容 System.out.println( fis.read(b));
for (int i=0;i
System.out.print((char)b[i]);
}
//释放资源 fis.close();
}
3.2字节流的输出流(OutputStream)
FileOutputStream 的构造方法
public FileOutputSteam(File file);
public FileOutputSteam(String name);
public FileOutputSteam(String name,boolean append);
成员方法:
void write(byte[] b) 将 b.length字节从指定的字节数组写入此输出流。
void write(byte[] b, int off, int len) 从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
void write(int b) 将指定的字节写入此输出流。
void close() 关闭此输出流并释放与此流相关联的任何系统资源。
//指定输出内容的文件
// File file = new File("d:\\test.txt");
//创建输出流的对象
// OutputStream os=new FileOutputStream(file);
/**
* A;创建File对象
* B:新建文件
* C:写出内容
*/
OutputStream os =new FileOutputStream("d:\\test.txt");
//准备输出的内容
String str = "Hello io";
//将输出内容按字节方式进行输出
// os.write(str.getBytes());
os.write(str.getBytes(),0,4);//0表示起始
os.close();
6.字符输入流Reader在上面的继承关系图中可以看出:
Reader 是所有的输入字符流的父类,它是一个抽象类。
CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据。
BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象。
FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号。
InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。
基类:Reader 抽象类
子类:InputStreamReder
构造方法:
按系统默认字符集进行文件内容的读取
InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader。
按指定字符集进行文件内容的读取
InputStreamReader(InputStream in, String charsetName) 创建一个使用命名字符集的
File file =new File("d:\\\\test.txt");
//构造InputStream对象
InputStream is = new FileInputStream("d:\\\\test.txt");
//创建字符输入流对象
InputStreamReader isr= new InputStreamReader(is);
//读取内容
// int b = -1;
// while ((b=isr.read())!=-1){
// System.out.print((char)b);
// }
//创建存储的缓冲区
char [] chs = new char [(int)file.length()];
//将文件内容读取到缓冲区chs
isr.read(chs);
for (char c:chs
) {
System.out.print(c);
}
//释放资源
isr.close();
is.close();
字符输入流的便捷类:FileReder 注意:不能指定特定编码格式,其按照系统默认的编码格式进行文件读取
构造方法:
FileReader(File file) 创建一个新的 FileReader ,给出 File读取。
FileReader(String fileName) 创建一个新的 FileReader ,给定要读取的文件的名称。
FileReader fr = new FileReader("d:\\test.txt");
int b =-1;
while (( b=fr.read() )!=-1){
System.out.print((char)b);
}
fr.close();
7.字符输出流Writer
在上面的关系图中可以看出:Writer 是所有的输出字符流的父类,它是一个抽象类。
CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据,
BufferedWriter 是一个装饰器为Writer 提供缓冲功能。
PrintWriter 和PrintStream 极其类似,功能和使用也非常相似。
OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。
字符输出流:Writer抽象类
子类:OutputStreamWriter
构造方法
OutputStreamWriter(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter。
成员方法:
void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write(int c) 写一个字符
void write(String str, int off, int len) 写一个字符串的一部分
//创建字符输出流对象,并指定转储文件
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\\\pet.template"),"utf-8");
String info = "您好,我的名字是{name},我是一只{type},我的主人{master}";
//写出操作
osw.write(info);
osw.close();
FileWriter:字符输出流的便捷类,也是OutputStreamWriter的子类
构造方法:
FileWriter(File file) 给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append) 给一个File对象构造一个FileWriter对象。
FileWriter(String fileName) 构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append) 构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。
成员方法:
public void flush();
public void close();
void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write(int c) 写一个字符
void write(String str, int off, int len) 写一个字符串的一部分
9.字符流与字节流转换
转换流的特点:其是字符流和字节流之间的桥梁
可对读取到的字节数据经过指定编码转换成字符
可对读取到的字符数据经过指定编码转换成字节
何时使用转换流?当字节和字符之间有转换动作时;
流操作的数据需要编码或解码时。
具体的对象体现:InputStreamReader:字节到字符的桥梁
OutputStreamWriter:字符到字节的桥梁
这两个流对象是字符体系中的成员,它们有转换作用,本身又是字符流,所以在构造的时候需要传入字节流对象进来。
10.RandomAccessFile类
该对象并不是流体系中的一员,其封装了字节流,同时还封装了一个缓冲区(字符数组),通过内部的指针来操作字符数组中的数据。 该对象特点:该对象只能操作文件,所以构造函数接收两种类型的参数:a.字符串文件路径;b.File对象。
该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r,rw)
注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。 可以用于多线程下载或多个线程同时写数据到文件。
经典代码:
1.使用流读取文件内容(经典代码,一定要掌握)
import java.io.*;
public class TestIO2 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("d:/a.txt"); // 内容是:abc
StringBuilder sb = new StringBuilder();
int temp = 0;
//当temp等于-1时,表示已经到了文件结尾,停止读取
while ((temp = fis.read()) != -1) {
sb.append((char) temp);
}
System.out.println(sb);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
//这种写法,保证了即使遇到异常情况,也会关闭流对象。
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
为了保证出现异常后流的正常关闭,通常要将流的关闭语句要放到finally语句块中,并且要判断流是不是null。
2.利用文件流实现文件的复制
package d804_2;
import java.io.*;
public class IoDemo2 {
public static void main(String[] args) {
copyFile("d:\\p.txt","d:\\u2.txt");
}
static void copyFile(String src, String dec) {
FileInputStream fis = null;
FileOutputStream fos = null;
//为了提高效率,设置缓存数组!(读取的字节数据会暂存放到该字节数组)
byte[] buffer = new byte[1024];
int temp = 0;
try {
fis = new FileInputStream(src);
fos = new FileOutputStream(dec);
//边读边写
//temp指的是本次读取的真实长度,temp等于-1时表示读取结束
while ((temp = fis.read(buffer)) != -1) {
/*将缓存数组中的数据写入文件中,注意:写入的是读取的真实长度;
*如果使用fos.write(buffer)方法,那么写入的长度将会是1024,即缓存
*数组的长度*/
fos.write(buffer,0,temp);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}