java基础之-IO(下)

来源:互联网 发布:unix高级编程环境 编辑:程序博客网 时间:2024/05/22 16:38

------- android培训、java培训、期待与您交流! ----------

1,打印流。PrintStream继承了FilterOutpuStream,PrintWriter继承了Writer.这两个流都属于封装类,是为了扩充功能而产生的。

它们都可以打印各种数据值表示形式。比如可以直接打印:print(char c),print(double d),print(float f) ,print(int i),print(long l),print(Object obj)
等。

(在这里值得注意的是即使我们println(int a))传入的是int类型变量,那么在打印的时候也是按照最低八位,也就是按照byte打印的)

因此当我们为了保证数据的原样性我们需考虑使用打印流。需要注意的是当我们要采用自动刷新时,也就是在构造函数中的boolean autoFlush参数为true时,那么我们就必须使用println()方法打印数据。

这两者的构造函数基本相同都可以将一个File对象或者字节输出流当做参数传入。也可以指定编码集。但PrintWriter中多了一个可以将字符输出流当做参数的构造函数。因此我们大多数使用PrintWriter。

2,合并流。SequenceInputStream是inputStream的子类。表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

也就是说它可以将N个字节流连接起来,从N1开始,当N1结尾时自动转换到N2的开头开始依次往下读取。

它的构造函数有:SequenceInputStream(Enumeration<? extendsInputStream> e) 传入一个枚举。SequenceInputStream(InputStream s1,InputStream s2)
传入两个字节读取流。如何使用呢,如果在两个文件以上,那么第二种构造函数已经不够用了,这时考虑使用枚举,枚举是JDK1.0版本就有的,而枚举就是为了遍历Vector集合所产生的。那么我们就联想到可以讲字节读取流添加到Vector中,在获取到枚举,传入到SquenceInputStream构造函数中,那么就可以实现多个字节读取流的链接了。

下面写个例子。

3,切割:将一个文件切割成几个文件。思路定义一个缓冲区,将数据读到缓冲区,然后将这个缓冲区,写入到不同的文件中。

4.对象流。

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。

注意:当一个类的实例要被序列化的前提是要实现serializabel接口,这个接口中没有任何方法要被重写。当这个类要被序列化时被被系统自动定义一个ID用来标识这个序列化的类。当我们将这个序列化的类写到一个本地文件后,要改动这个类重新编译,如果这时要读取这个类,那么会报错,因此会发生ID不匹配,为了避免这样的情况发生我们可以自定义一个ID让它在被改动后,还能读取到这个类。可以添加如下:public static final long serialVersionUID = 42L(访问修饰符可以是任意的)。

如果在这个类里的成员不想被序列化,那么可以采用静态的,或者在成员变量前加上 transient关键字,因为静态成员变量在方法区中,序列化只能是在堆中,如果加上transient关键字那么即使是在堆中也不能被序列化。

下面写个例子:

这是要被序列化的对象

如果我们写入到本地文件后直接读,那么会打印出来:小明:0:男

那么如果我们在构造函数中,传入一个年龄和性别。

同样也只会打印出:小明:0:男

这说明静态的不能被序列化可以读出来,但加入transient关键字的不能序列化也不能被读出来。因为transient保证了这个变量在堆内存中存在,而不会被存入到本地文件,同理更不可能被读出来。

5。管道流。PipedInputStream和PipedoutputStream是IO流与多线程结合的流。

它们可以将输入输出流相连接。在他们的构造函数中都可以将对方做为参数传递进去,表示和对方相连接。也可以用connect(管道流对象)方法设置连接。具体应用

为建立两个线程,run()方法分别进行输入和输出。因为在两个线程执行时谁先执行不确定,但是不会出现异常,因为read()方法是个阻塞式方法,当先执行读取方法时,并没有数据那么就会阻塞,释放执行权,那么就会让输出流,输出数据,有了数据,read()方法就可以进行了。

6,随机文件访问。RandomAccessFile类,它不是IO体系里的成员,但在IO包里,它继承与Object类。

此类的实例支持对随机访问文件的读取和写入。它的内部存在一个byte数组,带有指针,在指针的位置开始写入,读取,修改数据。该文件指针可以通过 getFilePointer 方法读取,并通过seek 方法设置。

它的构造函数:

RandomAccessFile(File file,String mode)和 RandomAccessFile(String name,String mode)
第二个参数是:模式。这个模式代表了对这个文件的操作类型。

模式可以为:“r” ,"rw","rws","rwd",其中"r":只读取和“rw”读取和写入较为常用。(注意:当为只读模式时如果文件不存在则发生异常,如果为读写模式时如果文件不存在则创建该文件,如果文件存在则续写该文件)

通常在读取和写入这个文件时,这个文件的数据要具有规律性,比如存入中国人的姓名和年龄,一个中国汉子占2字节,一个整数占4字节。那么我们以中国人名字最多8个字为例,它就是8*2+4=16个字节。以便当读取时可以用seek(long pos)设置指定的位置,进行读取修改等操作。

下面写个老师的例子加深下印象:


此类可以应用到下载资源上,将网上的资源分段读取,分段写入本地文件,将RandomAccessFile对象封装到不同的线程中执行。

7.操作基本数据类型的流对象。数据流:DataInputStream,DataOutputStream。

它的构造函数为:传入一个字节流。目的是为了增强其功能。其中数据流中有一个特殊的方法就是writeUTF(String s)按照这种编码形式写入的文件只能用数据读取流的readUTF()方法读取,用读取转换流指定编码UTF-8的方法不能读取出来,因为这是UTF-8修改版编码,同样的两个汉字,GBK占4字节,UTF-8占6字节,UTF-8修改版占8字节。

8,。ByteArrayInputStream,ByteArrayOutputStream是专门用来操作字节数组的。

bytearrayinputStream的构造函数中要指定一个源也就是字节数组。ByteArrayInputStream(byte[] buf)

而bytearrayoutputStream的构造函数中部需要传入任何参数,因此它的内部封装了一个可变长度的字节数组。因为两者都没有调用底层资源因此不需要关闭它们。

ytearrayoutputStream常用的方法有toByteArray() 返回一个字节数组。writeTo(OutputStream out)里面传入一个字节输出流。功能是将次缓冲区里的数据写入硬盘中。

9,。字符编码:由来,计算机只能识别二进制数,那么为了方便,便将这些各个国家的文字用二进制数表示,进行一一对应,形成一张表,就是编码表

常用的编码表:ASCII:美国信息交换码,用一个字节的7位表示。ISO8859-1:拉丁码表,用一个字节的八位表示。GB2312:中文编码表。GBK中国编码表的升级版

UNICODE:国际标准码。它融合了多重语言文字。UTF-8用三个字节表示一个字符。

在GBK中一个汉字占用两个字节,一个字母占用1个字节。UTF-8中汉字占用3个字节一个字母占用一个字节。

在进行编码解码时注意,当我们用GBK编码时解码用了ISO8859-1那么我们在用ISO8859-1编码,会得到原数据,再用GBK解码还会得到当初编码时的数据,但当用UTF-8解码错误时,在进行编码不会得到原数据。


0 0
原创粉丝点击