java基础之IO(重点)
(一)java.io包
Java.io 包包含了所有操作输入、输出需要的类。对于数据的输入和输出操作以流(stream)的方式进行。
注意:流本质就是一个数据序列,可以抽象理解为接水的管道。
1、分类
1、基于字节操作的I/O接口:InputStream和OutputStream
2、基于字符操作的I/O接口:Writer和Reader
3、基于磁盘操作的I/O接口:File
4、基于网络操作的I/O接口: Socket(不在java.io包下)
按数据流方向的不同分为输入流和输出流(输入和输出就是按程序来划分的)
按处理数据单位不同分为字节流和字符流(字节流相当于最原始的流,按一个个字节操作数据即:二进制数 字符流就是按一个个字符操作数据,一个字符就是两个字节,直接可以操作中文)
按照功能不同分为节点流和处理流
sdk中所提供的所有的流类型都分别继承一下四个抽象流类型,是抽象类,不是接口。
注意:输入流和输出流是按程序作为参照的,不是硬盘文件。对于程序,写就是输出,读就是输入。
字节流 | 字符流 | |
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
可以把上面四个抽象类,理解为四个管道。管道的一端接文件,一端接程序。
(二)InputStream(输入字节流)抽象类
继承自InputStream的流都是用于向程序中输入数据,且数据的单位是字节(8位)
1、InputStream的基本方法(都会抛出IOException)
int read()方法 读取一个字节并以整数的形式返回(0-255),如果返回-1表示已到输入流的末尾。
int read(byte[] buffer):读取一系列字节并存储到一个数组buffer,返回实际读取的字节数。返回-1.表示已读到输入流末尾。buffer是缓存,相当于用水桶来接水,先把水桶接满,然后在去倒水。
int read(byte[] buffer,int begin,int length)
void close():关闭流释放内存资源
(三)OutputStream(输出字节流)抽象类 与InputStream对应
继承自OutputStream的流都是用于向程序中输出数据,且数据的单位是字节(8位)
void write(int b) :表示向输出流写入一个字节数据,该字节数据为参数b的低八位。
void write(byte[] buffer)
void write (byte[] buffer,int begin,int length)
void close():关闭流释放内存资源
void flush():将输出流中缓冲的数据全部写出到目的地。
注意:在close()方法之前,应该先调用flush()方法。
(四)Reader(输入字符流)字符流是解决中文操作。
继承自Reader的流都是向程序中输入数据,并且数据的单位是字符(16位)。
int read()
int read(char[] cbuffer)
int read(char[] cbuffer , int begin, int length)
void close()
(五)Writer(输出字符流)
继承自Writer的流都是向程序中输出数据,并且数据的单位是字符(16位)。
void write(int c):写入单个字符,要写入的字符包含在给定整数值的 16 个低位中,16 高位被忽略。
void write(char[] cbuffer)
void write(char[] cbuffer, int begin , int length)
void write(String string) :将一个字符串中的字符写入到输出流。
注意:为啥能写入一个字符串,因为字符串有一个方法:char[] toCharArray()方法:字符串对象可以通过该方法把自己转换为一个字符数组。编译器会自动调用该方法。
void write (String string, int begin, int length)
void close()
void flush():将输出流中的缓冲数据全部写出到目的地
注意:在close()方法之前,应该先调用flush()方法。
(六)节点流类型(节点相当于数据源)(重点)
读写一个文件:
1、首先获取这个文件,获取该文件的路径加文件名:String path = getPath()+File.separator+getName()
2、利用File类,通过File类的构造方法获得文件对象,构造方法:File(String directoryPath, String filename)或者File(File dirObj, String filename)
3、利用节点流来读写文件的内容,FileInputStream(File file)或者FileInputStream(String filename)
- File file = new File ("hello.txt");
- FileInputStream in=new FileInputStream(file);
- InputStreamReader inReader=new InputStreamReader(in,"utf-8");
- BufferedReader bufReader=new BufferedReader(inReader);
-
- InputStreamReader isr = new InputStreamReader(new FileInputStream("ming.txt"));
- while((ch = isr.read())!=-1)
- {
- System.out.print((char)ch);
- }
FileInputStream类以二进制输入/输出,I/O速度快且效率搞,但是它的read()方法读到的是一个字节(二进制数据),很不利于人们阅读。
而FileReader类弥补了这个缺陷,可以以文本格式输入/输出,非常方便;比如可以使用while((ch = filereader.read())!=-1 )循环来读取文件;也可以使用BufferedReader的readLine()方法一行一行的读取文本。
当我们读写文本文件的时候,采用Reader是非常方便的,比如FileReader, InputStreamReader和BufferedReader。其中最重要的类是InputStreamReader,它是字节转换为字符的桥梁。 你可以在其构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如GBK等。
节点流就直接从一个特定的数据源(节点)读写数据(如:文件,内存),相当于一个管道直接插到数据源,直接读写。
父 类 InputStream OutputStream Reader Writer
文 件 FileInputStream FileOutputStrean FileReader FileWriter 文件进行处理的节点流
数 组 ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
字符串 无 无 StringReader StringWriter 对字符串进行处理的节点流
管 道 PipedInputStream PipedOutputStream PipedReader PipedWriter 对管道进行处理的节点流,线程之间
(七)处理流类型(注意构造方法)
缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写效率,同时增加了一些新的方法。
处理流就是连接在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。(相当于包别的管道上的管道)。
父 类 InputStream OutputStream Reader Writer
缓冲流 BufferedImputStrean BufferedOutputStream BufferedReader BufferedWriter (常用)
功能:需要父类作为参数构造,增加缓冲功能,避免频繁读写硬盘,可以初始化缓冲数据的大小,由于带了缓冲功能,所以就写数据的时候需要使用flush方法咯
转换流 InputStreamReader OutputStreamWriter-要inputStream或OutputStream作为参数,实现从字节流到字符流的转换
数据流 DataInputStream DataOutputStream -提供将基础数据类型写入到文件中,或者读取出来,
为什么要有这个流呢?看这样的分析,如果没有这种流的话,有一个long,本身只占8个字节,如果我要写入到文件,需要转成字符串,然后在转成字符数组,那空间会占用很多,但是有了这种流之后就很方便了,直接将这8个字节写到文件就完了。。是不是既节约了内存空间有让程序写起来更加方便简单了呐。写倒是很简单,但是读取的时候就注意了,根据读取的数据类型,指针会往下移,所以你写的顺序必须要和读的顺序一致才能完成你正确的需求。
对象流 :用于直接将对象写入写出。
流类有ObjectInputStream和ObjectOutputStream,本身这两个方法没什么,但是其要写出的对象有要求,该对象必须实现Serializable接口,来声明其是可以序列化的。否则,不能用对象流读写。
还有一个关键字比较重要,transient,由于修饰实现了Serializable接口的类内的属性,被该修饰符修饰的属性,在以对象流的方式输出的时候,该字段会被忽略。
1、缓冲流(重点:BufferedReader和BufferedWriter)
构造方法:BufferedReader(Reader in) BufferedReader(Reader in , int size) 其中size定义缓存区的大小
BufferedWriter BufferedInputStream BufferedOutputStream 构造方法与之类似
注意:BufferedReader提供了readLine()方法:用于读取一行字符串,通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。返回包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
BufferedWriter提供了newLine()方法:写入一个行分隔符。行分隔符字符串由系统属性 line.separator 定义,并且不一定是单个新行 ('\n') 符。
2、转换流:字节数据与字符数据之间的转换(重点)
InputStreamReader 需要和 InputStream 套接
OutputStreamWriter 需要和 OutputStream 套接
注意:转换流在构造时,可以指定其编码集合
InputStreamReader(InputStream in, String charsetName)
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。例如:
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System类的静态属性in是InputStream类型。Java 的控制台输入由 System.in 完成。System.in具有阻塞方法,就是你不输入,程序不往下走。
FileOutputStream(String name,
boolean append):append为true表示从文件末尾处写入,而不是开始位置。
3、数据流
作用:提供对java基础数据类型写入文件,或者是读出来。
DataInputStream和DataOutputStream提供了可以存取与机器无关的java原始类型数据的方法。
1、两个类的构造方法
DataInputStream(InputStream in )和DataOutputStream(OutputStream out)
注意:readUTF()方法:在网络传输数据常用,该方法读取使用 UTF-8 修改版格式编码的 Unicode 字符串的表示形式;然后以 String
的形式返回此字符串。
UTF—8编码:比较省空间,多用在网络传输数据中。
4、对象流(Object流):用于直接将对象写入和读取(重点)
流类有ObjectInputStream和ObjectOutputStream,本身这两个方法没什么,但是其要写出的对象有要求,该对象必须实现Serializable接口,来声明其是可以序列化的。否则,不能用对象流读写。
transient,由于修饰实现了Serializable接口的类内的属性,被该修饰符修饰的属性,在以对象流的方式输出的时候,该字段会被忽略。
1、所保存的对象必须实现Serializable接口。
2、 所保存的对象的属性也必须实现Serializable接口(该接口是标记接口,即没有任何方法的接口)。
3、 最好要给该对象提供一个版本号,private static final long serialVersionId。
注意:实现Serializable接口,就是标记该对象可以序列化,即告诉编译器该对象可以序列化,对象的序列化有JVM控制。Externalizable接口:通过实现该接口可以实现自己来控制对象的序列化过程。 需要重写两个方法:writeExternal 和 readExternal 方法。
PrintWriter和PrintStream都属于输出流,分别针对字符和字节。提供了重载的print()方法,println()方法用于多种数据类型的输出,有换行。
注意:PrintWriter和PrintStream都有自动flush功能。同时二者的输出操作不会抛出异常,在内部就会被处理。
public static void main(String[] args) throws IOException {
// 节点流FileOutputStream直接以A.txt作为数据源操作
FileOutputStream fileOutputStream = new FileOutputStream("A.txt");
// 过滤流BufferedOutputStream进一步装饰节点流,提供缓冲写
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
fileOutputStream);
// 过滤流DataOutputStream进一步装饰过滤流,使其提供基本数据类型的写
DataOutputStream out = new DataOutputStream(bufferedOutputStream);
out.writeInt(3);
out.writeBoolean(true);
out.flush();
out.close();
// 此处输入节点流,过滤流正好跟上边输出对应,读者可举一反三
DataInputStream in = new DataInputStream(new BufferedInputStream(
new FileInputStream("A.txt")));
System.out.println(in.readInt());
System.out.println(in.readBoolean());
in.close();
}