Java笔记系列(基于马士兵的课堂)(5)-IO

时间:2022-09-20 08:43:17

IO初步:(流)

概括:Java输入输入输出流原理。Java流的分类。输入输出流类。常见的节点流和处理流。文件流。缓冲流。数据流。转换流。Print流。Object流。

流:(即管道)<一端接着管道,一端接着数据源>java中对于数据的输入输如输出操作以流的形式进行。对文件,对空间的访问,读取通过流的方式获取不同种类的数据。程序通过标准的方法输入或输出程序。(在文件,信息中插入管道,使其可以流进去,或可以流出来这样的管道就叫做流)<与水流的方式一模一样>网络连接,文件与文件之间,文件与程序之间,程序与程序之间都可以通过流(注意运输的是二进制代码,但有加强的管道可以将这些二进制代码转换成所对应的数据再运输到别的程序文件里)


流的分类:

Java笔记系列(基于马士兵的课堂)(5)-IO

上一章,可见接口可以组织成一个庞大的继承体系,本章与上一章有相同点,也有不同点,本章对于流的体系组织是四个抽象类。

输入流输出流:

站在程序的角度上看是在输入程序数据,还是在输出程序(改变文件)

字符流字节流:

字节流是最原始的流,0101001(8位8位读)字符流(两个字节char)读

节点流处理流:

节点流:直接将管道接通文件与程序。

处理流:在管道之上套着,对文件数据的传输起处理作用的叫处理流。(可以套许多层)<更高级>

(以Stream结尾的都是字节流)Reader(字符流)输入流,writer(字符流)输出流

InputStream

Buffer缓冲区可以减少读写的次数,减少对硬件的损伤,相当于一个小桶,一次性装许多东西,一次性写到硬盘,这样的缓冲区可以使用字节数组完成。

 int

available()
          返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。

 void

close()
          关闭此输入流并释放与该流关联的所有系统资源。

 void

mark(int readlimit)
          在此输入流中标记当前的位置。

 boolean

markSupported()
          测试此输入流是否支持 mark 和 reset 方法。

abstract  int

read()
          从输入流中读取数据的下一个字节。

 int

read(byte[] b)
          从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。

(返回值实际读取多少值) int

read(byte[] b, int off, int len)
          将输入流中最多 len 个数据字节读入 byte 数组。

 void

reset()
          将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。

 long

skip(long n) (几乎不用)
          跳过和丢弃此输入流中数据的 n 个字节。

OutputStream

 void

close()
          关闭此输出流并释放与此流有关的所有系统资源。

 void

flush()
          刷新此输出流并强制写出所有缓冲的输出字节。

 void

write(byte[] b)
          将 b.length 个字节从指定的 byte 数组写入此输出流。

 void

write(byte[] b, int off, int len)
          将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

abstract  void

write(int b)
          将指定的字节写入此输出流。

对于flush和close

Close的关闭非常粗暴,close将直接将管道关闭,而flush将先把缓冲区的内容全部输出,然后再用close才是最好的选择。

Reader

Reader与InputStream的区别在于后者两个字节两个字节的读(中文字符占两个字节,若只一个字节一个字节的读,只能读半个)

abstract  void

close()
          关闭该流并释放与之关联的所有资源。

 void

mark(int readAheadLimit)
          标记流中的当前位置。

 boolean

markSupported()
          判断此流是否支持 mark() 操作。

 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

 Writer

append(char c)
          将指定字符添加到此 writer。

 Writer

append(CharSequence csq)
          将指定字符序列添加到此 writer。

 Writer

append(CharSequence csq, int start, int end)
          将指定字符序列的子序列添加到此 writer.Appendable。

abstract  void

close()
          关闭此流,但要先刷新它。

abstract  void

flush()
          刷新该流的缓冲。

 void

write(char[] cbuf)
          写入字符数组。

abstract  void

write(char[] cbuf, int off, int len)
          写入字符数组的某一部分。

 void

write(int c)
          写入单个字符。

 void

write(String str)
          写入字符串。

 void

write(String str, int off, int len)
          写入字符串的某一部分。

String中有可以将String变成字符数组的方法。


节点流类型

Java笔记系列(基于马士兵的课堂)(5)-IO

protected

FilterInputStream(InputStream in)
          将参数 in 分配给字段 this.in,以便记住它供以后使用,通过这种方式创建一个 FilterInputStream。

 int

available()
          返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。

 void

close()
          关闭此输入流并释放与此流关联的所有系统资源。

 void

mark(int readlimit)
          在输入流中的当前位置上作标记。

 boolean

markSupported()
          测试此输入流是否支持 mark 和 reset 方法。

 int

read()
          从此输入流中读取下一个数据字节。

 int

read(byte[] b)
          从此输入流中将 byte.length 个字节的数据读入一个 byte 数组中。

 int

read(byte[] b, int off, int len)
          从此输入流中将 len 个字节的数据读入一个 byte 数组中。

 void

reset()
          将此流重新定位到对此输入流最后调用 mark 方法时的位置。

 long

skip(long n)
          跳过和丢弃此输入流中数据的 n 个字节。

FileInputStream与FileOutputStream

见相应javaIO包中的练习

FileReader与FileWriter(与上述相同)

只不过显示中文很好。(但还是有的文字符号显示不了,因为可能有的国家的语言需要更大的字节,java不能提供)

处理流:(包在别的流上的流)

类型

Java笔记系列(基于马士兵的课堂)(5)-IO

缓冲流(小桶):(BufferedReader,BufferedWriter)内存中的相应缓冲内存。

见TestBufferStream。

1310(asc码中是回车,转换成字符后就是个空格)

这是一种套在节点流上的处理流,使管道拥有缓冲区。、

BufferReader

Java笔记系列(基于马士兵的课堂)(5)-IO

注意文件的内容的读写是在内存中的执行,而并非在命令提示框内,也并非在

中有一个特别好的方法,readLIne()这个方法可以读一行代码(返回值是一个String)。

转换流

Java笔记系列(基于马士兵的课堂)(5)-IO


转换流可以把字节流转换成字符流,将读取的方式改变。InputStreamReader(转换InputStream变成Reader)OutputStreamWriter(转换OutputStream变成Writer)注意程序中的true,如果没有这个true,这个命令将把这个文件的内容擦去,重新写,而有了这个true之后,他将在文件后面继续写。

之前在写的时候没有选择编码,会使用当前系统默认的编码(中文windows用的是gbk)

后来指定好了,编码为ISO08859_1.所以结果会打印两边。

这样一来在字节管道外面加一层可以使其灌输更快,直接字符串,不用再字符,或字符数组。

 Java笔记系列(基于马士兵的课堂)(5)-IO

西欧文字,就是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类型的数有对其进行操作专门的类。对于程序三,其还可以记录输入命令的时间(可以用于聊天室的构建)

 Java笔记系列(基于马士兵的课堂)(5)-IO

Object流(处理流 objectout/InputStream

用于直接将Object写入或读出,transient关键字。Serializable接口。Externalizable接口。

在new object的时候会有一些相关的版本号,指针之类的东西会被Object流一并写入。

对于Serializable(可被序列化的)是标记性接口这是一个没有方法的接口,编译器会识别它,认为他是可以序列化的。(如果想让某个类的对象可以被序列化,一定要让这个类实现Serializable)<这样就可以直接将Object分解再组装,不用一个一个的写,读>

Transient透明的:可以修饰成员变量,这个成员变量在序列化时可以不被序列化,这样,这个值在读的时候就是系统默认的值,为0。

Externalizable(接口)外部化:实现externalizable接口(serializable的子接口)可以决定自己的对象是如何序列化的。控制自己对象的写入写出过程,但这时必须要重写这个接口的两个方法。

总结:

本章主要是管道的对接方法和使用,以及管道与管道之间的不同。主要是:字节流,字符流,节点流,处理流,输入流,输出流,总的还是几个抽象类组织起的框架。Java中有将字节转换为字符的流,但没有将字符转换为字节的(因为内存中本来就是以字节形式储存的)。

注意每种类的用途,区别,名称,类别。