(1)、JavaIO流使用了一种装饰器设计模式,将IO流分成底层节点流和上层处理流。
(2)、Flie(java.io.File)类
文件和目录路径名的抽象表示形式,与平台无关
File 能新建、删除、重命名文件和目录,但 File不能访问文件内容本身。
构造方法
public File(String pathname):如果pathname是相对路径,则默认的当前路径在系统属性user.dir(用户根目录)中存储。
public File(String parent,String child):以parent为父路径,child为子路径创建File对象。
File的静态属性String separator存储了当前系统的路径分隔符。在UNIX中,此字段为‘/’,在Windows中,为‘\\’
常用方法
getName() 获取文件名
getPath() 获取文件完整路径(用户初始化时输入)
getAbsoluteFile() 返回的是一个File类对象,这个File对象表示是当前File对象的绝对路径名形式
getAbsolutePath() 返回的是一个字符串,这个字符串就是当前File对象的绝对路径名的字符串形式
getParent() 获取上一层文件目录(按用户初始化时输入解析)
renameTo(File newName) 文件更名(+路径)(目录不存在则失败)
文件检测
exists() 文件是否存在(返回boolean)
canWrite() 文件是否可写
canRead() 文件是否可读
isFile() 是否文件
isDirectory() 是否文件夹
获取常规文件信息
lastModified() 最后修改时间配合new Date()使用
length() 文件长度
目录操作相关
mkDir() 执行后,不会建立目录,找不到目录会返回false
mkDirs() 执行后,会建立多层目录
list() 返回String数组,为string类型的【文件名】(包含后缀名)
listFiles() 返回File对象数组,为File对象类型的【完整路径】
文件操作相关
createNewFile() 新建文件,有则失败
delete() 删除文件
(3)、文件过滤器(FilenameFilter==>函数式接口)
public static void main(String[] args) {
File file = new File(".");
String[] list = file.list((dir, name) -> {
System.out.println(dir + ":" + name);
return name.endsWith(".iml") || name.equals("src");
});
for (String s : list) {
System.out.println(s);
}
}
(4)、流分类
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串
按流向分为:输入流,输出流
按流的角色的不同分为:节点流,处理流(处理流作用于节点流之上)
Java的IO流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的
处理流主要功能提现在以下两个方面
以增加缓冲的方式来提高输入输出的效率
处理流可能提供了一系列便捷的方法来一次输入输出大批量的内容
可以嫁接在任何流之上
(5)、InputStream & Reader
InputStream 和 Reader 是所有输入流的基类。
InputStream(典型实现:FileInputStream)
int read()
int read(byte[] b)
int read(byte[] b, int off, int len)
Reader(典型实现:FileReader)
int read()
int read(char [] c)
int read(char [] c, int off, int len)
程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。
public static void main(String[]args) throws Exception{
FileInputStream fis = new FileInputStream("练习.iml");
byte[] b = new byte[1024];
int hasRead = 0;
while ((hasRead = fis.read(b))>0){
System.out.print(new String(b, 0, hasRead));
}
fis.close();
}
(6)、OutputStream & Writer
OutputStream 和 Writer 也非常相似
void write(int b/char c)
void write(byte[] b/char[] cbuf)
void write(byte[] b/char[] buff, int off, int len)
void flush()
void close()
需要先刷新,再关闭此流因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组,即以 String 对象作为参数void write(String str);void write(String str, int off, int len);
(7)、处理流的优势
(8)、流的分类
字符流还可以用字符串作为物理节点。
(9)、转换流
(10)、重点掌握
抽象基类 | 节点流(文件流) | 缓冲流 |
|
InputStream | FileInputStream (int read(byte[] b)) | BufferedInputStream (int read(byte[] b)) | 字节流 |
OutputStream | FileOutputStream (void write(b,0,len)) | BufferedOutputStream (flush()) (void write(b,0,len)) | |
Reader | FileReader (int read(char[] c)) | BufferedReader (readLine()) (int read(char[] c)) | 字符流 |
Writer | FileWriter (void write(c,0,len)) | BufferedWriter (flush()) (void write(c,0,len) void write(String str)) |
字节缓冲流
public static void main(String[] args) throws Exception {
FileInputStream fi = new FileInputStream("练习.iml");
BufferedInputStream bf = new BufferedInputStream(fi);
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("测试.txt"));
byte[] b = new byte[1024];
int such = 0;
while ((such = bf.read(b)) > 0) {
bo.write(b, 0, such);
}
bo.close();
bf.close();
fi.close();
}
字符缓冲流
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader("测试.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("联系.txt"));
char[] ch = new char[1024];
int such = 0;
while ((such = br.read(ch)) > 0) {
bw.write(ch, 0, such);
}
br.close();
bw.close();
}
(11)、转换流
实现字节流与字符流之间的转换
InputStreamReader:输入时,实现字节流到字符流的转换,提高操作的效率(前提是,数据是文本文件)
解码:字节数组->字符串
OutputStreamWriter:输出时,实现字符流到字节流的转换
编码:字符串->字节数组
public static void main(String[] args) throws Exception {
FileInputStream fi = new FileInputStream("联系.txt");
InputStreamReader ir = new InputStreamReader(fi);
FileOutputStream fo = new FileOutputStream("123");
OutputStreamWriter fw = new OutputStreamWriter(fo);
char[] ch = new char[1024];
int such = 0;
while ((such = ir.read(ch)) > 0) {
fw.write(ch, 0, such);
}
fo.close();
fw.close();
ir.close();
fi.close();
}
(12)、标准的输入输出流
System.in:The "standard" input stream:从键盘输入数据
System.out:The "standard" output stream:从显示器输出数据
(13)、输入输出重定向
输出重定向
public static void main(String[]args) throws Exception{
PrintStream ps = new PrintStream(new FileOutputStream("ou"));
System.setOut(ps);
System.out.println("哈哈哈哈!");//输出重定向到文件
}
输入重定向
public static void main(String[]args) throws Exception{
FileInputStream fi = new FileInputStream("123");
System.setIn(fi);
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
System.out.println(sc.next());
}
fi.close();
}
(14)、PrintWriter(处理字符)
该类可用来创建一个文件并向文本文件写入数据
public static void main(String[]args) throws Exception{
PrintWriter pw = new PrintWriter(new FileOutputStream("12313"));
pw.print("1213132132");
pw.close();
}
(15)、数据流(处理基本数据类型、String类、字节数组)
DataInputStream
public static void main(String[] args) throws Exception {
DataInputStream dis = new DataInputStream(new FileInputStream("ouuu"));
String name = null; // 接收名称
float price = 0.0f; // 接收价格
int num = 0; // 接收数量
char temp[] = null; // 接收商品名称
int len = 0; // 保存读取数据的个数
char c = 0; // '\u0000'
for (int i = 0; i < 3; i++) {
temp = new char[200]; // 开辟空间
len = 0;
while ((c = dis.readChar()) != '\t') { // 接收内容
temp[len] = c;
len++; // 读取长度加1
}
name = new String(temp, 0, len); // 将字符数组变为String
price = dis.readFloat(); // 读取价格
dis.readChar(); // 读取\t
num = dis.readInt(); // 读取int
dis.readChar(); // 读取\n
System.out.printf("名称:%s;价格:%5.2f;数量:%d\n", name, price, num);
}
}
DataOutputStream
public static void main(String[] args)throws Exception {
FileOutputStream fo = new FileOutputStream("ouuu");
DataOutputStream dos = new DataOutputStream(fo);
String names[] = {"衬衣","手套","围巾"} ; // 商品名称
float prices[] = {98.3f,30.3f,50.5f} ; // 商品价格
int nums[] = {3,2,1} ; // 商品数量
for(int i=0;i<names.length;i++){ // 循环输出
dos.writeChars(names[i]) ; // 写入字符串
dos.writeChar('\t') ; // 写入分隔符
dos.writeFloat(prices[i]) ; // 写入价格
dos.writeChar('\t') ; // 写入分隔符
dos.writeInt(nums[i]) ; // 写入数量
dos.writeChar('\n') ; // 换行
}
dos.close();
fo.close();
}
(16)、对象流(用来处理对象的)
对象的序列化机制:允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
ObjectInputStream(Object readObject();)
ObjectOutputStream (void writeObject(Object obj))
如何创建流的对象:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("person.txt")));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("person.txt")));
实现序列化机制的对象对应的类的要求:
①要求类要实现Serializable接口
②同样要求类的所有属性也必须实现Serializable接口
③ 要求给类提供一个序列版本号:private static final long serialVersionUID;
④属性声明为static或transient的,不可以实现序列化
static class Student implements Serializable {
String name;
int age;
private static final long serialVersionUID = 151354354313543L;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public static void main(String[]args) throws Exception{
Student stu = new Student("小王",15);
ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream("student"));
obj.writeObject(stu);
obj.close();
ObjectInputStream oi = new ObjectInputStream(new FileInputStream("student"));
Student stu2 = (Student) oi.readObject();
System.out.println(stu2);
}
(17)、随机存取文件流:RandomAccessFile
既可以充当一个输入流,又可以充当一个输出流:public RandomAccessFile(File file, String mode)
支持从文件的开头读取、写入。若输出的文件不存在,直接创建。若存在,则是对原有文件内容的覆盖。
支持任意位置的“插入”。
public static void main(String[]args) throws Exception{
RandomAccessFile ra = new RandomAccessFile("aaa","rw");
ra.write("123".getBytes());
RandomAccessFile ri = new RandomAccessFile("aaa","r");
byte[] b = new byte[1024];
int read = ri.read(b);
System.out.println(new String(b, 0, read));
}