Java学习笔记-7.Java IO流
一、输入/输出流
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类一般方法
注意:类中有readLine方法,但不存在writeLine方法
方法名称 含义 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个字节读入数组b public 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