20120417 杂知识点记录


20120417 杂知识点记录



没有方法的接口,通常称为:标记接口(就是给实现该接口的类盖个戳)。,如java.io.Serializable。可以手动为类指定一个序列化UID,注意,静态成员是不能被序列化的。因为,非静态的成员变量在内存中是放在堆栈中的,而静态变量是放在方法区的。序列化UID只能序列化堆里的变量。如果也想让某个非静态的变量不被序列化,可以给它加一个修饰符:transient,这样即使它在堆内存中,也不会被序列化。用法,比如用ObjectOutputStream、ObjectInputStream读写对象时,静态的和用transient修饰的变量的值是不会被存储到文件或其他流中去的。ObjectOutputStream、ObjectInputStream一定要成对使用。

集合当中涉及到IO流的是Properties,IO流中涉及到多线程的是PipedInputStream和PipedOutputStream(管道流)。

多线程操作中,实现Runnable接口后,一定要覆盖run方法,如果里面可能出现异常,不能抛,只能try、catch。创建线程并启动的方式:

Class MyThread implements Runnable {
	public void run() {
		try {
			…
		} catch(Exception e) 
		{
			…
		}
	}
}

Class MyThreadTest {
	public static void main(String[] args) {
		MyThread t = new MyThread();
		new Thread(t).start();
	}
}

字节流的写入方法write(int ch),是将ch值的最低八位写入了(因为字节流读写操作的单位是字节)。如果数值超过八位最大值(255),则会出现数据丢失。

RandomAccessFile随机读写访问
API的说明是:支持对随机访问文件的读取和写入。类似存储在文件系统中的一个大型 byte 数组,存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。
通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出 EOFException(是一种 IOException)。如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出 IOException,而不是 EOFException。需要特别指出的是,如果流已被关闭,则可能抛出 IOException。
这个类是Object的子类,之所以包含在IO包中,是因为它也具备读和写的功能。我们可以理解为,它里面封装了一个byte数组,同时存在一个文件指针,可以随机指向文件中某个字节的存储位置(数组角标),所以,可以通过指针对数组的元素进行操作。用方法getFilePointer可以获取指针位置。用seek方法可以改变指针位置(向前/后移动)。
其实,完成读写的原理,就是内部封装了字节读取流和输出流。通过构造函数,我们可以看出,该类只能操作文件。同时,操作文件还有不同的模式:r,只读;rw,读写。
r:只读模式只能读取已存在的文件,当构造函数传入的文件不存在时,不会创建文件,而是会出现异常;
rw:读写模式,当文件不存在时,会自动创建;如果已存在,则不会覆盖。
seek(long pos)方法:可以将指针向前或者向后移动pos个位置;
skipBytes(int n):向后跳过n个字节(不能向前)。
所以,seek比skipBytes方法常用。
seek方法,一般适用于文件中数据的存储是有规律的情况。比如,存储的都是人的信息,每个人的信息包括:姓名(固定分配字节数,比如16个字节,既最多8个汉字),年龄(固定4个字节,既一个int)。这样,每20个字节代表一个人的信息。若想访问某个人的信息时,就将指针移动到该位置,比如移动到第n个人,就是seek(20*n)。
另外:常见下载工具的下载方式,也运用了该方法的原理。一般下载工具是多线程下载,这样每个线程分配一段数据,为了保证文件的正确性,所有线程都应将本段下载的数据存储到文件(数组)中对应的位置。而不是像其他IO流对象那样,写文件都是自动追加到文件末尾的方式。

ByteArrayInputStream、ByteArrayOutputStream用来操作字节数组的流对象:
它是唯一一个没有调用系统资源的IO流。它是内部封装了一个可变长度的字节数组,用来存储读写操作的数据。所以,ByteArrayInputStram在构造的时候,需要接收数据源(字节数组),ByteArrayOutputStream则不用定义数据目的,因为内部封装了一个字节数组。这两个流都不需要close关闭操作,且没有IOException异常。

IO流中加入编码表的流对象有:
PrintStream、PrintWriter(但只能打印不能读取)、InputStreamReader、OutputStreamWriter。

常见的编码表:
ASCII:美国标准信息交换码(英文字符),一个字节的7位即可表示一个字符。
ISO8859-1:欧洲码表,一个字节的8位表示。
GB2312、GBK:中文编码表。
Unicode:国际标准码,融合多国文字,两个字节表示一个字符。如Java语言用的编码表(char)。
UTF-8:最多用三个字节表示一个字符。
类似电报的发送接收:
编码:字符串->字节数组(String->byte[],str.getBytes(charsetName));
解码:字节数组->字符串(byte[]->String,new String(byte[],charsetName))。

编码编错了,解码就不会正确了;
但如果编码对了,解码出错了,还可以恢复(服务器开发的时候用到)。

UTF-8存储的字符,带有标识头信息,比如两个字节表示的字符,是用110xxxxx 10xxxxxx表示,一个字节表示的字符(ASCII字符),是用0xxxxxxx表示,三个字节的是用1110xxxx 10xxxxxx 10xxxxxx表示。因此某个字节是表示的ASCII字符,还是三个字节的汉字,就用标识头识别。

猜你喜欢

转载自blog.csdn.net/nazhidao/article/details/7486863
今日推荐