理解IO流
标准输入输出数据流:java.lang.System:
java.lang.System;
public final class System extends Object{
static PrintStream err;//标准错误流(输出)
static InputStream in;//标准输入流(键盘输入流)
static PrintStream out;//标准输出流(显示器输出流)
}
System类不能创建对象,只能直接使用它的三个静态成员
main方法被执行时就会自动生成上面的三个对象
一、标准输出流(System.out)
System.out向标准输出设备输出数据,数据类型为PrintStream
void print(参数);
void println(参数);
print(Object)和println(Object)方法在运行时会自动调用参数Object和toString方法。
二、标准输入流(System.in)
System.in从标准输入设备上获取输入,数据类型是InputStream
int read();//返回ASCII码,若返回-1表示没有读取到任何字符表示没有读取到任何字节
int read(byte[] b);//读入多个字符节到缓冲区b中,返回读取字节数
三、标准错误流(System.err)
System.err输出标准错误,数据类型为PrintStream
四、java.IO层次体系结构
五个类:File、OutputStream、InputStream、Writer、Reader
一个接口:Serializable
-
流式部分——IO的主体部分
-
非流式部分——辅助流式工作的类。如:File类、RandomAccessFile类和FileDescriptor等类;
-
其他类——与文件读取安全相关的类,如:SerializablePermission类;以及与本地操作系统相关的文件系统的类。如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。
主要的类如下:
-
File(文件特征与管理):用于文件或者目录的描述信息
-
InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类,定义了所有输入流的共同特征。
-
OutputStream(二进制格式操作):抽象类,基于字节的输出操作,是所有输出流的父类,定义了所有输出流的共同特征。
Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示
-
Reader(文件格式操作):抽象类,基于字符的输入操作
-
Writer(文件格式操作):抽象类,基于字符的输出操作
-
RandomAccessFile(随机文件操作):从文件的任意位置进行存取操作
存取:输入输出操作
1、非流式文件类——File类
在java.io包中,File类提供了描述文件和目录的操作与管理办法,专门用来管理文件和目录,不提供输入输出。不是InputStream、OutputStream、Writer、Reader的子类
作用:主要用于命名文件,查询文件属性和处理文件目录
public class File extends Object implements Serializable,Comarable{}
构造函数
File(String pathname)
File f1 = new File("test1.txt");//f1在当前目录下被创建
File(String parent , String child)
File f2 = new File("D:\\dir1","test2.txt");
//d:\\dir1存在的情况下,在dir1下创建一个test.2txt
File(File parent , String child)
File f3 = new File("\\dir2");
File f4 = new(f4,"test3.txt");//在dir2下创建一个test3.txt文件
mkdir()创建文件对象指定的目录(单层目录)
createNewFile()创建文件对象指定的文件
list()返回目录中所有文件名字符串
2、Java.IO流类库
2.1 IO流的四个基本类
java.io包中包含了流式I/O所需要的所有类。
基本数据流
输入/输出 | 字节流 | 字符流 |
---|---|---|
输出流 | InputStream | Reader |
输入流 | OutputStream | Writer |
JDK1.4版本开始引入了新I/O类库,位于java.nio包中,新I/O类库利用通道和缓冲区来提高I/O操作的效率。
2.2 IO流的具体分类
一、按I/O类型来总体分类:
-
Memory
1)从/向内存数组读写数据: CharArrayReader、 CharArrayWriter、ByteArrayInputStream、ByteArrayOutputStream
2)从/向内存字符串读写数据 StringReader、StringWriter、StringBufferInputStream -
Pipe管道
实现管道的输入和输出(进程间通信): PipedReader、PipedWriter、PipedInputStream、PipedOutputStream
-
File 文件流
对文件进行读、写操作 :FileReader、FileWriter、FileInputStream、FileOutputStream
-
ObjectSerialization
对象输入、输出 :ObjectInputStream、ObjectOutputStream
-
DataConversion数据流
按基本数据类型读、写(处理的数据是Java的基本类型(如布尔型,字节,整数和浮点数)):DataInputStream、DataOutputStream
-
Printing
包含方便的打印方法 :PrintWriter、PrintStream
-
Buffering缓冲
在读入或写出时,对数据进行缓存,以减少I/O的次数:BufferedReader、BufferedWriter、BufferedInputStream、BufferedOutputStream
-
Filtering 滤流
在数据进行读或写时进行过滤:FilterReader、FilterWriter、FilterInputStream、FilterOutputStream过
-
Concatenation合并输入
把多个输入流连接成一个输入流 :SequenceInputStream
-
Counting计数
在读入数据时对行记数 :LineNumberReader、LineNumberInputStream
-
Peeking Ahead
通过缓存机制,进行预读 :PushbackReader、PushbackInputStream
-
Converting between Bytes and Characters
按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换(Stream到Reader,Writer的转换类):InputStreamReader、OutputStreamWriter
二、按数据来源(去向)分类
- File(文件): FileInputStream、FileOutputStream、FileReader、FileWriter
- byte[]:ByteArrayInputStream、ByteArrayOutputStream
- Char[]:CharArrayReader,CharArrayWriter
- String:StringBufferInputStream、StringBufferOutputStream,StringReader,StringWriter
- 网络数据流:InputStream、OutputStream、Reader、Writer
五、字节流InputStream和OutputStream
1、InputStream抽象类
InputStream类提供了3种重载的read方法
-
public abstract int read();读取一个字节的数据,返回值类型为int,若返回-1则表示没有读取到任何 字节
-
public int read(byte b[]);读取b.length个字节的数据放在b数组中,返回值是读取的字节数
-
public int read(byte b[],int off,int len);从输入流中最多读取len个字节的数据,放在偏移量为off的数组b中
-
public int available();返回输入流中可以读取的字节数,这个方法必须由继承InputStream类的子类调用才有用
-
public long skip(long n);跳过输入流中的几个字节,返回值是忽略的字节数
-
public int close();关闭已打开的流
-
主要子类:
1) FileInputStream把一个文件作为InputStream,实现对文件的读取操作
2) ByteArrayInputStream:把内存中的一个缓冲区作为InputStream使用
3) StringBufferInputStream:把一个String对象作为InputStream
4) PipedInputStream:实现了pipe的概念,主要在线程中使用
5) SequenceInputStream:把多个InputStream合并为一个InputStream
2、OutputStream抽象类
OutputStream提供了3个write方法
-
public abstract void write(int b);先将int转化为byte类型,把低字节写入到输出流中。
-
public void write(byte b[]);将数组b中的字节写到输出流
-
public void write(byte b[],int off,int len);将数组b中从偏移量off开始的额len个字节写入到输出流中
-
public void flush();将数据缓冲区中的数据全部输出,并清空缓冲区
-
public void close();关闭已打开的流
-
主要子类:
1)ByteArrayOutputStream:把信息存入内存中的一个缓冲区中
2)FileOutputStream:把信息存入文件中
3)PipedOutputStream:实现了pipe的概念,主要在线程中使用
4)SequenceOutputStream:把多个OutputStream合并为一个OutputStream
流程结束的判断:方法read()的返回值为-1时,readLine()的返回值为null时。
3、文件输入输出流FileInputStream/FileOutputStream
3.1 文件输入流FileInputStream类
FileInputStream使用read()方法一次读一个字节返回值类型为int;使用read()方法读入一个byte数组,byte数组通常扮演承接数据的中间角色。
作用:打开文件,把文件中数据读到内存中
//使用方法一
File fi = new File("d:/abc.txt");
FileInputStream in = new FileInputStream(fi);
//使用方法2
FileInputStream in = new FileInputStream("d:/abc.txt");
将InputFromFile.java的程序的内容显示在显示器上
import java.io.IOException;
import java.io.FileInputStream;
public class TestFile{
public static void main(String[] args) throws IOException{
try{
FileInputStream rf = new FileInputStream("InputFromFile.java");
int n = 512;
byte[] buffer= new byte[n];
while((rf.read(buffer,0,n)!=-1)&&n>0){
System.out.println(new String(buffer));
}
System.out.println();
rf.close();
}catch(IOException IOe){
System.out.println(IOe.toString());
}
}
}
3.2文件输出流FileOutputStream类
作用:将数据从内存区读入文件
一个表示文件名的字符串也可以是File或FileDescriptor对象
//创建的第一种方法
File fi = new File("d:/abc.txt");
FileOutputStream out = new FileOutputStream(fi);
//创建的第二种方法
FileOutputStream out = new FileOutputStream("d:/abc.txt");
//方式3:构造函数将FileDescriptor()对象作为参数
FileDescriptor fd = new FileDescriptor();
FileOutputStream out = new FileOutputStream(fd);
//方式4:构造函数将文件名作为第一参数,将布尔值作为第二参数
FileOutputStream out = new FileOutoutStream("d:/abc.txt",true);
注:文件中写数据时,若文件已存在,覆盖存在的文件
使用键盘输入一段文章,将文章保存在 文件write.txt中
import java.io.IOException;
import java.io.FileOutputStream;
public class TestFile{
public static void main (String[] args) throws IOException{
try{
System.out.println("please Input from Keyboard");
int count = 0;
int n = 512;
byte[] buffer = new byte[n];
count = System.in.read(buffer);
FileOutputStream out = new FileOutStream("d:/myjava/write.txt");
out.write(buffer,0,count);
out.close();
System.out.println("Save to the.write.txt");
}catch(IOException IOe){
System.out.println("File Write Error!");
}
}
}
3.3 FileInputStream流和FileOutputStream的应用
将file1.txt复制到file2.txt中
import java.io.File;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.FileInputStream;
public class TestFile{
public static void main(String[] args)throws IOException{
try{
int count;
File in = new File("file1.txt");
File out = new File("file2.txt");
FileInputStream infile = new FileInputStream(in);
FileOutputStream outfile = new FileOutputStream(out);
//判断如果输入流不为空进行循环内操作
while((count = infile.read()) != -1){
//写入file2.txt文件中
outfile.write(count);
}
//关闭输入流
infile.close();
//关闭输出流
outfile.close();
}catch(IOException IOe){
System.out.println(IOe);
}
}
}
4、缓冲输入输出流 BufferedInputStream/BufferedOutputStream
BufferedInputStream
计算机访问外存的频率越高,造成CPU闲置的概率就越大,为了减少对外存的访问次数,我们应该一次读写尽量多的数据。因此增加了缓冲机制,缓冲流就是每一个数据流分配一个缓冲区,这样可以提高传输效率。
BufferedInputStream比FileInputStream多了一个缓冲区,它提供了一个缓冲数组,调用read()方法首先从缓冲数组中读取数据,如果缓冲数组中没有数据,则选择从物理数据源中读取数据放入缓冲区中。BuffferedInputStream默认缓冲大小是8192字节。每次读取的数据量很小时FileInputStream每次都是从硬盘读入,而BufferedInputStream大部分是从缓冲区读入。BufferedInputStream效率高。当BUFFER_SIZE>8192时缓冲池输入流和文件输入流效率没有明显的差别。
BufferedOutputStream
执行write时先写入缓冲区,待缓冲区写满后再写入输出设备
将文件读入内存:
FileInputStream in = new FileInputStream(file);
BufferedInputStream bin = new BufferedInputStream(in);
bin.read();
bin.close();
将内存写入文件:
String fileB = "/User/zhangyingying/b.txt";
FileOutputStream out = new FileOutputStream(fileB);
BufferedOutputStream bout = new BufferedOutputStream(out);
byte[] buffer = {0x1,0x2,0x3};
bout.write(buffer);
bout.flush();
bout.close();
键盘输入流到读到内存
import java.io.*;
public class Testfile{
public static void main(String[] args){
//字符流
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
FileWriter out = new FileWriter("myfile.txt");
BuferedOutputStream bout = new BufferedWriter(out);
String s;
While((s = dr.readLine()).length() > 0){
bout.write(s,0,length());
}
}
}
String readLine():读取一行字符串,以回车符结束
bout.write(String s ,offset ,len)从缓冲区将字符串s从offset开始,len长度的字符串写到某处。
六、字符流Reader和Writer
java中字符采用unicode编码,一个字符是16位,一个字符由两个字节组成。
1、Reader抽象类
用于读取字符流的抽象类。子类必须实现read(char[],int,int)和close(),多数子类会重写定义的一些方法
FileReader:用于 读取字符文件中的数据,使用缺省的字符编码
构造函数
-
FileReader fr = new FileReader(“test.txt”);——文件名做字符串
-
File对象做字符串
File file =new File(“test.txt”);
FileReader fileReader = new FileReader(file);
-
FileDescriptor对象作为参数
FileDescriptor() fd = new FileDescriptor();
FileReader fileReader = new FileReader(fd);
CharArrayReader
- 用字符数组作为参数:CharArrayReader(char[]);
- 将字符数组作为输入流:CharArrayReader(char[],int,int);
StringReader
- 读取字符串,构造函数如下:public StringReader(String s);
InputStreamReader
输入流读取字节将字节流转换为字符流
public InputStreamReader(InputStream is);
FilterReader:允许过滤字符流
protected filterReader(Reader r)
BufferReader:接受Reader对象作为参数,并对其添加字符缓冲器
可以使用readLine()方法读取一行
public BufferReader(Reader r);
- public int read();读取一个字符,返回值为读取的字符;
- public int read(char cbuf[],int off, int len);读取len个字符,从数组cbuf[]的下标off处开始存放,返回值为实际读取的字符数量子类必须实现
2、Writer抽象类
子类必须实现write(char[],int,int)、flush()、close()方法
其子类:
FileWriter
将字符类型写入文件
public FileWriter(file f);
CharArrayWriter
将字符缓冲器用作输出
public CharArrayWriter();
PrintWriter:生成格式化输出
public PrintWriter(outputstream os);
FilterWriter:用于写入过滤字符流
protected FilterWriter(Writer w);
PipedWriter:与PipedOutputStream对应
**StringWriter:无与之对应的以字节为导向的stream **
主要方法
(1) public void write(int c); //将整型值c的低16位写入输出流
(2) public void write(char cbuf[]); //将字符数组cbuf[]写入输出流
(3) public abstract void write(char cbuf[],int off,int len); //将字符数组cbuf[]中的从索引为off的位置处开始的len个字符写入输出流
(4) public void write(String str); //将字符串str中的字符写入输出流
(5) public void write(String str,int off,int len); //将字符串str 中从索引off开始处的len个字符写入输出流
(6) flush( ) //刷空输出流,并输出所有被缓存的字节。
(7) close( ) //关闭流 public abstract void close() throws IOException
七、InputStream和Reader的区别
- InputStream输入流为字节流,最小单位是字节;Reader输入流为字符流,在处理字符流时涉及了字符编码转换问题。
- Reader能将输入流中采用其他编码类型的字符转换为Unicode字符,然后在内存中为其分配内存
八、OutputStream和Writer的区别
- OutputStream输出流为字节流最小单位是字节,Writer输出流为字符流,在处理字符流时涉及了字符编码转换问题
- Writer能将内存中的Unicode字符转换为其他编码类型的字符,再写到输出流中。
九、BufferedInputStream和BufferedReader的区别
BufferedInputStream实现的时候在自身的read()方法中提供缓存,是一次取1024或更多字节然后再读,最后一个个的返回。没有实现读一行的方法。
BufferReader可以通过readLine()方法实现读一行(回车为结束符),可以使用数组或StringBuilder存储一行数据,并一次性返回。
十、FileWriter(字符输出流类)
构造方法
//创建字符输出流类对象和文件相关联,如果文件不在的话创建一个文件。
FileWriter file = new FileWriter(String FileName);
//创建一个字符输出流类对象和文件关联,并且设定是否续写,false为不续写(原来文件内容会被覆盖掉),true为续写。
FileWriter file = new FileWriter(Srting FileName, boolean append);
主要方法
//写入字符串,此时的字符串还没有到达被写入文件中,暂存在缓冲区中,写入之后使用flush()方法刷新,数据才会被存储到目的文件中。
void write(String str);
//刷新对应的输出流,将缓冲区中的数据保存到对应文件中去
void flush();
//关闭输出流,在关闭之后再写入或刷新会抛出异常
void close();
十一、FileReader(字符输入流)
构造方法
//第一种构造方法,创建输入流对象与文件相关联
FileReader fileReader = new FileReader(“test.txt”);
//第二种构造方法,创建文件对象,创建输入流对象,通过文件对象与相对应文件相关联。
File file = new File(“test.txt”);
FileReader fileReader = new FileReader(file);
主要方法
int read();
int read(char[] c);
int read(char[] c,off,len);
int read(CharBuffer target);
void close();
十二、如何选择IO流
1、确定是数据源还是数据目的
- 源:输入流 InpurtStream/Reader
- 目的:输出流 OutputStream/Writer
2、操作对象是否纯文本
- 是:Reader、Writer
- 否:InputStream、OutputStream
3、具体设备
-
硬盘文件:File+
- 读取:FileInputStream、FileReader
- 写入:FileOutputStream、FileWrite
-
内存:数组
-
byte[]:ByteArrayInputStream、ByteArrayOutputStream
-
char[]:CharArrayReader、CharArrayWriter
-
String:StringBufferInputStream(过时,只能用于String的每个字符都是8位的字符串),StringReader,StringWriter
-
网络(Socket流):输出socket.getOutputStream();输出socket.getInputStream()
-
键盘:输入System.in()读取;输出System.out()打印;
Scanner scan = new Scanner(System.in);
-
4、是否需要转换流
是:InputStreamReader/OutputStreamWriter
5、是否需要缓冲提高效率
是:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter
6、是否需要格式化输出
将一个文件中数据存储到另一个文件中。JAVA的文件读取主要有字节流读取和字符流读取两种方式,字节流可以既可以操作文本文件,也可以操作非文本文件,如一些二进制数据(图片,视频,对象),而字符流只能操作文本。
十三、IOException异常类的子类
- public class EOFException:非法到达文件尾或输入流尾的时候,抛出这种异常;
- public class FileNotFoundException:当文件找不到时,抛出异常;
- public class InterruptedIOExcception:I/O操作被中断时,抛出这种异常。