IO初步:(流)
概括:Java输入输入输出流原理。Java流的分类。输入输出流类。常见的节点流和处理流。文件流。缓冲流。数据流。转换流。Print流。Object流。
流:(即管道)<一端接着管道,一端接着数据源>java中对于数据的输入输如输出操作以流的形式进行。对文件,对空间的访问,读取通过流的方式获取不同种类的数据。程序通过标准的方法输入或输出程序。(在文件,信息中插入管道,使其可以流进去,或可以流出来这样的管道就叫做流)<与水流的方式一模一样>网络连接,文件与文件之间,文件与程序之间,程序与程序之间都可以通过流(注意运输的是二进制代码,但有加强的管道可以将这些二进制代码转换成所对应的数据再运输到别的程序文件里)
流的分类:
上一章,可见接口可以组织成一个庞大的继承体系,本章与上一章有相同点,也有不同点,本章对于流的体系组织是四个抽象类。
输入流输出流:
站在程序的角度上看是在输入程序数据,还是在输出程序(改变文件)
字符流字节流:
字节流是最原始的流,0101001(8位8位读)字符流(两个字节char)读
节点流处理流:
节点流:直接将管道接通文件与程序。
处理流:在管道之上套着,对文件数据的传输起处理作用的叫处理流。(可以套许多层)<更高级>
(以Stream结尾的都是字节流)Reader(字符流)输入流,writer(字符流)输出流
InputStream
Buffer缓冲区可以减少读写的次数,减少对硬件的损伤,相当于一个小桶,一次性装许多东西,一次性写到硬盘,这样的缓冲区可以使用字节数组完成。
int |
available() |
void |
close() |
void |
mark(int readlimit) |
boolean |
markSupported() |
abstract int |
read() |
int |
read(byte[] b) |
(返回值实际读取多少值) int |
read(byte[] b, int off, int len) |
void |
reset() |
long |
skip(long n) (几乎不用) |
OutputStream
void |
close() |
void |
flush() |
void |
write(byte[] b) |
void |
write(byte[] b, int off, int len) |
abstract void |
write(int b) |
对于flush和close
Close的关闭非常粗暴,close将直接将管道关闭,而flush将先把缓冲区的内容全部输出,然后再用close才是最好的选择。
Reader
Reader与InputStream的区别在于后者两个字节两个字节的读(中文字符占两个字节,若只一个字节一个字节的读,只能读半个)
abstract void |
close() |
void |
mark(int readAheadLimit) |
boolean |
markSupported() |
int |
read() |
int |
read(char[] cbuf) |
abstract int |
read(char[] cbuf, int off, int len) |
int |
read(CharBuffer target) |
boolean |
ready() |
void |
reset() |
long |
skip(long n) |
Writer
append(char c) |
|
append(CharSequence csq) |
|
append(CharSequence csq, int start, int end) |
|
abstract void |
close() |
abstract void |
flush() |
void |
write(char[] cbuf) |
abstract void |
write(char[] cbuf, int off, int len) |
void |
write(int c) |
void |
|
void |
String中有可以将String变成字符数组的方法。
节点流类型
protected |
FilterInputStream(InputStream in) |
int |
available() |
void |
close() |
void |
mark(int readlimit) |
boolean |
markSupported() |
int |
read() |
int |
read(byte[] b) |
int |
read(byte[] b, int off, int len) |
void |
reset() |
long |
skip(long n) |
FileInputStream与FileOutputStream
见相应javaIO包中的练习
FileReader与FileWriter(与上述相同)
只不过显示中文很好。(但还是有的文字符号显示不了,因为可能有的国家的语言需要更大的字节,java不能提供)
处理流:(包在别的流上的流)
类型
缓冲流(小桶):(BufferedReader,BufferedWriter)内存中的相应缓冲内存。
见TestBufferStream。
1310(asc码中是回车,转换成字符后就是个空格)
这是一种套在节点流上的处理流,使管道拥有缓冲区。、
BufferReader
注意文件的内容的读写是在内存中的执行,而并非在命令提示框内,也并非在
中有一个特别好的方法,readLIne()这个方法可以读一行代码(返回值是一个String)。
转换流
转换流可以把字节流转换成字符流,将读取的方式改变。InputStreamReader(转换InputStream变成Reader)OutputStreamWriter(转换OutputStream变成Writer)注意程序中的true,如果没有这个true,这个命令将把这个文件的内容擦去,重新写,而有了这个true之后,他将在文件后面继续写。
之前在写的时候没有选择编码,会使用当前系统默认的编码(中文windows用的是gbk)
后来指定好了,编码为ISO08859_1.所以结果会打印两边。
这样一来在字节管道外面加一层可以使其灌输更快,直接字符串,不用再字符,或字符数组。
西欧文字,就是ISO9959_1,后来就才出现了Unicode(16)
System.out对象是命令行代码,System.in是InputStream类型(是一个子类),
System.in是在接收键盘的输入。
管道接在键盘上,正准备读键入内容(一个字符,一个字符的读)。
BufferedReader可以读一行,有readLine()方法。这个程序有三个参数。
这是一个输入的参数知道输入exit。
DataIn/OutputStram,即ByteArrayIn/OutputStream
ByteArrayIn/OutputStream是可以(以字节数组)传输数据的管道,而这不方便我们传输较大的数字,及一些基本数据类型,因为基础数据类型在传输时,需要先转换成一个一个的字符串,再拆字符,转换为字节数组再传进出,但如果我们直接套上数据流就不会这么麻烦了,因为数据流可以直接传输基础数据类型(同时还可以计算这些数据类型的占多少字节),注意这些基础数据类型在写的时候的顺序,在读的时候也要按顺序,否则其会取类型的一部分进行强制转换,发生数据丢失,溢出。同时这种方法还可以传输unicode编码,注意Unicode(utf8)与UIcode(utf16)有区别,前者虽为早期,但其占空间较小,所以网落上一般使用这种Unicode编码。
Print流(只有输出没有输入)(基础节点流)
PrintWriter和PrintStream(一个输出字节,一个输出字符)
二者重写了Print方法,System中的out是一个静态的,是PrintStream类型。
Print流可以用于输出各种类型的数据,而且PrintWriter和PrintStream的输出操作不会抛出异常。Print流有自动的flush功能,即缓存自动清除,每输出一次,flush一次。
Out也可以通过setOut方法改变输出位置(默认输出在命令行窗口),System.out的输出地方就变了(变成了文件,因为out是PrintStream类型),分析管道程序,画图很重要。
第一个程序重写了out,第二个程序可以将输出管道在命令行窗口输入地址,将该地址下的文件,用管道输出到命令行窗口。
第三个程序是日志程序,可以记录程序员对程序的改动,操作。Java有专门的日志api,日志开发包。注意这里文件可以不用flush,但需要close。Java.util.date封装了当前的日期(装的long的毫秒数可正可负),对于这个long类型的数有对其进行操作专门的类。对于程序三,其还可以记录输入命令的时间(可以用于聊天室的构建)
Object流(处理流 objectout/InputStream)
用于直接将Object写入或读出,transient关键字。Serializable接口。Externalizable接口。
在new object的时候会有一些相关的版本号,指针之类的东西会被Object流一并写入。
对于Serializable(可被序列化的)是标记性接口这是一个没有方法的接口,编译器会识别它,认为他是可以序列化的。(如果想让某个类的对象可以被序列化,一定要让这个类实现Serializable)<这样就可以直接将Object分解再组装,不用一个一个的写,读>
Transient透明的:可以修饰成员变量,这个成员变量在序列化时可以不被序列化,这样,这个值在读的时候就是系统默认的值,为0。
Externalizable(接口)外部化:实现externalizable接口(serializable的子接口)可以决定自己的对象是如何序列化的。控制自己对象的写入写出过程,但这时必须要重写这个接口的两个方法。
总结:
本章主要是管道的对接方法和使用,以及管道与管道之间的不同。主要是:字节流,字符流,节点流,处理流,输入流,输出流,总的还是几个抽象类组织起的框架。Java中有将字节转换为字符的流,但没有将字符转换为字节的(因为内存中本来就是以字节形式储存的)。
注意每种类的用途,区别,名称,类别。