一、输入/输出流

1.流:不同类型的输入、输出源    数据流:输入或输出的数据

   Java数据流的所有接口和类都是在java.io包中定义的,因此应在程序开头加入

   import java.io.*

2.流的分类:

  (1)从流的流动方向来看,可以将IO流分为输入流和输出流

          输入流:数据信息从某个地方流向程序中

          输出流:数据信息从程序中发送到某个目的地

  (2)从流的数据处理单位来看,可以将IO流分为字节流和字符流

          字节流:以字节方式处理的二进制数据

          字符流:以字符方式处理的数据流(Java使用Unicode字符集,存放一个字符需要两个字节)

  (3)从流的功能来看,可以将IO流分为节点流和过滤流

          节点流:程序中用于直接操作目标设备所对应的IO流

          过滤流(也称为包装流):通过一个间接IO流去调用相应的节点流,以更加灵活方便地读/写各种类型的数据

二、字节流和字符流

1.java.io包中有两大继承体系:

   一类是以字节为单位处理数据的Stream,它们的命名方式都是***Stream

   另一类是以字符为单位处理数据的Reader和Writer,它们的命名方式都是*Reader或*Writer

三、文件及文件流

1.Java中IO流操作的基本流程

   使用File类定位一个文件->通过字节流或字符流的子类进行流对象的实例化

   ->进行读写操作->关闭字节或字符流

2.Java字节流和字符流的区别:在字符流进行操作时会使用到缓冲区,字节流操作不会使用缓冲区

import java.io.*;
class FileStream {
    public static void main(String[] args) {
        try {
            File inFile = new File("file1.txt");
            File outFile = new File("file2.txt");
            FileReader fis = new FileReader(inFile);
            FileWriter fos = new FileWriter(outFile);
            int c;
            while ((c = fis.read()) != -1) {
                fos.write(c);
            }
            fis.close();
            //fos.close();
            fos.flush();    //若无此语句,file2.txt文件为空
         } catch(FileNotFoundException e) {
            System.out.println("FileStream: " + e);
        } catch (IOException e) {
            System.out.println("FileStream: " + e);
        }
    }
}

   flush();

语句强制缓冲区输出,若使用FileInputStream字节流操作则无该技术

   字符流在缓冲区未满前先存放在缓冲区中,除非使用flush() 或 close()强制输出

3.在Windows系统下文件名称分隔符使用"/"或转义字符"\\"

   而Linux中使用"/"

   为了保持Java系统很好的可移植性,在操作文件时最好使用File.separator

   例:File f = new FIle("D:" + File.seperator + "test.txt");

   一般使用"./"表示当前目录,"../"表示当前目录的父目录

4.随机文件读写:RandomAccessFile类

   访问模式值及含义

mode值含义"r"以只读方式打开"rw"打开以便读取和写入,如果该文件不存在,则尝试创建该文件"rws"同步读/写,任何写操作的内容都被直接写入物理文件,包括文件内容和文件属性"rwd"同步读/写,任何写操作的内容都被直接写入物理文件,不包括文件属性

   "rw"模式时,仅当RandomAccessFile类对象执行close方法时才将更新内容写入文件

   而"rws"和"rwd"模式是同步读/写,因此可以保证数据实时更新

   RandomAccessFile类一般方法

方法名称含义

public long getFilePointer() throws IOException返回当前的文件指针位置 public void seek(long pos) throws IOException移动文件指针到pos位置public int skipBytes(int n) throws IOException文件指针向后移动n个字节,n为负数时指针不移动public int read(byte[] b) throws IOException将最多b.length个字节读入数组bpublic void write(byte[] b) throws IOException将b.length个字节从指定数组b写入到文件public final byte readByte() throws IOException读取一个字节public final void writeByte(int v) throws IOException将(byte) v写入文件public final String readLine() throws IOException读取一行public void close() throws IOException关闭流

四、过滤流

1.缓冲流

   为提高IO流的读取效率,Java提供了具有缓冲功能的流类,使用这些流类时,会创建一个内部的缓冲区。

   在读字节或字符时,先从数据源读取到的数据填充到缓冲区,然后再返回

   在写字节或字符时,先把写入的数据填充到内部缓冲区,然后一次性写入到目标数据源中,从而提高了I/O流的读取效率

   缓冲流包括:

   字节流:BufferedInputStream    BufferedOutputStream

   字符流:BufferedReader    BufferedWriter

   注意:缓冲区的大小默认为32字节大小,一般缓冲区的大小为内存页或磁盘块等的整数倍

            只有缓冲区满时,才会将数据真正送到输出流,但可以使用flush()方法人为地将尚未填满的缓冲区中的数据送出

2.数据流:DataInputStream 和 DataOutputStream

   作用:允许程序按与机器无关的风格读取Java原始数据,即不关心一个数值应当是多少字节

例:

import java.io.IOException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class DataStreamDemo {
    public static void main(String[] args) throws IOException {
        //write the data
        FileOutputStream fos = new FileOutputStream("data.txt");
        DataOutputStream dos = new DataOutputStream(fos);
        dos.writeBoolean(true);
        dos.writeByte((byte)123);
        dos.writeChar('J');
        dos.writeDouble(3.1415926);
        dos.writeFloat(2.7182f);
        dos.writeInt(1234567);
        dos.writeLong(998877665544332211L);
        dos.writeShort((short)11223);
        dos.close();
        //read the data
        FileInputStream fis = new FileInputStream("data.txt");
        DataInputStream dis = new DataInputStream(fis);
        System.out.println(dis.readBoolean());
        System.out.println(dis.readByte());
        System.out.println(dis.readChar());
        System.out.println(dis.readDouble());
        System.out.println(dis.readFloat());
        System.out.println(dis.readInt());
        System.out.println(dis.readLong());
        System.out.println(dis.readShort());
        dis.close();
    }
}


3.打印流:使输出信息更方便的类,主要包含PrintStream和PrintWriter

   包含输出方法print  println  printf

五、标准流

1.语言包java.lang中的System类管理标准IO流和错误流。System是final类,System类中定义了以下三个静态变量成员变量

   public static final InputStream in:标准输入,一般是键盘

   public static final PrintStream out:标准输出,一般是显示器

   public static final PrintStream err:错误信息输出,通常是显示器

例:

public class SystemDemo {
    public static void main(String[] args) {
        try {
            byte bArray[] = new byte[20];
            String str;
            System.out.print("Input:");
            System.in.read(bArray);
            str = new String(bArray, 0);
            System.out.print("Output:");
            System.out.println(str.trim());
        }
        catch (IOException ioe) {
            System.err.println(ioe.toStirng());
        }
    }
}



六、对象流

1.对象的序列化:把一个对象变为二进制的数据流的方法,可以实现对象的传输和存储

   只有实现 java.io.Serializable 接口的类才能被序列化

   java.io.Serializable接口中没有任何方法,一个类声明实现java.io.Serializable只是表明该类加入对象序列化协议

2.对象流

   类ObjectOutputStream和ObjectInputStream继承了接口ObjectOutput和ObjectInput

   将数据流功能扩展到可以读/写对象,方法:readObject(); 和 writeObject();

   注:通常,只要某个类实现了Serializable接口,那么该类的类对象中的所有属性都会被串行化

         对于一些敏感信息,只需在不串行化的属性上用 transient 修饰即可

七、Scanner类

1.Scanner类处于java.util包中,使用时需要import引入

   Scanner类常用方法

方法名称含义

public Scanner(InputStream source)从指定字节输入流中接收内容public Scanner(File source) throws FileNotFoundException从文件中接收内容public boolean hasNextInt()判断输入的是否是整数public boolean hasNextDouble()判断输入的是否是小数public String next()接收数据public int nextInt()接收整数public float nextDOuble()接收小数public Scanner useDelimiter(String pattern)设置分隔符

例:

Scanner reader = new Scanner(System.in);
while(reader.hasNextDouble()) {
    double x = reader.nextDouble();
}

八、流的选择

1.步骤:

  (1)选择合适的节点流:按照链接的数据源种类进行选择

                                     读写文件应该使用文件流,读写字节数组应该使用字节数组流

  (2)选择合适方向的流:读:输入流/写:输出流

  (3)选择字节流或字符流:所有的文件在传输时都是以字节的方式进行的(包括图片等)

                                        而字符时只有在内存中才会形成的,因此字节流使用较广泛

  (4)包装流:可以选择多个,例如:

                      如果需要读/写格式化数据,选择DataInputStream/DataOutputStream

                      如果需要提高读/写的效率,选择BufferedReader/BufferedWriter