java IO操作主要指使用java进行输入输出操作,以内存为基准,按照数据流动的方向,将流向内存的称为输入流,流出内存的称为输出流。对于输入输出流,又细分为字节输入流,字节输出流,字符输入流,字符输出流。下面笔者将对这些流的基本使用进行介绍,如有错误还请批评指正。
IO流的分类图,左边按字节和字符流划分,右边按输入输出流划分。
字节输入流(InputStream)
一.基础知识
1.InputStream是一个抽象类,是所有字节输入的父类
2.根类常用的成员方法:
(1)abstract int read() 从输入流中读取数据的下一个字节。
(2)int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
(3)void close() 关闭此输入流并释放与该流关联的所有系统资源
3.常用的已实现的子类:
(1)FileInputStream 文件字节输入流。从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。
(2)BufferedInputStream 字节缓冲输入流
二.使用方法
1.FileInputStream的使用方法
/*
一次读取一个字节
注意事项:
1.构造方法:
(1)FileInputStream(File file) 过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的File 对象 file 指定
(2)FileInputStream(String name) 过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定
2.父类成员方法详细分析
(1)abstract int read() 返回读取到字节的值,如果读取到文件末尾将会返回-1
*/
public class Main{
public static void main(String[] args) throws IOException{
FileInputStream fis = new FileInputStream("参数");
int len = 0;
while((len=fis.read())!=-1){
System.out.println((char)len);
}
fis.close();
}
}
/*
一次读取多个字节
注意事项:
1.父类成员方法分析:
(1)int read(byte[] b) 返回值是读取到的有效字节的个数,并将其存储在缓冲区数组 b 中,若没有可读字节将会返回-1
2.如何将字节数组转化为字符串?
调用String类的构造方法new String(byte[] bytes, int offset, int length) offset为起始位置,length是为要转化的长度
*/
public class Main{
public static void main(String[] args){
FileInputStream fis = new FileInputStream("参数");
int len = 0;
byte[] by = new byte[1024];
while((len=fis.read(by))!=-1){
System.out.println(new String(by,0,len));
}
}
}
三.原理分析
1.一次读取一个字节的原理分析
当程序执行读取文件的代码时,这事当前的程序会将此任务转交给JVM虚拟机,JVM虚拟机再将此任务交给操作系统os,由操作系统完成文件 的读取,然后依次返回.
2.使用一次读取一个字节数组的数据需要注意的问题
(1)方法int read(byte[] b)的返回值是读取到的有效字节的个数,那么何为有效字节呢?我们列如下例子:
eg:要读取的文本数据为: abcdefg ,规定参与读取的字节数组的大小为2,即byte by[2],请简述其读取过程.
初始 字节数组的内容: 0 0 (为了叙述方便,我们假设字节数组的里存的是真实数据)
第一次读取 字节数组的内容: a b 有效字节个数为2
第二次读取 字节数组的内容: c d 有效字节个数为2
第三次读取 字节数组的内容: e f 有效字节个数为2
第四次读取 字节数组的内容: g f 有效字节个数为1
这也是为什么我们在将字节数组转化为字符数组时更多使用 new String(byte[] bytes, int offset, int length),这样就可以避免重复计入数据 问题。如上例的第四次读取,最后一次由于只读取到一个有效字符g,故只能覆盖数组的第一个值,导致第二个值并没有被覆盖,如果使用new String(byte[] bytes, int offset, int length)输出就只会输出g,而使用 new String(byte[] bytes)则会输出g f,后者显然是错误的.
(2)数组的大小最好为1024的整数倍
字节输出流(OutputStream)
一.基础知识:
1.OutputStream是一个抽象类,是所有字节输出流的父类.
2.根类的常用成员方法:
(1)void close() 关闭此输出流并释放与此流有关的所有系统资源。
(2)void flush() 刷新此输出流并强制写出所有缓冲的输出字节。
(3)void write(byte[] b)将 b.length 个字节从指定的 byte 数组写入此输出流。
(4)void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的len 个字节写入此输出流。
3.常用的已实现的子类:
(1)FileOutputStream 文件字节输出流,是用于将数据写入 File 或 FileDescriptor 的输出流。
(2)BufferedOutputStream 字节缓冲输出流
二.使用方法
1.FileOutputStream的使用方法
/*
文件字节输出流的使用注意事项
1.构造方法
(1)FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流
(2)FileOutputStream(File file, boolean append) 创建一个向指定 File对象表示的文件中写入数据的文件输出流,可追加写数据
(3)FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流,name为文件路径
(4)FileOutputStream(String name, boolean append) 创建一个向具有指定 name 的文件中写入数据的输出文件流,可追加写数据
2.如何利用字节输出流,写入一个字符串?
利用String类中的getBytes()方法将字符转转化为字节输入,然后调用字节输出流中的write()方法将其写入
*/
public class Main{
public static void main(String[] args){
FileOutputStream fos = null;
try{
fos = new FileOutputStream("文件的相对路径/绝对路径");
fos.write(97); //一次写入一个字节
/*一次写多个数据 void write(byte[] b)将 b.length 个字节从指定的 byte 数组写入此输出流。
byte[] bt = new byte[]{97,98,99,100};
fos.write(bt);
*/
/*
一次写入多个数据 void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的len 个字节写入此输出流
byte[] bt = new byte[]{97,98,99,100};
fos.write(bt,1,2);
*/
} catch(FileNotFoundException e){
e.printStackTrace();
} catch(IOException e){
e.printStackTrace();
} finally{
if(fos != null){
try{
fos.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
/*
FileOutputStream追加写演示代码
注意事项:
1.调用构造方法:FileOutputStream(File file, boolean append) 或 FileOutputStream(String name, boolean append)
其中若参数append的值为true则允许追加写,为false则不允许追加写
2.如何换行?
windows:\r\n
linux:/n
mac:/r
*/
public class Main{
public static void main(String[] args){
FileOutputStream fos = null;
try{
fos = new FileOutputStream("问价的相对路径/绝对路径",true); //允许追加写
fos.write("世界你好!".getBytes());
fos.write("\r\n".getBytes());
} catch(FileNotFoundException e){
e.printStackTrace();
} catch(IOException e){
e.printStackTrace();
} finally{
if(fos != null){
try{
fos.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
三.常见问题分析
void flush() 和 void close()的区别?
当我们调用write方法写数据时,数据并没有立即写到文件里,而是写在一个叫做"内存缓冲区"的地方.只有当我们调用了flush()刷新方法后,数据才会被写到文件里。需要注意的是,当我们调用close()方法关闭流时,会自动调用flush()刷新方法,所以我们常常不写flush()刷新方法。
字符输入流(Reader)
一.基础知识
1.Reader是一个抽象类,是所有字符输入流的父类
2.根类的常用成员方法:
(1)int read() 取单个字符。
(2)int read(char[] cbuf) 将字符读入数组
(3)abstract void close() 关闭该流并释放与之关联的所有资源
3.常用的已实现的子类:FileReader(FileReader extends InputStreamReader extends Reader),
BufferedReader
二.使用方法
1.FileReader的使用方法
/*
注意事项
1.构造方法:
(1)FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader
(2)FileReader(String fileName) 在给定从中读取数据的文件名的情况下创建一个新 FileReader
*/
public class Main{
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("参数");
int len = 0;
while((len=fr.read())!=-1){
System.out.println((char)len);
}
}
}
字符输出流(Writer)
一.基础知识
1.Reader是一个抽象类,是所有字符输出流的父类
2.根类的常用成员方法:
(1)abstract void close() 关闭此流,但要先刷新它
(2)abstract void flush() 刷新该流的缓冲
(3)void write(char[] cbuf) 写入字符数组
(4)abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分
(5)void write(int c) 写入单个字符
(6)void write(String str) 写入字符串。
(7)void write(String str, int off, int len) 写入字符串的某一部分
3.常用的已实现的子类:FileWriter(FileReader extends OutputStreamWriter extends Writer)
BufferedWriter
二.使用方法
1.FileWriter的使用方法
/*
注意事项:
1.构造方法:
(1)FileWriter(File file)根据给定的 File 对象构造一个 FileWriter 对象。
(2)FileWriter(File file, boolean append) 根据给定的 File 对象构造一个 FileWriter 对象。可追加写,true为可追加写。
(3)FileWriter(String fileName) 根据给定的文件名构造一个 FileWriter 对象。
(4)FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的boolean值来构造FileWriter对象.可追加。
*/
public class Main{
public static void main(String[] args) throws IOException{
FileWriter fw = new FileWriter("参数");
fw.write("世界你好!");
fw.close();
}
}
在了解了基本的四个流之后,jdk为我们提供了更强大的流----高效读写缓冲流,它是对4个基本流的增强,同样也是4个流,字节缓冲输入流,字节缓冲输出流,字符缓冲输入流,字符缓冲输出流。
缓冲流的原理图(以输入流为例)。
字节缓冲输入流(BufferedInputStream)
一.基础知识
1.BufferedInputStream extends FilterInputStream extends InputStream
2.构造方法:
(1)BufferedInputStream(InputStream in) 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。
(2)BufferedInputStream(InputStream in, int size) 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流
in,以便将来使用
3.常用的成员方法:
(1) void close() 关闭此输入流并释放与该流关联的所有系统资源
(2) int read(byte[] b, int off, int len) 从此字节输入流中给定偏移量处开始将各字节读取到指定的 byte 数组中
(3))继承自父类的方法
4.使用步骤:
(1)创建一个字节输入流对象 FileInputStream
(2)创建一个字节缓冲流对象BufferedInputStream
(3)read()方法读数据
(4)关闭流
二.代码演示
/*
字节输入流
*/
public class Main{
public static void main(String[] args) throws IOException{
FileInputStream fis = new FileInputStream("参数");
BufferedInputStream bis = new BufferedInputStream(fis);
int len = bis.read();
System.out.println((char)len);
}
}
字节缓冲输出流(BufferedOutputStream)
一.基础知识
1.BufferedOutputStream extends FilterOutputStream extends OutputStream
2.构造方法:
(1)BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流
(2)BufferedOutputStream(OutputStream out, int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流
3.常用的成员方法:
(1)void flush() 刷新此缓冲的输出流
(2)void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流
(3)void write(int b) 将指定的字节写入此缓冲的输出流
(4)继承自父类的方法
4.使用步骤:
(1)创建一个字节输出流对象FileOutputStream
(2)创建一个字节缓冲输出流对象BufferedOutputStream
(3)write方法写数据
(4)关闭流
二.代码演示
/*
字符缓冲输出流
*/
public class Main{
public static void main(String[] args) throws IOException{
FileOutputStream fos = new FileOutputStream("参数");
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("世界你好".getBytes());
bos.close();
fos.close();
}
}
字符缓冲输入流(BufferedReader)
一.基础知识
1.BufferedReader extends Reader
2.构造方法:
(1)BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流
(2)BufferedReader(Reader in, int sz) 创建一个使用指定大小输入缓冲区的缓冲字符输入流
3.常用的成员方法
(1) String readLine() 读取一个文本行
读取一个文本行。通过下列字符之一即可认为某行已终止:换行 (’\n’)、回车 (’\r’) 或回车后直接跟着换行
包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
(2)继承自父类的成员方法
二.代码演示
/*
代码演示
*/
public class Main{
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("参数");
BufferedReader br = new BufferedReader(fr);
String str = null;
while((str=br.readLine()) != null){
System.out.println(str);
}
}
}
字符缓冲输出流(BufferedWriter)
一.基础知识
1.BufferedWriter extends Writer
2.构造方法:
(1)BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流
(2)BufferedWriter(Writer out, int sz) 创建一个使用给定大小输出缓冲区的新缓冲字符输出流
3.常用成员方法
(1)void newLine() 写入一个行分隔符
(2)继承自父类的成员方法
二.代码演示
/*
字符缓冲输出流
*/
public class Main{
public static void main(String[] args) throws IOException{
FileWriter fw = new FileWriter("参数");
BufferedWriter bw = new BufferedWriter(fw);
bw.write("世界你好!");
bw.newLine(); //换行
bw.close();
}
}
以上即是对javaSE中IO流的简单概述