IO流——标准输入、输出、打印流

例子见Github-JavaSE-Day07

在这里插入图片描述

CharArrayReader 和 CharArrayWriter

与字节流中ByteArrayStream类似。
再次强调,在I/O流中,字节是万能的。而如果是纯文本可以采取字符方式,效率相对更高。

CharArrayReader构造方法:
CharArrayReader(char[] buf)
从指定的字符数组中创建CharArrayReader。

1
2
3
4
5
6
7
8
9
char[] chars = "土家族民族自治区ww1".toCharArray();
CharArrayReader charArrayReader = new CharArrayReader(chars);
try {
int read = 0;
while ((read = charArrayReader.read()) != -1) {
System.out.println((char)read);
}
}
……

CharArrayWriter构造方法:
CharArrayWriter()
创建一个新的CharArrayWriter。

1
2
3
4
5
CharArrayWriter charArrayWriter = new CharArrayWriter();
charArrayWriter.write(97);
charArrayWriter.write(98);
System.out.println(charArrayWriter);
charArrayWriter.close();

注:
输出时候可以直接打印对象显示。输入时候不可以,需要用read方法

FilterReader (少)

用于读取已过滤的字符流,可以指定自己的规则。

BufferedReader 和BufferedWriter (相对较多)

与BufferedInputStream 和 BufferedOutputStream类似。

buffered本身是带缓冲区的意思,所以我们可以从一个文件里面读取对应的数据。

BufferedReader构造方法:
BufferedReader(Reader in)
创建使用默认大小的输入缓冲区的缓冲字符输入流。 参数是一个Reader对象。

下面第二句会划红线报错,因为Reader和InputStream不匹配(字节是无法直接匹配我们对应的一个字符的):

1
2
InputStream inputStream = null;
inputStream = new BufferedReader(new FileReader("aaa.txt"));

改进:

1
2
Reader reader = null;
reader = new BufferedReader(new FileReader("aaa.txt"));

接下来取数据,最简单的一种方式,每次读取一个字符:

1
2
int read = reader.read();
System.out.println((char)read);

字符读取效率比较低,BuferedReader多了一个readline(),可以按行读取:

1
2
3
4
String read = null;
while ((read = reader.readLine())!= null) {
System.out.println(read);
}

BufferedWriter构造方法:
BufferedWriter(Writer out)
创建使用默认大小的输出缓冲区的缓冲字符输出流。

1
2
3
4
5
6
7
8
9
10
11
BufferedWriter bufferedWriter = null;
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(new File("abc.txt"));
bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write("mashibing"); // 写,返回值是null
bufferedWriter.newLine(); // 换行
bufferedWriter.append("m马士兵"); // 追加,返回值是Writer
bufferedWriter.flush();
}
……

练习1

要求:从控制台(标准输入标准输出)进行一个数据读取。

system类中:
在这里插入图片描述
Stream 一定是针对字节的,而不是字符。
如何把字节转为字符?
利用处理流(字节–>字符)。
System.out本身归属于PrintSteam,而PrintStream又归属OutputStream
在这里插入图片描述
所以最终可以当成一个OutputStream的子类了,所以可以写成new OutputStreamReader(System.out)

1
2
3
4
5
6
7
8
9
10
11
12
13
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(System.out);
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
try {
String str = "";
while (!str.equals("exit")) {
str = bufferedReader.readLine();
bufferedWriter.write(str);
bufferedWriter.flush();
}
}
……

关闭四个流非常麻烦,可采取以下方式简化,之后就不需要再关闭I/O流:

1
2
3
4
5
6
try( InputStreamReader inputStreamReader = new InputStreamReader(System.in);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(System.out);
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);) {
……
}

练习2

要求:例如发送一个请求(输入网址),服务器一定是要返回一个数据的。而这中间也是包含一个I/O流。试想能通过JAVA的I/O流来访问百度并且把首页相关信息返回给我吗?

只要经过网络传输,一般情况下都需要InputStreamReader进行字节转字符和OutputStreamWriter进行字符转字节的操作。

1
2
3
4
5
6
7
8
9
10
11
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
bufferedReader = new BufferedReader(new InputStreamReader(new URL("http://www.baidu.com").openStream(),"UTF-8"));
bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("baidu.html")));
String msg =null;
while ((msg = bufferedReader.readLine()) != null) {
bufferedWriter.write(msg);
bufferedWriter.newLine();
}
……

PrintWriter

PrintWriter构造方法:
创建一个新的打印流,参数可以是File file,可以是String fileName,也可以是OutputStream out

1
2
3
4
5
6
7
8
9
10
11
12
13
PrintStream printStream = null;
try {
printStream = new PrintStream(System.out);
// printStream = new PrintStream(new FileOutputStream("123.txt"));
printStream.write("hello world".getBytes());
printStream.println(true);
System.out.println(); // 所以此时printStream就是相当于`System.out`
// 格式化输出
System.out.printf("%s--%d---%.2f","abc",123,11.1);
// 错误输出 标红打印
System.err.println("mashibing");
}
……

System.out归属于printStream

RandomAccessFile

文件类可以对文件进行相关的操作。
构造方法:

  1. RandomAccessFile(File file, String mode)
    创建一个随机访问文件流从File参数指定的文件中读取,并可选地写入文件。
  2. RandomAccessFile(String name, String mode)
    创建随机访问文件流,以从中指定名称的文件读取,并可选择写入文件。
    mode参数指定要打开文件的访问模式。 允许的值:r,w,s,d

通过RandomAccessFile可以利用块来进行一个文件数据的读取。

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
 File file = new File("doc.txt");
// 整个文件大小
long length = file.length();
// 规定块的大小
int blockSize = 1024;
// 文件可以被切分成多少个块
int size = (int) Math.ceil(length * 1.0 / blockSize);
System.out.printf("要被切成%d个块\n",size);

int beginPos = 0;
int actualSize = blockSize > length ? (int) length : blockSize;
for (int i = 0; i < size; i++) {
// 每次读取块的时候的起始偏移量
beginPos = i*blockSize;
if (i == size - 1) {
actualSize = (int) length;
} else {
actualSize = blockSize;
length -= actualSize;
}
System.out.println(i + "-->起始位置是:" + beginPos + "-->读取的大小是:" + actualSize);
readSplit(i, beginPos, actualSize); // 分块读取文件内容
}
……
public static void readSplit(int i, int beginPos, int actualSize) {
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile(new File("doc.txt"),"r");
// 表示从哪个偏移量开始读取数据
randomAccessFile.seek(beginPos);
byte[] bytes = new byte[1020];
int length = 0;
while ((length = randomAccessFile.read(bytes))!= -1) {
if (actualSize > length) {
System.out.println(new String(bytes, 0, length));
actualSize -= length;
} else {
System.out.println(new String(bytes, 0, actualSize));
break;
}
}
}
……