一、输入/输出流
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