【转】输入/输出流 - 全面掌握IO

File类:

程序中操作文件和目录都可以使用File类来完成即不管是文件还是目录都是使用File类来操作的,File能新建,删除,重命名文件和目录,但File不能访问文件内容本身,如果需要访问文件本身,则需要使用输入/输出流,该类是位于java.io包下的

输入与输出IO:

输入流:只能从中读取数据,而不能向其中写入数据(由InputStream(字节流)和Reader(字符流)作为基类)

输出流:只能向其写入数据,而不能从中读取数据(由OutputStream(字节流)和Writer(字符流)作为基类)

java的io总共涉及40多个类,但都是从这四个抽象基类中派生出来的

InputStream最重要的三个read方法:

Reader中的read方法:

从这两个抽象类提供的方法就可以看出其实功能基本是一样的,只是操作的数据单元不一样而已

由于InputStream与Reader都是抽象类,是不能进行实例化的,我们只能用他们的子类来创建实例,它们分别提供了一个子类用于读取文件的输入流:FileInputStream和

FileReader,这两个子类都是节点流(与处理流相对)-----会直接与指定的文件关联而无包装。下面代码演示FileInputStream使用read(byte[] b):

package xidian.sl.io;

import java.io.FileInputStream;
import java.io.FileReader;

public class InputStreamTest {
    /**
     * 使用FileInputStream读取该类本身
     * */
    public static void FileInputStreamTest() throws Exception{
        FileInputStream fis = null;
        try{
        //创建字节输入流
        fis = new FileInputStream("src/xidian/sl/io/InputStreamTest.java");
        //创建一个长度为1024的字节数组来存取
        byte[] bbuf = new byte[1024];
        //用于保存实际读取的字节数
        int hasRead = 0;
        //使用循环来进行重复读取
        while((hasRead = fis.read(bbuf))> 0){
            //取出字节,将字节数组转化为字符串输出
            System.out.println(new String(bbuf, 0 , hasRead));
        }
        }finally{
            //关闭文件输入流
            fis.close();
        }
    }
    /**
     * 使用FileReader读取该类本身
     * */
    public static void FileReaderTest() throws Exception{
        FileReader fr = null;
        try{
        //创建字节输入流
        fr = new FileReader("src/xidian/sl/io/InputStreamTest.java");
        //创建一个长度为1024的字节数组来存取
        char[] bbuf = new char[40];
        //用于保存实际读取的字节数
        int hasRead = 0;
        //使用循环来进行重复读取
        while((hasRead = fr.read(bbuf))> 0){
            //取出字节,将字节数组转化为字符串输出
            System.out.println(new String(bbuf, 0 , hasRead));
        }
        }finally{
            //关闭文件输入流
            fr.close();
        }
    }
    public static void main(String[] args) throws Exception{
        InputStreamTest.FileInputStreamTest();
        InputStreamTest.FileReaderTest();
    }
}

可以看到这两个子类的使用方式可以说是完全一样的,不过这里要注意一个问题:字节流FileInputStream是根据字节来读取的,而一个中文是占两个字节的,如果包含很多中文的文件被字节流分多次进行读取,可能会造成乱码,因为有可能会导致刚好将一个中文分两次读取,这样就会乱码了,因此如果中文包含多的话还是使用字符流FileReader比较好,

在字节流与字符流之间选择的规律:如果需要进行输入/输出的内容是文本内容,则应该考虑使用字符流,如果需要进行输入/输出的是二进制内容,则应该考虑使用字节流,因为字节流的功能比字符流强大,计算机中所有的数据都是二进制的,而字节流可以处理所有的二进制文件;

OutputStream中最重要的write方法:

Writer中最重要的write方法:

Writer类中多了两个对字符串的操作类,因此如果是直接输出字符串就选用Writer会比较的方便;

与输入流一样,输出流也有两个文件操作的子类:FileOutputStream和FileWrite

package xidian.sl.io;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;

public class OutputStreamTest {
    /**
     * 使用字节流输出
     * */
    public static void FileOutputStreamTest() throws Exception{
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try{
            //创建字节输入流
            fis = new FileInputStream("src/xidian/sl/io/InputStreamTest.java");
            //创建字节输出流
            fos = new FileOutputStream("src/xidian/sl/io/Output.txt");
            byte[] bt = new byte[40];
            int hasRead = 0;
            //循环从输入流中读取数据
            while((hasRead = fis.read(bt))> 0){
                //每读取一个,即写入文件输出流,读了多少就写多少
                fos.write(bt, 0, hasRead);
            }

        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            /**
             * 流在关闭时会自动执行flash,将缓冲中的数据flush到物理节点中
             * 所以关闭时很重要的
             * */
            if(fis != null){
                fis.close();
            }
            if(fos != null){
                fos.close();
            }
        }
    }
    /**
     * 使用字符流输出字符串会显得比较的方便
     * */
    public static void FileWriteTest() throws Exception{
        FileWriter fw = null;
        try{
            //创建字节输出流
            fw = new FileWriter("src/xidian/sl/io/Output.txt");
            fw.write("温州医学院\r\n");
            fw.write("信息与管理专业\r\n");
            fw.write("温州医学院\r\n");
            fw.write("温州医学院\n");
            fw.write("温州医学院");
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(fw != null){
                fw.close();
            }
        }
    }
    public static void main(String[] args) throws Exception{
        OutputStreamTest.FileOutputStreamTest();
        OutputStreamTest.FileWriteTest();
    }
}

上面是节点流的基本使用,下面将了解处理流的使用,处理流会显得更加的高效

区分节点流于处理流的方法是:只要流的构造器的参数不是一个物理节点,而是已存在的流,那这个流一定是处理流,因为所有的节点流都是直接以物理io节点作为构造器的参数、

(如file)。

举例:PrintStream处理流来封装FileOutputStream节点流,进行输出,由于PrintStream类的输出功能非常的强大,因此我们需要输出文本内容一般都会将输出流包装成PrintStream后输出

package xidian.sl.io;

import java.io.FileOutputStream;
import java.io.PrintStream;

public class PrintStreamTest {
    public static void main(String[] args){
        PrintStream ps = null;
        try{
            //创建一个节点输出流
            FileOutputStream fos = new FileOutputStream("src/xidian/sl/io/Output.txt");
            //以PrintStream处理流来包装FileOutputStream节点流
            ps = new PrintStream(fos);
            ps.println("普通字符串");
            ps.println(new PrintStreamTest());
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            ps.close();
        }
    }
}

其实我们一直使用的标准输出System.out的类型都是PrintStream:

从上面的实例就可以看出将节点流封装成处理流很简单,只需调用处理流的构造方法来传入节点流就可以了;而且看到上面流的关闭只是关闭了处理流而未去关闭节点流,这样做是完全正确的,以后我们在关闭流的时候只需要关闭最上层的处理流即可;

字符流中有两个特别的流来处理字符串的:StringReader和StringWriter,

可以看到使用时实例化只需要传入一个字符串即可:例子:

package xidian.sl.io;

import java.io.StringReader;
import java.io.StringWriter;

public class StringNodeTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String src = "你是个神";
        StringReader sr = new StringReader(src);
        char[] chars = new char[40];
        int hasRead = 0;
        try{
            //采用循环的方式
            while((hasRead = sr.read(chars))>0){
                System.out.println(new String(chars, 0, hasRead));
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            sr.close();
        }
        //创建StringWriter
        StringWriter sw = new StringWriter(40);
        sw.write("你是一个大神");
        sw.write("你也是一个大神");
        System.out.println(sw.toString());

    }

}

io系统提供的两个转换流:InputStreamReader和OutputStreamWriter,都是将字节流转化为字符流

在java中是使用System.in来提供键盘输入的,但这个标准输入流是InputStream类的实例:

而前面讲到了当处理的是文本内容时,使用字符流会显得比较方便,正好键盘输入就是文本的操作,因此我们有必须将System.in转换为字符流:

package xidian.sl.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class KeyinTest {
    public static void main(String[] args){
        BufferedReader br = null;
        try{
            //将System.in对象转化为Reader对象
            InputStreamReader isr = new InputStreamReader(System.in);
            //将节点流包装为处理流
            br = new BufferedReader(isr);
            String buffer = null;
            //采用循环的方式一行一行读取
            while((buffer = br.readLine()) != null){
                System.out.print("输入的内容 = "+ buffer);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

PrintStream是有强大的输出功能,而BufferReader有强大的输入(即读取),因此在操作读取文本内容时尽可能将其转化为BufferReader,可以方便的使用readLine()方法

接下来最为强大的文件操作类RandomAccessFile来了,这个类既可以向文件输入数据,也可以输出数据,并且他与不同的流最大的不同就是“支持文件任意位置的访问”,即程序可以控制读取文件哪个位置的内容;

从构造方法上可以看出,除了提供一个文件或文件名外还需要提供一个String参数mode,mode规定了RandomAccessFile类访问文件的模式:

1. “r”:以只读的方式打开指定文件

2. “rw”:以读取,写入方式打开指定文件,并且文件不存在会自动进行创建

3.“rws”与“rwd”:与“rw”类似,只是要求文件内容或元数据的每个更新都同步写入底层存储设备

时间: 2024-10-13 12:22:29

【转】输入/输出流 - 全面掌握IO的相关文章

【java】缓冲字符字节输入输出流:java.io.BufferedReader、java.io.BufferedWriter、java.io.BufferedInputStream、java.io.BufferedOutputStream

BufferedReader最重要,因为有个方法public String readLine() 1 package System输入输出; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 7 public class Test { 8 public static void main(String[] args) throws IOExce

Java IO详解(三)------字节输入输出流

File 类的介绍:http://www.cnblogs.com/ysocean/p/6851878.html Java IO 流的分类介绍:http://www.cnblogs.com/ysocean/p/6854098.html 那么这篇博客我们讲的是字节输入输出流:InputStream.OutputSteam(下图红色长方形框内),红色椭圆框内是其典型实现(FileInputSteam.FileOutStream)  1.字节输出流:OutputStream public abstrac

【转载】Java输入输出流-IO

转自:http://blog.csdn.net/hguisu/article/details/7418161 1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读写数据的标准方法.任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法. Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核

Java中IO流,输入输出流概述与总结

总结的很粗糙,以后时间富裕了好好修改一下. 1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中.其中, 所有输入流类都是抽象类InputStream(字节输入流),或者抽象类Reader(字符输入流)的子类: 而所有输出流都是抽象类OutputStream(字节输出流)或者Writer(字符输出流)的子类. [首先需要明白的是:流是干什么的???(为了永久性的保存数据)   根据数据流向的不同分为输入流和输出流:   根据处理数据类型的不同分为字符流和字

java.IO输入输出流:过滤流:buffer流和data流

java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入:缓冲流为什么比普通的文件字节流效率高? 不带缓冲的操作,每读一个字节就要写入一个字节. 由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低. 带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里. 等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多! 这就是两者的区别

C++笔记(9):IO输入输出流

输入输出流 C++的输入输出流是IO系统向用户提供一个统一的接口,它隔离了具体的设备差异.包括标准输入输出流和文件流.标准输入输出流 istream是输入流类,cin就是istream类型的对象.ostream是输出流类,cout是ostream类型的对象. 在C++中允许用户重载运算符"<<"和">>",实现对象的输入和输出. 重载这二个运算符时,在对象所在的类中,将重载这二个运算符的函数说明该类的友元函数. C++在头文件fstream.

《三》Java IO 字节输入输出流

那么这篇博客我们讲的是字节输入输出流:InputStream.OutputSteam(下图红色长方形框内),红色椭圆框内是其典型实现(FileInputSteam.FileOutStream)    1.字节输出流:OutputStream ? 1 2 3 public abstract class OutputStream extends Object implements Closeable, Flushable 这个抽象类是表示字节输出流的所有类的超类. 输出流接收输出字节并将其发送到某个

Java IO输入/输出流的套接

缓冲字符流BufferedInputStream / BufferedOutputStream 文件操作流 InputStream / OutputStream java 输入输出流的套接,测试一下流链的速度 因为节点流在程序中并不是很常用,一般常通过过滤流将多个流套接在一起,利用各流的特性共同处理数据,套接的多个流构成了一个流链: 我们来分析他们的运行时间.(因为在不同的系统(maxOX,Linux,WIN(32/64))上运行的时间可能都不相同)我截取了几段时间来进行对比. 1.缓冲字符流B

java开发知识IO知识之输入输出流以及文件

java开发知识IO知识之输入输出流以及文件 一丶流概述 流十一组有序的数据序列.根据操作的类型,可以分为输入流跟输出流两种. IO(input/output)输入/输出流提供了一条通道程序.可以使用这条通道把源的字节序列送到目的地 简单来说. 就是操作二进制. 二进制提供了读写功能. 写就是输出. 读就是输入. 输入输出流图示: 输入流讲解 InputStream类. 1. 输入流以及类层次结构 输入流就是从"文件" 读取到内存. 这个文件是抽象的.意思就是不管什么内容从硬盘也好.任