(一)原理
-
在Java程序中,对于数据的输入输出操作以流(Stream)方式进行
-
J2SDK提供了各种各样的“流” 类,用以获取不同种类的数据:程序中通过标准的方法输入或输出数据
-
io包里面定义了所有的流,所以一说流指的就是io包里面的
(二)字节流
-
最原始的一个流,读出来的数据就是010101这种最底层的数据表示形式,只不过它是按 照字节来读的,一个字节(Byte)是8位(bit)读的时候不是一个位一个位的来读,而是一个字节一个字节来读
-
用一根管道一端插进文件里,一端插进程序里面,然后开始读数据,
-
如果站在文件的角度上,这叫输出。
-
如果站在程序的角度上,这叫输入。
-
InputStream(输入流)
-
我们看到的具体的某一些管道,凡是以InputStream结尾的管道,都是以字节的形式向我们的程序输入数据
-
继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8bit)
基本方法
-
读取一个字节并以整数的形式返回(0~255) ,如果返回-1就说明已经到了输入流的末尾
int read() throws IOException
-
读取一系列字节并存储到一个数组buffer,返回实际读取的字节数,如果读取前已到输入流的末尾,则返回-1
int read(byte[] buffer) throws IOException
-
读取length个字节并存储到一个字节数组buffer,从length位置开始,返回实际读取的字节数
-
如果读取前以到输入流的末尾返回-1
int read(byte[] buffer,int offset,int length) throws IOException
-
关闭流释放内存资源
void close() throws IOException
-
跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException
案例
import java.io.*;
class TestFileInputStream {
public static void main(String args[]) {
int b = 0; //使用变量b来装调用read()方法时返回的整数
FileInputStream in = null;
//使用FileInputStream流来读取有中文的内容时,读出来的是乱码,因为使用 InputStream流里面的read()方法读取内容时是一个字节一个字节地读取的,而一个汉字是占用两个 字节的,所以读取出来的汉字无法正确显示。
//FileReader in = null;
//使用FileReader流来读取内容时,中英文都可以正确显示,因为Reader流里面的 read()方法是一个字符一个字符地读取的,这样每次读取出来的都是一个完整的汉字,这样就可以正确 显示了。
try {
in = new FileInputStream("E:\\JavaSE\\jy.txt");
}catch (FileNotFoundException e) {
System.out.println("系统找不到指定文件!");
System.exit(-1); //系统非正常退出
}
long num = 0; //使用变量num来记录读取到的字符数
//调用read()方法时会抛异常,所以需要捕获异常
try {
while ((b = in.read()) != -1) {
//调用int read() throws Exception方法时,返回的是一个int类型的整数
//循环结束的条件就是返回一个值-1,表示此时已经读取到文件的末尾了。
System.out.print((char) b);
//如果没有使用“(char)b”进行转换,那么直接打印出来的b就是数字,而不是英文和中文了
// “char(b)”把使用数字表示的汉字和英文字母转换成字符输入
num++; }
in.close();// 关闭输入流
System.out.println();
System.out.println("总共读取了" + num + "个字节的文件");
}catch (IOException e1) {
System.out.println("文件读取错误!");
}
}
}
OutputStream(输出流)
继承自OutputStream的流是用于程序中输出数据,且数据的单位为字节(8bit)
基本方法
-
向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
-
将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
-
将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b,int off,int len) throws IOException
-
关闭流释放内存资源
void close() throws IOException
-
将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
案例
import java.io.*;
public class TestFileOutputStream {
public static void main(String args[]) {
int b = 0;
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("E:\\JavaSE\\jy.txt");
out = new FileOutputStream("E:\\JavaSE\\jy2.txt");
//指明要写入数据的文件,如果指定的路径中不存在这样的文件,则系统会自动创建一个
while ((b = in.read()) != -1) {
out.write(b);
//调用write(int c)方法把读取到的字符全部写入到指定文件中去
System.out.print((char) b);
}
in.close();
out.close();
} catch (FileNotFoundException e) {
System.out.println("文件读取失败");
System.exit(-1); //非正常退出
} catch (IOException e1) {
System.out.println("文件复制失败!");
System.exit(-1);
}
System.out.println("---已写入在jy2.txt里面");
}
}
(三)字符流
字符流是一个字符一个字符地往外读取数据,一个字符是2个字节
Reader
-
读取一个字节并以整数的形式返回(0~255),如果返回-1就说明已经到了输入流的末尾
int read() throws IOException
-
读取一系列字节并存储到一个数组buffer,返回实际读取的字节数,如果读取前已到输入流的末尾,则返回-1
int read(byte[] buffer) throws IOException
-
读取length个字节并存储到一个字节数组buffer,从length位置开始,返回实际读取的字节数
-
如果读取前以到输入流的末尾返回-1.
int read(byte[] buffer,int offset,int length) throws IOException
-
关闭流释放内存资源
int read(byte[] buffer,int offset,int length) throws IOException
-
跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException
Writer
- 向输出流中写入一个字节数据,该字节数据为参数b的低16位
void write(int b) throws IOException
- 将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
- 将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b,int off,int len) throws IOException
- 关闭流释放内存资源
void close() throws IOException
- 将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
(四)节点流
-
节点流就是一根管道直接插到数据源上面,直接读数据源里面的数据,或者是直接往数据源里面写入数据
-
典型的节点流是文件流:文件的字节输入流(FileInputStream),文件的字节输出(FileOutputStream),文件的字符输入流(FileReader),文件的字符输出流(FileWriter)。
类型 | 字符流 | 字节流 |
---|---|---|
File(文件) | FileReader、FileWriter | FileInputStream、FileOutputStream |
Memory Array | CharArrayReader、 CharArrayWriter | ByteArrayInputStream、ByteArrayOutputStream |
Memory String | StringReader、StringWriter | - |
Pipe(管道) | PipedReader、PipedWriter | PipedInputStream、PipedOutputStream |
(五)处理流
处理流是包在别的流上面的流,相当于是包到别的管道上面的管道
处理类型 | 字符流 | 字节流 |
---|---|---|
Buffffering (缓冲流) | BufffferedReader、BufffferedWriter | BufffferedInputStream、 BufffferedOutputStream |
Filtering | FilterReader、FilterWriter | FilterInputStream, FilterOutputStream |
Converting between bytes and chaacter | InputStreamReader、OutputStreamWriter | - |
Object Serialization | - | ObjectInputStream、 ObjectOutputStream |
Data conversion | - | DataInputStream、 DataOutputStream |
Counting | LineNumberReader | LineNumberInputStream |
Peeking ahead | PusbackReader | PushbackInputStream |
Printing | PrintWriter | PrintStream |
缓冲流
缓冲流要”套接“在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法。J2SDK提供了四种缓冲流,常用构造方法如下:
BufferedReader(Reader in)
BufferedReader(Reader in,int sz) //sz 为自定义缓冲区的大小
BufferedWriter(Writer out)
BufferedWriter(Writer out,int sz)
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
BufferedOutputStream(InputStream in)
BufferedOutputStream(InputStream in,int size)
-
缓冲输入流支持其父类的mark和reset方法
-
BufffferedReader提供了readLine方法用于读取一行字符串
-
BufffferedWriter提供了newLine用于写入一个行分隔符
-
对于输出的缓冲流,写出的数据会现在内存中缓存,使用flflush方法将会使内存中的数据立刻写出
转换流
-
InputStreamReader 和 OutputStreamWriter 用于字节数据到字符数据之间的转换
-
InputStreamReader 需要和 InputStream “套接”
-
OutputStreamWriter 需要和 OutputStream “套接”
-
转换流在构造时可以指定其编码集合
InputStream isr = new InputStreamReader(System.in,"ISO8859-1")
数据流
-
DataInputStream 和 DataOutputStream 分别继承自InputStream 和 OutputStream , 它属于处理流,需要分别“套接”在InputStream 和 OutputStream类型的节点流上。
-
DataInputStream 和 DataOutputStream 提供了可以存取与机器无关的Java原始类型数据(int,double等)的方法
-
DataInputStream 和 DataOutputStream 的构造方法
DataInputStream(InputStream in)
DataOutputStream(OutputStream out)
打印流
-
PrintWriter 和 PrintStream 都属于输出流,分别针对与字符和字节
-
PrintWriter 和 PrintStream 提供了重载的print
-
Println方法用于多种数据类型的输出
-
PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
-
PrintWriter 和 PrintStream有自动flflush功能
PrintWriter(Writer out)
PrintWriter(Writer out,boolean autoFlush)
PrintWriter(OutputStream out)
PrintWriter(OutputStream out,boolean autoFlush)
PrintStream(OutputStream out)
PrintStream(OutputStream out,boolean autoFlush)
对象流
直接将Object 写入或读出
-
transient关键字——transient:透明的,用它来修饰的成员变量在序列化的时候不予考虑,就是当成不存在
-
serializable接口
-
externaliazble接口