IO流的典型使用方式

IO流的典型使用方式

《Java编程思想》(第4版)18.6节学习笔记

缓冲输入文件

FileReader可打开文件进行字符输入,为了对文件进行缓冲以提高速度,可用BufferedReader进行包装。BufferedReader提供readLine方法,返回null时就达到了文件末尾。

package com.cas.io;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedInputFile {
    public static String read(String filename) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(filename));
        String s;
        StringBuilder strBuilder = new StringBuilder();
        while ((s = reader.readLine()) != null) {
            strBuilder.append(s + "\n");
        }
        reader.close();
        return strBuilder.toString();
    }

    public static void main(String[] args) throws IOException {
        System.out.println(read("test.txt"));
    }
}

从内存输入

示例:使用以上的BufferedInputFile读取文件内容到字符串,String结果用来创建一个StringReader,然后调用read()每次读取一个字符并打印到控制台。

package com.cas.io;

import java.io.IOException;
import java.io.StringReader;

public class MemoryInput {
    public static void main(String[] args) throws IOException {
        StringReader reader = new StringReader(BufferedInputFile.read("test.txt"));
        int c;
        //read以int形式返回下一字节,打印时要转为char类型
        while ((c = reader.read()) != -1) {
            System.out.print(((char) c));
        }
    }
}

格式化的内存输入

要读取格式化数据,可以使用面向字节的I/O类DataInputStream。

package com.cas.io;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;

public class FormattedMemoryInput {
    public static void main(String[] args) throws IOException {
        try {
            DataInputStream in = new DataInputStream(new ByteArrayInputStream(
                    BufferedInputFile.read("test.txt").getBytes()));
            while (true) {
                System.out.print((char) in.readByte());
            }
        } catch (EOFException e) {
            System.err.println("End of Stream");
        }
    }
}

输出示例:

Hello,
World!
End of Stream

如果从DataInputStream一次一个字节地读取字符,那么任何字节的值都是合法的结果,因此返回值不能用来检测输入是否结束,此时可用available()方法查看还有多少可供存取的字符。

package com.cas.io;

import java.io.*;

public class TestEOF {
    public static void main(String[] args) throws IOException {
        DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("test.txt")));
        while (in.available() != 0) {
            System.out.print(((char) in.readByte()));
        }
    }
}

注意,available()的工作方式会随着所读取的媒介类型的不同而有所不同,字面意思是“在没有阻塞的情况下所能读取的字节数”。对于文件,意味着整个文件;但对于不同类型的流,可能不是这样,因此要谨慎使用。

基本的文件输出

FileWriter指定文件,BufferedWriter用以缓冲输出,PrintWriter提供格式化机制。

package com.cas.io;

import java.io.*;

public class BasicFileOutput {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new StringReader(BufferedInputFile.read("test.txt")));
        PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter("test_out.txt")));
        int lineCount = 1;
        String line;
        while ((line = reader.readLine()) != null) {
            writer.println(lineCount++ + ": " + line);
        }
        // 刷新清空缓冲区内容
        writer.close();
        System.out.println(BufferedInputFile.read("test_out.txt"));
    }
}

文本文件输出的快捷方式

Java SE5在PrintWriter中添加了一个辅助构造器,可以简化文本文件写出的装饰工作。

// PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter("test_out.txt")));
PrintWriter writer = new PrintWriter("test_out.txt");

存储和恢复数据

为了输出可供另一个流恢复的数据(如Double),需要用DataOutputStream写入数据,并用DataInputStream恢复数据,这些流可以是任何形式。

如果使用DataOutputStream写入数据,Java保证可以使用DataInputStream准确的读取数据—无论读和写数据的平台多么不同(XML是在不同计算平台之间移动数据的另一种方式)。

package com.cas.io;

import java.io.*;

public class StoringAndRecoveringData {
    public static void main(String[] args) throws IOException {
        //写出数据
        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data.txt")));
        out.writeDouble(Math.sqrt(2));
        out.writeUTF("根号2的值");
        out.close();
        //读取数据
        DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("data.txt")));
        System.out.println(in.readDouble());
        System.out.println(in.readUTF());
    }
}

注意,writeUTF和readUTF使用的是适合于Java的UTF-8变体。

读写随机访问文件

RandomAccessFIle实现了DataInput和DataOutput接口,类似于DataInputStream和DataOutputStream的组合。另外,利用seek()可以在文件中到处移动,并修改文件中的某个值。

使用RandomAccessFIle时,必须知道文件排版,以便正确地操作它。RandomAccessFIle拥有读取基本类型和UTF-8字符串的各种具体方法。

示例代码:

package com.cas.io;

import java.io.IOException;
import java.io.RandomAccessFile;

public class UsingRandomAccessFile {
    static String file = "test.dat";

    /**
     * 读取并显示3个Double值
     */
    static void display() throws IOException {
        // 只读方式打开
        RandomAccessFile rf = new RandomAccessFile(file, "r");
        for (int i = 0; i < 3; i++) {
            System.out.println("Value " + i + ": " + rf.readDouble());
        }
        System.out.println(rf.readUTF());
        rf.close();
    }

    public static void main(String[] args) throws IOException {
        // 读写方式打开
        RandomAccessFile rf = new RandomAccessFile(file, "rw");
        for (int i = 0; i < 3; i++) {
            rf.writeDouble(i * 1.2);
        }
        rf.writeUTF("The end of the file");
        rf.close();
        display();
        // 将2号位的Double值增至10倍
        rf = new RandomAccessFile(file, "rw");
        rf.seek(2 * 8);
        double tmp = rf.readDouble();
        rf.seek(2 * 8);
        rf.writeDouble(10 * tmp);
        rf.close();
        display();
    }
}

输出结果:

Value 0: 0.0
Value 1: 1.2
Value 2: 2.4
The end of the file
Value 0: 0.0
Value 1: 1.2
Value 2: 24.0
The end of the file

管道流

PipedInputStream、PipedOutputStream、PipedReader和PipedWriter属于管道流,用于多线程中任务之间的通信。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值