Java--IO详解

字节流

字节流处理原始的二进制数据 I/O。有两个抽象父类

  • InputStream 抽象了应用程序读取数据的方式
  • OutputStream 抽象类应用程序写出数据的方式

输入输出流的基本方法:

1
2
3
4
5
6
read();
read(byte[] buf)
read(byte[] buf,int start,int size)
out.write(int b)
out.write(byte[] buf)
out.write(byte[] buf,int start,int size)

子类:

  • FileInputStream 具体实现了在文件上读取数据
  • FileOutputStream 实现了向文件中写出byte数据的方法
  • DataOutputStream/DataInputStream 对”流”功能的扩展,可以更加方面的读取int,long,字符等类型数据
  • BufferedInputStream/BufferedOutputStream 这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能从应用程序中把输
    入放入文件,相当于将一缸水倒入到另一个缸中:

    FileOutputStream—>write()方法相当于一滴一滴地把水“转移”过去
    DataOutputStream–>writeXxx()方法会方便一些,相当于一瓢一瓢把水“转移”过去
    BufferedOutputStream—>write方法更方便,相当于一飘一瓢先放入桶中,再从桶中倒入到另一个缸中,性能提高了

javaio1

javaio2

一下通过几个例子来看他的具体实现:

向文件中写入字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 字节流
* 向文件中写入字符串
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
OutputStream out =new FileOutputStream(f);
String str="hello";
byte[] b=str.getBytes();
out.write(b);
out.close();
}
}

向文件中写入字符串(一个字节一个字节的写入)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 字节流
* 向文件中一个字节一个字节的写入字符串
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
OutputStream out =new FileOutputStream(f);
String str="hello";
byte[] b=str.getBytes();
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
out.close();
}
}

向文件中添加新内容(同时不覆盖原本的内容)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 字节流
* 向文件中追加新内容:
**/
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
OutputStream out =new FileOutputStream(f,true);
String str="Welcome";
byte[] b=str.getBytes();
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
out.close();
}
}

读取文件的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 字节流
* 读文件内容
**/
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
InputStream in=new FileInputStream(f);
byte[] b=new byte[1024];
in.read(b);
in.close();
System.out.println(new String(b));
}
}

读取文件的内容(固定长度)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 字节流
* 读文件内容
**/
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
InputStream in=new FileInputStream(f);
byte[] b=new byte[1024];
int len=in.read(b);
in.close();
System.out.println("读入长度为:"+len);
System.out.println(new String(b,0,len));
}
}

或者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 字节流
* 读文件内容,节省空间
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
InputStream in=new FileInputStream(f);
byte[] b=new byte[(int)f.length()];
in.read(b);
System.out.println("文件长度为:"+f.length());
in.close();
System.out.println(new String(b));
}
}

将上面的例子改为一个一个的读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 字节流
* 读文件内容,节省空间
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
InputStream in=new FileInputStream(f);
byte[] b=new byte[(int)f.length()];
for (int i = 0; i < b.length; i++) {
b[i]=(byte)in.read();
}
in.close();
System.out.println(new String(b));
}
}

判断文件的末尾

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 字节流
*读文件
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
InputStream in=new FileInputStream(f);
byte[] b=new byte[1024];
int count =0;
int temp=0;
while((temp=in.read())!=(-1)){
b[count++]=(byte)temp;
}
in.close();
System.out.println(new String(b));
}
}

用字节流实现复制数据

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.FileOutputStream;
import java.io.IOException;
/*
* 需求:把c盘下的a.txt的内容复制到d盘下的b.txt中
*
* 数据源:
* c:\\a.txt -- 读取数据-- FileInputStream
* 目的地:
* d:\\b.txt -- 写出数据 -- FileOutputStream
*/
public class FileDemo2 {
public static void main(String[] args) throws IOException {
// 封装数据源
FileInputStream fis = new FileInputStream("c:\\a.txt");
// 封装目的地
FileOutputStream fos = new FileOutputStream("d:\\b.txt");

// 复制数据
int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}

// 释放资源
fos.close();
fis.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
27
28
29
30
31
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 通过定义数组的方式确实比以前一次读取一个字节的方式快很多,所以,看来有一个缓冲区还是非常好的。
* 既然是这样的话,那么,java开始在设计的时候,它也考虑到了这个问题,就专门提供了带缓冲区的字节类。
* 这种类被称为:缓冲区类(高效类)
* 写数据:BufferedOutputStream
* 读数据:BufferedInputStream
*
* 构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小就足够了。
*
* 为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢?
* 原因很简单,字节缓冲区流仅仅提供缓冲区,为高效而设计的。但是,真正的读写操作还得靠基本的流对象实现。
*/
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws IOException {
// BufferedOutputStream(OutputStream out)
// FileOutputStream fos = new FileOutputStream("bos.txt");
// BufferedOutputStream bos = new BufferedOutputStream(fos);
// 简单写法
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream("bos.txt"));

// 写数据
bos.write("hello".getBytes());

// 释放资源
bos.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
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 需求:把e:\\a.mp4复制到当前项目目录下的b.mp4中
*
* 字节流四种方式复制文件:
* 基本字节流一次读写一个字节: 共耗时:117235毫秒
* 基本字节流一次读写一个字节数组: 共耗时:156毫秒
* 高效字节流一次读写一个字节: 共耗时:1141毫秒
* 高效字节流一次读写一个字节数组: 共耗时:47毫秒
*/
public class CopyMp4Demo {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
// method1("e:\\a.mp4", "copy1.mp4");
// method2("e:\\a.mp4", "copy2.mp4");
// method3("e:\\a.mp4", "copy3.mp4");
method4("e:\\a.mp4", "copy4.mp4");
long end = System.currentTimeMillis();
System.out.println("共耗时:" + (end - start) + "毫秒");
}

// 高效字节流一次读写一个字节数组:
public static void method4(String srcString, String destString)
throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcString));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destString));

byte[] bys = new byte[1024];
int len = 0;
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}

bos.close();
bis.close();
}

// 高效字节流一次读写一个字节:
public static void method3(String srcString, String destString)
throws IOException {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
srcString));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destString));

int by = 0;
while ((by = bis.read()) != -1) {
bos.write(by);

}

bos.close();
bis.close();
}

// 基本字节流一次读写一个字节数组
public static void method2(String srcString, String destString)
throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(destString);

byte[] bys = new byte[1024];
int len = 0;
while ((len = fis.read(bys)) != -1) {
fos.write(bys, 0, len);
}

fos.close();
fis.close();
}

// 基本字节流一次读写一个字节
public static void method1(String srcString, String destString)
throws IOException {
FileInputStream fis = new FileInputStream(srcString);
FileOutputStream fos = new FileOutputStream(destString);

int by = 0;
while ((by = fis.read()) != -1) {
fos.write(by);
}

fos.close();
fis.close();
}
}

字符流

字符流处理字符数据的I/O流,自动处理与本地字符集转化。
字符的处理,一次处理一个字符。底层依然是基本的字节序列。

字符流的基本实现方法

  • InputStreamReader 完成byte流解析为char流,按照编码解析
  • OutputStreamWriter 提供char流到byte流,按照编码处理
  • FileReader/FileWriter

字符流的过滤器

  • BufferedReader —->readLine 一次读一行
  • BufferedWriter/PrintWriter —->写一行


字符流操作要注意的问题:
字符流数据没有直接进文件而是到缓冲区,所以要刷新缓冲区。
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
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
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
/*
* OutputStreamWriter的方法:
* public void write(int c):写一个字符
* public void write(char[] cbuf):写一个字符数组
* public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
* public void write(String str):写一个字符串
* public void write(String str,int off,int len):写一个字符串的一部分
*/
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
// 创建对象
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"osw2.txt"));

// 写数据
// public void write(int c):写一个字符
// osw.write('a');
// osw.write(97);
// 为什么数据没有进去呢?
// 原因是:字符 = 2字节
// 文件中数据存储的基本单位是字节。
// void flush()

// public void write(char[] cbuf):写一个字符数组
// char[] chs = {'a','b','c','d','e'};
// osw.write(chs);

// public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
// osw.write(chs,1,3);

// public void write(String str):写一个字符串
// osw.write("Welcome");

// public void write(String str,int off,int len):写一个字符串的一部分
osw.write("Welcome", 2, 3);

// 刷新缓冲区
osw.flush();
// osw.write("Welcome", 2, 3);

// 释放资源
osw.close();
// java.io.IOException: Stream closed
// osw.write("Welcome", 2, 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
33
34
35
36
37
38
39
40
41
42
43
44
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/*
* String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组
* byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组
*
* 编码:把看得懂的变成看不懂的
* String -- byte[]
*
* 解码:把看不懂的变成看得懂的
* byte[] -- String
*
* 举例:谍战片(发电报,接电报)
*
* 码表:小本子
* 字符 数值
*
* 要发送一段文字:
* 今天晚上在老地方见
*
* 发送端:今 -- 数值 -- 二进制 -- 发出去
* 接收端:接收 -- 二进制 -- 十进制 -- 数值 -- 字符 -- 今
*
* 今天晚上在老地方见
*
* 编码问题简单,只要编码解码的格式是一致的。
*/
public class StringDemo {
public static void main(String[] args) throws UnsupportedEncodingException {
String s = "你好";

// String -- byte[]
byte[] bys = s.getBytes(); // [-60, -29, -70, -61]
// byte[] bys = s.getBytes("GBK");// [-60, -29, -70, -61]
// byte[] bys = s.getBytes("UTF-8");// [-28, -67, -96, -27, -91, -67]
System.out.println(Arrays.toString(bys));

// byte[] -- String
String ss = new String(bys); // 你好
// String ss = new String(bys, "GBK"); // 你好
// String ss = new String(bys, "UTF-8"); // ???
System.out.println(ss);
}
}

向文件中写入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 字符流
* 写入数据
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
Writer out =new FileWriter(f);
String str="hello";
out.write(str);
out.close();
}
}

这个例子和上面的例子没什么区别,只是可以直接输入字符串,而不需要将字符串转化为字节数组。
如果想在文件中追加内容时,可以使用将上面的声明out的哪一行换为:
Writer out =new FileWriter(f,true);
这样,运行程序的时候,会发现文件内容变为:
hellohello
如果想在文件中换行的话,需要使用“\r\n”
比如将str变为String str=”\r\nhello”;
这样文件追加的str的内容就会换行了。

从文件中读内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 字符流
* 从文件中读出内容
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
char[] ch=new char[100];
Reader read=new FileReader(f);
int count=read.read(ch);
read.close();
System.out.println("读入的长度为:"+count);
System.out.println("内容为"+new String(ch,0,count));
}
}

这里最好采用循环读取的方式,因为我们有时候并不知道文件到底有多大。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 字符流
* 从文件中读出内容
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName="D:"+File.separator+"hello.txt";
File f=new File(fileName);
char[] ch=new char[100];
Reader read=new FileReader(f);
int temp=0;
int count=0;
while((temp=read.read())!=(-1)){
ch[count++]=(char)temp;
}
read.close();
System.out.println("内容为"+new String(ch,0,count));
}
}

字符流复制文本文件

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.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/*
* 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
*
* 数据源:
* a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader
* 目的地:
* b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter
*/
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
// 封装数据源
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"a.txt"));
// 封装目的地
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"b.txt"));

// 读写数据
// 方式1
// int ch = 0;
// while ((ch = isr.read()) != -1) {
// osw.write(ch);
// }

// 方式2
char[] chs = new char[1024];
int len = 0;
while ((len = isr.read(chs)) != -1) {
osw.write(chs, 0, len);
// osw.flush();
}

// 释放资源
osw.close();
isr.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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 由于我们常见的操作都是使用本地默认编码,所以,不用指定编码。
* 而转换流的名称有点长,所以,Java就提供了其子类供我们使用。
* OutputStreamWriter = FileOutputStream + 编码表(GBK)
* FileWriter = FileOutputStream + 编码表(GBK)
*
* InputStreamReader = FileInputStream + 编码表(GBK)
* FileReader = FileInputStream + 编码表(GBK)
*
/*
* 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
*
* 数据源:
* a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader
* 目的地:
* b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter
*/
public class CopyFileDemo2 {
public static void main(String[] args) throws IOException {
// 封装数据源
FileReader fr = new FileReader("a.txt");
// 封装目的地
FileWriter fw = new FileWriter("b.txt");

// 一次一个字符
// int ch = 0;
// while ((ch = fr.read()) != -1) {
// fw.write(ch);
// }

// 一次一个字符数组
char[] chs = new char[1024];
int len = 0;
while ((len = fr.read(chs)) != -1) {
fw.write(chs, 0, len);
fw.flush();
}

// 释放资源
fw.close();
fr.close();
}
}

字符缓冲流

字符流为了高效读写,也提供了对应的字符缓冲流。BufferedWriter:字符缓冲输出流,BufferedReader:字符缓冲输入流。

BufferedWriter基本用法

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

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
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/**
* 字符流为了高效读写,也提供了对应的字符缓冲流。
* BufferedWriter:字符缓冲输出流
* BufferedReader:字符缓冲输入流
*
* BufferedWriter:字符缓冲输出流
* 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
* 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
*/
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
// BufferedWriter(Writer out)
// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
// new FileOutputStream("bw.txt")));

BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

bw.write("hello");
bw.write("world");
bw.write("java");
bw.flush();

bw.close();
}
}

BufferedReader基本用法

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。

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.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/**
* BufferedReader
* 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
* 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
*
* BufferedReader(Reader in)
*/
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
// 创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("bw.txt"));

// 方式1
// int ch = 0;
// while ((ch = br.read()) != -1) {
// System.out.print((char) ch);
// }

// 方式2
char[] chs = new char[1024];
int len = 0;
while ((len = br.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}

// 释放资源
br.close();
}
}

拓展功能
  • BufferedWriter,newLine():根据系统来决定换行符
  • BufferedReader,String readLine():一次读取一行数据
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
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 字符缓冲流的特殊方法:
* BufferedWriter:
* public void newLine():根据系统来决定换行符
* BufferedReader:
* public String readLine():一次读取一行数据
* 包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
*/
public class BufferedDemo {
public static void main(String[] args) throws IOException {
// write();
read();
}

private static void read() throws IOException {
// 创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("bw2.txt"));

// public String readLine():一次读取一行数据
// String line = br.readLine();
// System.out.println(line);
// line = br.readLine();
// System.out.println(line);

// 最终版代码
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}

//释放资源
br.close();
}

private static void write() throws IOException {
// 创建字符缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt"));
for (int x = 0; x < 10; x++) {
bw.write("hello" + x);
// bw.write("\r\n");
bw.newLine();
bw.flush();
}
bw.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
27
28
29
30
31
32
33
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中
*
* 数据源:
* a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader -- BufferedReader
* 目的地:
* b.txt -- 写出数据 -- 字符转换流 -- OutputStreamWriter -- FileWriter -- BufferedWriter
*/
public class CopyFileDemo2 {
public static void main(String[] args) throws IOException {
// 封装数据源
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 封装目的地
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

// 读写数据
String line = null;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}

// 释放资源
bw.close();
br.close();
}
}

OutputStreramWriter 和InputStreamReader类

整个IO类中除了字节流和字符流还包括字节和字符转换流。

  • OutputStreramWriter将输出的字符流转化为字节流
  • InputStreamReader将输入的字节流转换为字符流

但是不管如何操作,最后都是以字节的形式保存在文件中的。

将字节输出流转化为字符输出流

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 将字节输出流转化为字符输出流
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "d:"+File.separator+"hello.txt";
File file=new File(fileName);
Writer out=new OutputStreamWriter(new FileOutputStream(file));
out.write("hello");
out.close();
}
}

将字节输入流变为字符输入流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 将字节输入流变为字符输入流
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String fileName= "d:"+File.separator+"hello.txt";
File file=new File(fileName);
Reader read=new InputStreamReader(new FileInputStream(file));
char[] b=new char[100];
int len=read.read(b);
System.out.println(new String(b,0,len));
read.close();
}
}

前面列举的输出输入都是以文件进行的,现在我们以内容为输出输入目的地,使用内存操作流

  • ByteArrayInputStream 主要将内容写入内容
  • ByteArrayOutputStream 主要将内容从内存输出

使用内存操作流将一个大写字母转化为小写字母

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 使用内存操作流将一个大写字母转化为小写字母
* */
import java.io.*;
class hello{
public static void main(String[] args) throws IOException {
String str="ROLLENHOLT";
ByteArrayInputStream input=new ByteArrayInputStream(str.getBytes());
ByteArrayOutputStream output=new ByteArrayOutputStream();
int temp=0;
while((temp=input.read())!=-1){
char ch=(char)temp;
output.write(Character.toLowerCase(ch));
}
String outStr=output.toString();
input.close();
output.close();
System.out.println(outStr);
}
}

管道流

管道流主要可以进行两个线程之间的通信。

  • PipedOutputStream 管道输出流
  • PipedInputStream 管道输入流

验证管道流

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
71
72
73
74
75
/**
* 验证管道流
* */
import java.io.*;

/**
* 消息发送类
* */
class Send implements Runnable{
private PipedOutputStream out=null;

public Send() {
out=new PipedOutputStream();
}
public PipedOutputStream getOut(){
return this.out;
}
public void run(){
String message="hello , Rollen";
try{
out.write(message.getBytes());
}catch (Exception e) {
e.printStackTrace();
}try{
out.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}

/**
* 接受消息类
* */
class Recive implements Runnable{
private PipedInputStream input=null;
public Recive(){
this.input=new PipedInputStream();
}
public PipedInputStream getInput(){
return this.input;
}
public void run(){
byte[] b=new byte[1000];
int len=0;
try{
len=this.input.read(b);
}catch (Exception e) {
e.printStackTrace();
}try{
input.close();
}catch (Exception e) {
e.printStackTrace();
}
System.out.println("接受的内容为 "+(new String(b,0,len)));
}
}
/**
* 测试类
* */
class hello{
public static void main(String[] args) throws IOException {
Send send=new Send();
Recive recive=new Recive();
try{
//管道连接
send.getOut().connect(recive.getInput());
}catch (Exception e) {
e.printStackTrace();
}

new Thread(send).start();
new Thread(recive).start();
}
}

参考自:java中的io整理

有收获再赞赏哦🤭
------ 本文结束感谢您的阅读-------------
0%