Java笔记 - IO流 - 其他类

RandomAccessFile随机访问文件

RandomAccessFile是Object的子类。一般IO流都是成对出现的,但是RandomAccessFile和打印流、序列流一样都是单独存在的。
特点:
1. 和打印流序列流不同的是RandomAccessFile既可以读也可以写。
2. RandomAccessFile的内部其实是一个byte类型的数组,数组可以延长,该数组存在一个指向数组的索引,称之为文件指针。
3. 可以通过getFilePointer方法获取指针的位置,通过seek方法设置指针的位置。
4. 它可以对数组进行读和写,数组是byte类型的,所以RandomAccessFile类其实是对字节输出流和字节输入流进行了封装
5. RandomAccessFile对象的源和目的只能是文件。

RandomAccessFile raf = new RandomAccessFile("E:\\raf.txt","rw");
raf.write("张三".getBytes());
raf.writeInt(97);
raf.write("李四".getBytes());
raf.write(98);
raf.close();

输出结果:

张三   a李四b

这里是a和b是因为记事本把写进去的97和98解析了,不管怎么解析,最底层的97和98是不变的,所以这里没有问题。而如果我们修改代码
raf.write(609);
输出结果却也是a。因为int类型是4个字节,它只写最低位的字节。如果我们想写原字节,就要用writeInt方法, 所以a前面有3个空格。
并且如果使用RandomAccessFile创建文件,文件不存在,则创建,文件存在,则不创建。这和一般的输出流不一样,其他的输出流都是不管文件存在不存在都会创建。如果文件存在,继续写入数据,就会把原数据覆盖。

RandomAccessFile raf = new RandomAccessFile("E:\\raf.txt","rw");
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);

raf.close();

输出结果:

name=张三
age=97

在读age的时候我们不能拿数组读,读完转成String然后打印出来,因为age应该是一个int类型的值,不能用String类型。所以需要一个专门读int类型值的方法readInt(),读完就是97了。

操作指针读写

设置指针:seek
获取指针:getFilePointer
因为内部其实是一个数组,所以指针位置从0开始。

RandomAccessFile raf = new RandomAccessFile("E:\\raf.txt","rw");

raf.seek(8);
raf.write("王五".getBytes());
raf.writeInt(99);
System.out.println("指针位置在"+raf.getFilePointer()) ;
raf.close();

输出结果:

指针位置在16
//记事本中内容:张三   a王五c,覆盖掉了李四,但是张三依然保留。

PipedInputStream和PipedOutputStream管道流

管道流的主要作用就是可以进行两个线程之间的通讯,一个线程作为管道输出流,一个线程作为管道输入流。它不同于其他的输入输出流,管道输出流只能连接到管道输入流。不建议对这两个对象使用单线程,因为这两个输入输出流是相互关联的。如果恰好先执行的是输入流,而输出流还没有往外写数据,read方法是一个阻塞式方法,这时候就会死锁。

public static void main(String[] args) throws IOException {

    PipedInputStream input = new PipedInputStream();
    PipedOutputStream output = new PipedOutputStream();

    input.connect(output);

    new Thread(new Input(input)).start();
    new Thread(new Output(output)).start();

}

//管道输入流线程
class Input implements Runnable{

    private PipedInputStream in;
    Input(PipedInputStream in){
        this.in = in;
    }
    public void run(){
        try {
            byte[] buf = new byte[1024];
            int len = in.read(buf);

            String s = new String(buf,0,len);

            System.out.println("s="+s);
            in.close();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

//管道输出流线程
class Output implements Runnable{
    private PipedOutputStream out;
    Output(PipedOutputStream out){
        this.out = out;
    }
    public void run(){
        try {
            Thread.sleep(5000);
            out.write("hi,管道来了!".getBytes());
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

输出结果:

hi,管道来了!

DateInputStream和DateOutputStream

DataInputStream和DataOutputStream都是Java中输入输出流的装饰类。数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。
这两个流对象也要对应着使用。
这两个流对象中的writeInt、readInt等方法其实在RandomAccessFile类和ObjectInputStream、ObjectOutputStream类中也都存在,但是这些方法的使用场景不同,一个是专门用来随机访问文件的,一个是专门用来对对象序列化的。
如果只想操作Java的基本数据类型,就可以使用DateInputStream和DateOutputStream。

DataOutputStream dos = new DataOutputStream(new FileOutputStream("G:\\datastreamdemo.txt"));
dos.writeUTF("你好");
dos.close();

DataInputStream dis = new DataInputStream(new FileInputStream("G:\\datastreamdemo.txt"));
String str = dis.readUTF();
System.out.println(str);
dis.close();

输出结果:

你好

ByteArrayInputStream和ByteArrayOutputStream

这两个是操作字节数组的流对象,他们的源和目的都是内存,所以不需要调用系统的底层资源,不需要关流。
ByteArrayOutputStream:
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
ByteArrayInputStream :
包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。

ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write("abcd".getBytes());

byte[] buf = bos.toByteArray();
ByteArrayInputStream bis = new ByteArrayInputStream(buf);

int ch = 0;
while((ch = bis.read())!=-1){
    System.out.println(ch);
}

输出结果:

97
98
99
100
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值