欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

CoreJava学习心得13

程序员文章站 2022-07-13 21:37:22
...
1Java中的I/O

使用I/O流访问file中的内容。
JVM与外界通过数据通道进行数据交换。
分类:按流分为输入流和输出流,按传输单位分为字节流和字符流,还可以分为节点流和过滤流。

节点流:负责数据源和程序之间建立连接。
过滤流:用于给节点增加功能。在关闭流时如果使用了过滤流,只需关闭最外层的流就可以了。

过滤流的构造方式是以其他流为参数构造(这样的设计模式称为装饰模式)并且过滤流本身不能使用,他的作用只是增强节点流的功能。

字节输入流:

InputStream类 (抽象类)
所有字节输入流的父类

io包中的InputStream为所有字节输入流的父类。
int read();读入一个字节(每次一个);
可先使用new  byte[],调用read(byte[] b),byte[]数组长度决定了可以读取到的最大字节数,用来调整效率。read (byte[])返回值可以表示有效数;read (byte[])返回值为-1表示结束。

字节输出流:io包中的OutputStream位所有字节输入流的父类。Write和输入流中的read相对应。

在流中close()方法由程序员控制。因为输入输出流已经超越了VM的边界,所以有时可能无法回收资源。
原则:凡是跨出虚拟机边界的资源都要求程序员自己关闭,不要指望垃圾回收。
以Stream结尾的类都是字节流。
如果构造FileOutputStream的同时磁盘会建立一个文件。如果创建的文件与磁盘上已有的文件名重名,就会发生覆盖。
用FileOutputStream中的boolean,则视添加情况,将数据覆盖重名文件还是将输入内容放在文件的后面。(编写程序验证)


如:FileInputStream,ObjectInputStream,PipedInputStrean都是InputStream类的子类。

1) 三个基本的read()方法
      a. int read(): 从流里读出的一个字节或者-1; (实际读了多长)
      b. int read(byte[]):将数据读入到字节数组中,并返回所读的字节数; (期望读了多长)
      c. int read(byte[], int , int):两个int参数指定了所要填入的数组的子范围。
2) 其它方法
      a. void close(): 关闭流,如使用过滤器流,关闭最外部的流,会关闭其余的流。
      b. int available(): 返回可从流中读取的字节数。
      c. void skip(long): 丢弃了流中指定数目的字符。
      d. boolean markSupported()
      e. void mark(int)
      f. void rese()

OutputStream类(抽象类)
所有输出流的父类。

1) 三个基本的write()方法
      a. void write()
      b. void write(byte[])
      c. void write(byte[], int , int)
2) 其它方法
      a. void close(): 关闭流,如使用过滤器流,关闭最外部的流,会关闭其余的流。
      b. void flush(): 允许你强制执行写操作。
注意:在流中close()方法由程序员控制。因为输入输出流已经超越了JVM的边界,所以有时可能无法回收资源。
原则:凡是跨出虚拟机边界的资源都要求程序员自己关闭,不要指望垃圾回收。

基本输入输出所使用的类的介绍:

FileInputStream和FileOutputStream (文件输入输出流)

以上两个是字节流
1) 结点流,可以对磁盘文件进行操作。
2) 要构造一个FileInputStream, 所关联的文件必须存在而且是可读的。
3) 要构造一个FileOutputStream而输出文件已经存在,则它将被覆盖。

FileInputStream infile = new FileInputStream("myfile.dat");
   FIleOutputStream outfile = new FileOutputStream("results.dat");
FileOutputStream outfile = new FileOutputStream(“results.dat”,true);
参数为true时输出为添加,为false时为覆盖。
 
FileOutputStream类代码:(为什么能建文件)
		Public FileOutputStream(String name){
			This(name!=null?new File(String):null,false);
		}



DataInputStream和DataOutputStream(字节流)

以上两个是过滤流。通过流来读写Java基本类,注意DataInputStream和DataOutputStream的方法是成对的。 支持直接输出输入各种数据类型。
writeBoolean(boolean b),readBoolean() ------以1bit数据传送
writeByte(int),readInt()------以1 byte数据传送
writeBytes(String s),readLine() (已过时方法)将字符串按字节顺序写出到基础输出流中以byte序列数据传送
writeChar(int v),readChar()――――――以 2 byte
writeChars(String s),readChar()-------------以 2 byte序列
writeDouble(double d),readDouble() -------以 8 byte
writeInt(int v),readInt()
writeLong(long l),readLong()
writeShort(short s),readShort()
writeUTF(String),readUTF()-----------能输出中文!

注意:使用DataOutputStream/DataInputStream时,要注意写入顺序和读取顺序相同,否则会将没有分割写入的信息分割不正确而读取出错误的数据。



BufferInputStream和BufferOutputStream(带缓存的字节流)

以上两个是过滤流,可以提高I/O操作的效率 ,用于给节点流增加一个缓冲的功能。

在JVM的内部建立一个缓冲区,数据先写入缓冲区,等到缓冲区的数据满了之后再一次性写出,效率很高。使用带缓冲区的输入输出流的速度会大幅提高,缓冲区越大,效率越高。(这是典型的牺牲空间换时间)

切记:使用带缓冲区的流,如果数据数据输入完毕,使用flush()方法将缓冲区中的内容一次性写入到外部数据源。用close()也可以达到相同的效果,因为每次close()都会调用flush()。一定要注意关闭外部的过滤流。

管道流(和UnixC++中的FIFO相同)
PipedInputStream和PipedOutputStream (字节流)

这两个是节点流,注意,用来在线程间通信。

  
 PipedOutputStream pos=new PipedOutputStream();
		PipedInputStream pis=new PipedInputStream();
		try
		{
			pos.connect(pis);
			new Producer(pos).start();//线程类对象,在构造时,使用管道流通信
			new Consumer(pis).start();//线程类对象,在构造时,使用管道流通信
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}


随机存取文件

RondomAccessFile类允许随机访问文件,这个类也是支持直接输出输入各种数据类型。
getFilepoint()可以知道文件中的指针位置,使用seek()定位。
Mode(“r”:随机读;”w”:随机写;”rw”:随机读写)
1) 实现了二个接口:DataInput和DataOutput;
2) 只要文件能打开就能读写;
3) 通过文件指针能读写文件指定位置;
4) 可以访问在DataInputStream和DataOutputStream中所有的read()和write()操作;
5) 在文件中移动方法:
a. long getFilePointer(): 返回文件指针的当前位置。
b. void seek(long pos): 设置文件指针到给定的绝对位置。
c. long length(): 返回文件的长度。


字符流

字符流可以解决编程中字符的编码问题。从字符到整数,对字符集和整数集建立一一对应的关系,就算叫做编码,从整数映射到字符,就叫做解码。

编码问题:

字节流的字符编码:
字符编码把字符转换成数字存储到计算机中,按ASCii将字母映射为整数。
把数字从计算机转换成相应的字符的过程称为解码。

编码的方式:
每个字符对应一个整数。不同的国家有不同的编码,当编码方式和解码方式不统一时,产生乱码。因为美国最早发展软件,所以每种的编码都向上兼容ASCII 所以英文没有乱码。

ASCII(数字、英文)1个字符占一个字节(所有的编码集都兼容ASCII)
ISO8859-1(欧洲)  1个字符占一个字节
GB-2312/GBK        1个字符占两个字节
Unicode            1个字符占两个字节(网络传输速度慢)
UTF-8              变长字节,对于英文一个字节,对于汉字两个或三个字节。


InputStreamReader和OutputStreamWriter(字节流转化成字符流的桥转换器)
这两个类不是用于直接输入输出的,他是将字节流转换成字符流的桥转换器,并可以指定编解码方式。

Reader和Writer (字符流类,所有字符流的父类型)

1) Java技术使用Unicode来表示字符串和字符,而且提供16位版本的流,以便用类似的方法处理字符。
2) InputStreamReader和OutputStreamWriter作为字节流与字符流中的接口。
3) 如果构造了一个连接到流的Reader和Writer,转换规则会在使用缺省平台所定义的字节编码和Unicode之间切换。

BufferedReader/(BufferedWriter,不常用)(这两个类需要桥转换)
PrintWriter(带缓存的字符输出流,不需要桥转换)

常用输入输出类型,不需要桥接,其中其它方法请参看API文档。
以上两个都是过滤流,需要用其他的节点流来作参数构造对象。
BufferedReader的方法:String  readLine(),当他的返回值是null时,就表示读取完毕了。要注意,再写入时要注意写换行符,否则会出现阻塞。
BufferedWriter的方法:newLine() ,这个方法会写出一个换行符。
PrintWriter的方法:println(….String,Object等等)和write(),println(...)这个方法就不必再写换行符了,在使用时会自动换行。

注意:在使用带有缓冲区的流时,在输入之后就要flush()方法,把缓冲区数据发出去。

原则:保证编解码方式的统一,才能不至于出现错误。
java.io包的InputStreamread输入流的从字节流到字符流的桥转换类。这个类可以设定字符转换方式。
OutputStreamred:输出流的字节流桥转换成字符流
Bufferread有readline()使得字符输入更加方便。
在I/O流中,所有输入方法都是阻塞方法。
Bufferwrite给输出字符加缓冲,因为它的方法很少,所以使用父类PrintWrite,它可以使用字节流对象,而且方法很多。