IO分类以及InputStream

流的分类

  • 按照操作数据单位不同分为:字节流(8bit)操作二进制文件不会造成损失,字符流(效率比较高,操作文本文件)
  • 按数据流的流向不同分为:输入流,输出流
  • 按流的角色的不同分为节点流,处理流/包装流
抽象基类 字节流 字符流
输入流 InputStream(抽象类) Reader
输出流 OutputStream(抽象类) Write

字节输入/输出流

image-20220703170702227

FileInputStream

image-20220703170650957

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
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
Test test=new Test();
test.readFile1();
}
public void readFile1() throws IOException {
String filePath="D:\\文件下载\\test.txt";
FileInputStream fileInputStream=new FileInputStream(filePath);
int readDate;
try {
//从该输入读取一个字节的数据,如果没有输入可用,此方法将阻止,返回-1表示读取完毕
while ((readDate=fileInputStream.read())!=-1){
System.out.print((char)readDate);
}
}
catch (IOException ioException){
ioException.printStackTrace();
System.out.println("文件读取失败");
//最终一定要关闭这个流文件,释放资源
}finally {

fileInputStream.close();
}
System.out.println("文件读取成功");
}


}

image-20220703170526909

虽然文件读取成功,但是这里的中文是以乱码的方式出现,在utf-8中,一个中文由三个字节组成,但是这里是一次性读取一个字节,会出现乱码,而且这样的方式读取比较缓慢。

所以我们可以使用read(byte[] b)的方法来提高效率,下面这一段代码中,我们设置成3个为一组进行读取,可以正常读取出相应的值。而且效率比较高。

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
import java.io.FileInputStream;
import java.io.IOException;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
Test test=new Test();
test.readFile1();
}
public void readFile1() throws IOException {
String filePath="D:\\文件下载\\test.txt";
FileInputStream fileInputStream=new FileInputStream(filePath);
byte []buff=new byte[3];
int readLine;
try {
//从该输入读取一个字节的数据,如果没有输入可用,此方法将阻止,返回-1表示读取完毕
//如果读取正常,则返回实际读取的个数
while ((readLine=fileInputStream.read(buff))!=-1){
System.out.println(readLine);
System.out.print(new String(buff,0,readLine));
}
} finally {

fileInputStream.close();
}
System.out.println("文件读取成功");
}


}

image-20220703170633908

FileOutStream

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.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
* @author zss
*/
public class Test {
public static void main(String[] args) throws IOException {
Test test=new Test();
test.writeFile();
}
/**将数据写入到文件中,如果文件不存在,则创建该文件*/
public void writeFile() throws IOException {
String filePath="D:\\文件下载\\test1.txt";
FileOutputStream fileOutputStream=null;
try {
fileOutputStream=new FileOutputStream(filePath);
//写入一个字节
//fileOutputStream.write('h');
//写入多个字节
String str="hello world";
//将字符串数组转成字符
//fileOutputStream.write(str.getBytes(StandardCharsets.UTF_8));
//传入一个数组
fileOutputStream.write(str.getBytes(),0,str.length());
}
catch (IOException ioException){
System.out.println("文件写出失败");
}finally {
assert fileOutputStream != null;
fileOutputStream.close();}
}
}

只是这种方法会掩盖原来的文章,如果不想要掩盖原来的文章,在构造器中,添加一个true

1
fileOutputStream=new FileOutputStream(filePath,true);

练习

将图片拷贝到另外一个文件夹

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
import java.io.*;

/**
* @author zss
*/
public class Excesice {
static String picture;

public static void main(String[] args) throws IOException {
Excesice excesice = new Excesice();
excesice.copy();
}

public void copy() throws IOException {
byte[] buff = new byte[1024];
String pictureAddress = "D:\\壁纸\\彩云.png";
String pictureDenAddress="D:\\文件下载\\彩云.png";
FileInputStream fileInputStream = new FileInputStream(pictureAddress);
FileOutputStream fileOutputStream=new FileOutputStream(pictureDenAddress);
int pictureDate;
try {
while ((pictureDate = fileInputStream.read(buff)) != -1) {
/**必须使用此方法,而不可以使用fileOutputStream.write(str.getBytes(),0,str.length());,因为不知道是好结束,否则文件会发生错误*/
fileOutputStream.write(buff);
}
} catch (IOException ioException) {
System.out.println("文件访问失败");
} finally {
fileInputStream.close();
fileOutputStream.close();
}
}
}