IO流

IO流

设备之间进行数据传输的过程称为流。

流:流本身也是一个具体的对象,它可以被看成是和特定设备连接的管道。

流的分类

根据数据的流向可以分为:==输入流和输出流==

根据流返回或接受数据类型可以分为:==字节流和字符路==

注意:

字符流内部处理的依旧是字节数据,他只是对外提供了字符数据的调用接口。

==节点流和处理流==

字节输出流:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
* 输出流
*/

public class Output {
public static void main(String[] args) throws IOException {
//1.创建一个FileOutputStream对象
FileOutputStream fos = new FileOutputStream("a.txt",true);
//2.调用方法write,将数据写入
fos.write(97);
fos.write(98);
//3.使用结束,清空内存
fos.close();
}
}
输出流特点:
  1. 输出流写入数据,文件如果不存在则会自动创建文件。
  2. 如果希望每次在写的数据后追加内容,则可以设置FileOutputStream的构造方法的第二个参数为true(默认是false)。

字节输入流:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class Input {
public static void main(String[] args) throws IOException {
//1.创建输入流对象
FileInputStream fis = new FileInputStream("a.txt");
// //2.调用read()方法读出数据
// int i1 = fis.read();
// System.out.println(i1);
// int i2 = fis.read();
// System.out.println(i2);
// int i3 = fis.read();
// System.out.println(i3);
// //如果读取完毕,-1表示结尾
// int i4 = fis.read();
// System.out.println(i4);

//使用循环读取
int i; //i 记录每次循环读取的数据
while((i = fis.read()) != -1){
System.out.println(i);
}

//3.关闭流
fis.close();
}
}
注意:每次使用结束必须关闭流。
  • 输入流 读取的文件必须存在。

可使用read()和read(byte[] b)等方法读取文件中的数据,如果到达文件末尾, 会返回-1;

流对象用完之后,为了保证能够关闭流,可使用finally子句。

copy练习:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyDemo {
public static void main(String[] args) throws IOException {
//创建字节输入流对象
FileInputStream fis = new FileInputStream("C:/Users/renhongchang/Desktop/c/aa.txt");
//创建输出流对象 拷贝的目标路径一定要给出文件名字
FileOutputStream fos = new FileOutputStream("C:\\Users\\renhongchang\\Desktop\\c\\a\\ccc.txt");

//获取拷贝之前的时间
long star = System.currentTimeMillis();

//调用read()方法,读取文件
int i;
while((i = fis.read()) != -1){
fos.write(i);
}
//获取拷贝结束时间
long end = System.currentTimeMillis();

//计算拷贝时间
int time = (int)(end - star);
System.out.println("拷贝使用的时间是:" + time + "mm");

//关闭数据流
fis.close();
fos.close();
}
}

缓冲流类:

除了定义字节缓冲区来提高文件拷贝效率外,IO中还提供了两个字节缓冲流来提高文件拷贝效率:

==BufferedInputStream==和==BufferedOutputStream==。

==BufferedInputStream和BufferedOutputStream常用来对InputStream和OutputStream进行缓冲处理==

一旦使用缓冲流,如果没有关闭流,数据保存在缓冲区中,并不及时关闭流。

缓冲流执行写操作时:
  1. 缓冲区满
  2. 刷新缓冲区
  3. 流关闭
使用缓冲流copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.io.*;

public class BufferCopy {
public static void main(String[] args) throws IOException {
//创建字节输入流对象
FileInputStream fis = new FileInputStream("C:\\Users\\renhongchang\\Desktop\\c\\aa.txt");
//创建输入流缓冲流对象
BufferedInputStream bis = new BufferedInputStream(fis);
//创建输出流缓冲流对象
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("C:\\Users\\renhongchang\\Desktop\\c\\a\\ddd.txt"));
try{

//获取拷贝之前的时间
long star = System.currentTimeMillis();

//调用read()方法,读取文件
int i;
while((i = bis.read()) != -1){
bos.write(i);
}
//获取拷贝结束时间
long end = System.currentTimeMillis();

//计算拷贝时间
int time = (int)(end - star);
System.out.println("拷贝使用的时间是:" + time + "mm");
}catch(IOException e){
e.printStackTrace();
}finally {
//为了确保流能够关闭,可以将close()写到finally子句中
//关闭数据流
bis.close();
fis.close();
bos.close();
}
}
}

字符流:

==抽象类Reader和Writer==是字符输入/输出流的根类

  • Reader中定义的方法:

int read()

int read(char[] cbuf)

int read(char[] cbuf, int off, int len)

void close()

  • Writer中定义的方法:

void flush()

void write(char[] cbuf)

void write(char[] cbuf, int off, int len)

void write(int c)

void write(String str) void close()

Writer如果不使用 flush() 方法或者 close() 方法数据不会写入磁盘。

flush() 和 close() 的区别:

  • flush() 是刷新,将数据流中的数据刷出,写入磁盘,使用之后流 还可以继续调用;而close() 是关闭流,使用之后,流不可以再继续调用。
  • close() 方法 主要功能是关闭流,释放资源,同时具有刷新流的效果;flush() 方法只能刷新流。
使用字符流写出数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriteDemo {
public static void main(String[] args) throws IOException {
//创建字符输出流
Writer fw = new FileWriter("b.txt");
//输出数据
try {
fw.write(new char[]{'你','好','世','界'});
} catch (IOException e) {
e.printStackTrace();
}finally {
//刷新流
fw.flush();
//关闭流
fw.close();
}
}
}
使用字符流读入数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class ReadDemo {
public static void main(String[] args) throws IOException {
//创建字符输入流
Reader fr = new FileReader("b.txt");

//定义缓冲数组
char[] context = new char[128];

int i;
//读出数据
try{
while((i = fr.read(context)) != -1){
System.out.print(context);
}
}catch(Exception e){
e.printStackTrace();
}finally {
fr.close();
}

}
}

按照某种规则将数据存储在计算机中叫编码,反之,用某种规则将计算机中的二进制解析出来叫做解码。

转换流:OutputStreamWriter类 和 InputStreamReader

在JDK中,提供了两个类用于实现将字节流转换为字符流,它们分别是InputStreamReader和OutputStreamWriter。

InputStreamReader是==Reader的子类==,它可以==将一个字节输入流转换成字符输入流==,方便直接读取字符。

OutputStreamWriter是==Writer的子类==,它可以==将一个字节输出流转换成字符输出流==,方便直接写入字符。

使用转换流copy不同编码集的文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private static void test01()throws IOException {
//创建输入转换流 指定字符集:读取的源文件的编码集
InputStreamReader inputStreamReader = new InputStreamReader(
new FileInputStream("C:\\Users\\renhongchang\\Desktop\\c\\b.txt"),"GBK");
//创建输出转换流 指定字符集
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(
new FileOutputStream("C:\\Users\\renhongchang\\Desktop\\c\\a\\eee.txt"),"GBK"
);

try{
int i;
while((i = inputStreamReader.read()) != -1){
outputStreamWriter.write(i);
}
}catch(Exception e){
e.printStackTrace();
}finally{
//关闭输入流
inputStreamReader.close();
//刷新输出流
outputStreamWriter.flush();
//关闭输出流
outputStreamWriter.close();
}

}

注意:使用输入流转换流需要注意,设置的字符集需要和源文件的字符集相同,否则会乱码,写入的时候一般不存在乱码的问题。

序列化:

==将内存中的对象通过某种格式排列之后记录下来== ,这个过程叫对象的 序列化 (Serialization-也叫串行化) 。

练习:

学生实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.io.Serializable;

/**
* 1. 将存有多个自定义对象的集合序列化操作,保存到 list.txt 文件中。
* 2. 反序列化 list.txt ,并遍历集合,打印对象信息。
* 案例分析
* 1. 把若干学生对象 ,保存到集合中。
* 2. 把集合序列化。
* 3. 反序列化读取时,只需要读取一次,转换为集合类型。
* 4. 遍历集合,可以打印所有的学生信息
* */
public class Student implements Serializable {
private String id;
private String name;
private String sex;

//构造方法
public Student(String id, String name, String sex) {
this.id = id;
this.name = name;
this.sex = sex;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

@Override
public String toString() {
return "Student{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
}

实现功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class StudentList{

//将学生对象写入集合中
public static List<Student> getStudentList() {
//创建集合对象
List<Student> studentList = new ArrayList<Student>();
studentList.add(new Student("111","张三","男"));
studentList.add(new Student("222","张4","男"));
studentList.add(new Student("333","张5","男"));
studentList.add(new Student("444","张6","男"));
studentList.add(new Student("555","张7","男"));
return studentList;
}

//序列化
public static void studentList() throws IOException {
//创建ObejectOutputStream对象
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("list.txt"));
//调用writeObject()方法
objectOutputStream.writeObject(getStudentList());
//刷新流
objectOutputStream.flush();
//关闭流
objectOutputStream.close();
}

//反序列化
public static void reStudentList() throws IOException, ClassNotFoundException {
//创建ObjectInputStream对象
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("list.txt"));
//调用readObject()方法
List list = (List) objectInputStream.readObject();
//遍历集合
for (Object obj : list){
System.out.println(obj.toString());
}
}
}

File:

File类常用方法:

createNewFile()在指定位置创建一个空文件,成功就返回true,如果已存在就不创建,然后返回false。
mkdir() 在指定位置创建一个单级文件夹。
mkdirs() 在指定位置创建一个多级文件夹。
renameTo(File dest)如果目标文件与源文件是在同一个路径下,那么renameTo的作用是重命名, 如果目标文件与源文件不是在同一个路径下,那么renameTo的作用就是剪切,而且还不能操作文件夹。

删除:
delete() 删除文件或者一个空文件夹,不能删除非空文件夹,马上删除文件,返回一个布尔值。
deleteOnExit() jvm退出时删除文件或者文件夹,用于删除临时文件,无返回值。
判断:
exists() 文件或文件夹是否存在。
isFile() 是否是一个文件,如果不存在,则始终为false。
isDirectory() 是否是一个目录,如果不存在,则始终为false。
isHidden() 是否是一个隐藏的文件或是否是隐藏的目录。
isAbsolute() 测试此抽象路径名是否为绝对路径名。
获取:
getName() 获取文件或文件夹的名称,不包含上级路径。
getAbsolutePath()获取文件的绝对路径,与文件是否存在没关系
length() 获取文件的大小(字节数),如果文件不存在则返回0L,如果是文件夹也返回0L。
getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回null。
lastModified()获取最后一次被修改的时间。

文件夹相关:
static File[] listRoots()列出所有的根目录(Window中就是所有系统的盘符)
list() 返回目录下的文件或者目录名,包含隐藏文件。对于文件这样操作会返回null。
listFiles() 返回目录下的文件或者目录对象(File类实例),包含隐藏文件。对于文件这样操作会返回null。
list(FilenameFilter filter)返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。
listFiles(FilenameFilter filter)返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;


public class FileMethod {

public static void main(String[] args) throws IOException {
//创建方法
/* @SuppressWarnings("unused")
File file = new File("F:\\a.txt");
//System.out.println("创建成功了吗?"+file.createNewFile());
//System.out.println("单级文件夹创建成功了吗?"+file.mkdir());
//System.out.println("多级文件夹创建成功了吗?"+file.mkdirs());
//File dest = new File("F:\\电影\\c.txt");
//System.out.println("重命名成功了吗?"+file.renameTo(dest));
*/

/* //删除方法
File file = new File("F:\\电影");
System.out.println("删除成功了吗?"+file.delete());
file.deleteOnExit();
*/

//判断方法
/* File file = new File("F:\\a.txt");
System.out.println("文件或者文件夹存在吗?"+file.exists());
System.out.println("是一个文件吗?"+file.isFile());
System.out.println("是一个文件夹吗?"+file.isDirectory());
System.out.println("是隐藏文件吗?"+file.isHidden());
System.out.println("此路径是绝对路径名?"+file.isAbsolute());
*/

//获取方法
/*
File file = new File("f:\\a.txt");
System.out.println("文件或者文件夹得名称是:"+file.getName());
System.out.println("绝对路径是:"+file.getPath());
System.out.println("绝对路径是:"+file.getAbsolutePath());
System.out.println("文件大小是(以字节为单位):"+file.length());
System.out.println("父路径是"+file.getParent());
//使用日期类与日期格式化类进行获取规定的时间
long lastmodified= file.lastModified();
Date data = new Date(lastmodified);
SimpleDateFormat simpledataformat = new SimpleDateFormat("YY年MM月DD日 HH:mm:ss");
System.out.println("最后一次修改的时间是:"+simpledataformat.format(data));
*/

//文件或者文件夹的方法

File[] file = File.listRoots();
System.out.println("所有的盘符是:");
for(File item : file){
System.out.println("\t"+item);
}
File filename =new File("F:\\Java workspace\\Java");
String[] name = filename.list();
System.out.println("指定文件夹下的文件或者文件夹有:");
for(String item : name){
System.out.println("\t"+item);
}
File[] f = filename.listFiles();
System.out.println("获得该路径下的文件或文件夹是:");
for(File item : f){
System.out.println("\t"+item.getName());
}

}
}
目录遍历:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.io.File;

public class TraverseOfFile {
public static void main(String[] args) {
//创建File对象
File file = new File("C:\\Users\\renhongchang\\Desktop\\c");

//遍历所有目录下所有文件
// test01(file);

//删除文件夹
test02(file);
}



private static void test01(File file) {

//创建File数组用于存储listFile()返回的内容
File[] files = file.listFiles();

//遍历数组
for (File fil : files){
//如果是目录,则递归调用有方法,返回目录里的内容
if (fil.isDirectory())
test01(fil);
//如果是文件则,直接打印
if (fil.isFile())
System.out.println(fil);
}
}

private static void test02(File file) {
//创建File数组用于存储listFile()返回的内容
File[] files = file.listFiles();

//遍历数组
for (File fil : files){
//如果是目录,则递归调用有方法,返回目录里的内容
if (fil.isDirectory())
test02(fil);
//如果是文件则,直接删除
if (fil.isFile())
fil.delete();
}
file.delete();
}
}