IO(Input/Output):输入和输出,指的是某个设备或环境进行数据的输入或输出,Java将输入、输出抽象成流对象来解决。
例:以Java游戏程序为中心
IO流在Java中从输入输出角度分类 | IO流在Java中从数据的角度分类 |
---|---|
输入流 | 字符流 例:word文件、java文件 可以理解为文本,我们能直接能读懂的都可以认为是字符流 |
输出流 | 字节流 例:图片文件、音视频文件等 是二进制数据,这种数据用文本打开后我们读不懂。 |
字符输入流的超类:Reader | 子类:FileReader、BufferReader |
---|---|
字符输出流的超类:Writer | 子类:FileWriter、BufferWriter |
字节输入流的超类:InputStream | 子类:FileInputStream |
字节输出流的超类:OutputStream | 子类:FileOutputStream |
关闭缓冲区语句外的try...catch
外使用if语句判断相应流的对象是否为空,再使用finally语句将上述代码括起来。
将输入、输出流的对象在方法一开始赋值为空,再创建其对象,这样方便关闭资源。
使用字符流向一个文件中写入内容的步骤:
①创建目标文件或定位到目标文件
②创建输出流对象
③将输出流指向目标文件
④做相应操作
⑤刷新输出流的缓冲区
⑥释放资源
注意:在使用相对路径时做操作时,待代码运行完毕后,在相应项目上右键刷新才能看到新创建的文件!
FileWriter(File file)
给一个File对象构造一个FileWriter对象。
例:
// "文件名.xxx"
FileWriter fw = new FileWriter(new File("Test.txt"));
---------------------------------------------------------------------------------
FileWriter(String fileName)
构造一个给定文件名的FileWriter对象。
例:
// "文件名.xxx"
FileWriter fw = new FileWriter("Test.txt");
---------------------------------------------------------------------------------
返回值类型 方法名 参数列表
void write(String str)
写入一个字符串
---------------------------------------------------------------------------------
abstract void flush()
刷新流。
---------------------------------------------------------------------------------
abstract void close()
关闭流,先刷新。
---------------------------------------------------------------------------------
void write(char[] cbuf)
写入一个字符数组。
public static void main(String[] args){
//创建目标文件,此处使用的为相对路径的目录
File file = new File("Test.txt");
FileWriter fw = null;
try {
//创建输出流对象,并将输出流指向目标文件
fw = new FileWriter(file);
//写入字符串
fw.write("HelloWorld!");
//写入字符数组
char[] ch = {
'a','b','c','d','e','f','g','h'};
fw.write(ch);
//刷新(清空)缓冲区,将内容写入到文件中
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
//判断输出流是否为空
if(fw != null) {
try {
//关闭输出流,释放资源
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:在项目中将会产生一个Test.txt文件,文件内容为:HelloWorld!abcdefgh
构造器部分改进代码:
public static void main(String[] args){
//,此处使用的为相对路径的目录
FileWriter fw = null;
try {
//创建输出流对象,自动创建目标文件并将输出流指向目标文件
fw = new FileWriter("Test.txt");
虽然flush方法会当缓冲区存满后自动写入,但是效率不高,还有可能发生缓冲区溢出的情况,所以我们要手动调节。
例如下面的代码,向文件中写入100个HelloWorld!
,我们可以每到10次写入之后做一次缓冲区清空。
for(int i = 0;i<100;i++){
fw.write("HelloWorld!");
if(i%10 == 0){
fw.flush();
}
}
当第二个参数为true时,将追加写入
FileWriter(File file, boolean append)
给一个File对象构造一个FileWriter对象。
例:
// "文件名.xxx"
FileWriter fw = new FileWriter(new File("Test.txt"),true);
---------------------------------------------------------------------------------
FileWriter(String fileName, boolean append)
构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。
例:
// "文件名.xxx"
FileWriter fw = new FileWriter("Test.txt",true);
---------------------------------------------------------------------------------
Winous | Linux | Mac |
---|---|---|
\r\n |
\n |
\r |
建议使用"\r\n"
,可兼容Windows记事本。若为"\n\r"
将会存在空行。
例:fw.write("字符串"+"\r\n");
abstract void write(char[] cbuf, int off, int len)
写入字符数组的一部分。
---------------------------------------------------------------------------------
void write(int c)
写一个字符
---------------------------------------------------------------------------------
void write(String str, int off, int len)
写一个字符串的一部分。
---------------------------------------------------------------------------------
public static void main(String[] args){
FileWriter fw = null;
try {
//创建输出流对象,自动创建目标文件并将输出流指向目标文件
fw = new FileWriter("Test.txt",true);
//写入字符串选定的部分
fw.write("HelloWorld!",0,5);
//写入字符数组选定的部分
char[] ch = {
'a','b','c','d','e','f','g','h'};
fw.write(ch,0,4);
//这里的98对应的是b
fw.write(98);
//刷新(清空)缓存区,将内容写入到文件中
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
//判断输出流是否为空
if(fw != null) {
try {
//关闭输出流,释放资源
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:Test.txt文件中将有Helloabcdb
内容。
读取一个名为文件名.xxx的内容并打印到控制台
①创建输入流对象
②读取数据
③关闭输入流
FileReader(File file)
创建一个新的 FileReader ,给出 File读取。
---------------------------------------------------------------------------------
FileReader(String fileName)
创建一个新的 FileReader ,给定要读取的文件的名称。
---------------------------------------------------------------------------------
返回值类型 方法名 参数列表
int read()
读一个字符 (当返回值为-1时表示此文件已读取完毕)(若文件中存在换行也将会读取到)
例:
public static void main(String[] args) {
FileReader fr = null;
try {
//此处需要try...catch来捕获文件未找到异常
fr = new FileReader("Test.txt");
int num = 0;
//当read方法读取完数据后会返回-1,所以我们使用while循环判断
//此处需要try...catch来捕获IO流异常
while((num = fr.read())!=-1) {
//read方法返回值类型为字符对应的ASCII码
System.out.print(num+" ");
//如果想要打印原始字符,需要强制转换
//若要使用这条输出语句需要注释上一行的输出语句!
// System.out.print((char)num+" ");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
//这里没有重新try...catch,而是使用try...catch...catch
}catch (IOException e) {
e.printStackTrace();
}finally {
if(fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
输出结果:
72 101 108 108 111 87 111 114 108 100 33
强转后的输出结果:
H e l l o W o r l d !
---------------------------------------------------------------------------------
int read(char[] cbuf)
将字符读入数组。 (当返回值为-1时表示此文件已读取完毕)(若文件中存在换行也将会读取到)
例:
public static void main(String[] args) {
FileReader fr = null;
try {
//此处需要try...catch来捕获文件未找到异常
fr = new FileReader("Test.txt");
int num = 0;
char[] ch = new char[15];
//当read方法读取完数据后会返回-1,所以我们使用while循环判断
//此处需要try...catch来捕获IO流异常
while((num = fr.read(ch))!=-1) {
//此处read方法返回值为读取到的字符长度
System.out.print(num+" ");
}
//此处直接将char数组转换为字符串类型
String str = new String(ch);
System.out.println(ch);
} catch (FileNotFoundException e) {
e.printStackTrace();
//这里没有重新try...catch,而是使用try...catch...catch
}catch (IOException e) {
e.printStackTrace();
}finally {
if(fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
输出结果:
---------------------------------------------------------------------------------
abstract int read(char[] cbuf, int off, int len)
将字符读入数组的一部分。 (若文件中存在换行也将会读取到)
(off为在数组中存入字符的起始位置,len为存入字符的长度)
例:
public static void main(String[] args) {
FileReader fr = null;
try {
//此处需要try...catch来捕获文件未找到异常
fr = new FileReader("Test.txt");
int num = 0;
char[] ch = new char[20];
//当read方法读取完数据后会返回-1,所以我们使用while循环判断
//此处需要try...catch来捕获IO流异常
//这里使用read方法将指定长度的字符读入到数组中指定位置
while((num = fr.read(ch,1,8))!=-1) {
//此处指定输出存入char数组中的字符
System.out.println(new String(ch,0,5));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
//这里没有重新try...catch,而是使用try...catch...catch
}catch (IOException e) {
e.printStackTrace();
}finally {
if(fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
输出结果:
---------------------------------------------------------------------------------
注意:read(char[] cbuf, int off, int len)
在此方法中,read方法将字符读入数组后并不是永久存储,只是暂时存储,并且会被覆盖!
例如:Test.txt中存储的字符为HelloWorld!abcde
。
FileReader fr = null;
fr = new FileReader("Test.txt");
int num = 0;
char[] ch = new char[20];
while((num = fr.read(ch,1,8))!=-1) {
System.out.println(new String(ch,0,5));
}
数组中的变化结果如下:
第一次返回值不为-1
[ ,H,e,l,l,o,W,o,r, ]
输出结果:
Hell
第二次返回值不为-1
[ ,l,d,!,a,b,c,d,e, ]
输出结果:
ld!a
第三次返回值为-1
由上方代码可知数组的作用只是暂存,并不是永久存储
,read方法中参数int off
是指存入数组中的位置,new String
构造方法中参数int off
是指读取数组中参数的起始位置。
所以推荐写法如下:
public static void main(String[] args) {
FileReader fr = null;
try {
//此处需要try...catch来捕获文件未找到异常
fr = new FileReader("Test.txt");
int len = 0;
char[] ch = new char[10];
//当read方法读取完数据后会返回-1,所以我们使用while循环判断
//此处需要try...catch来捕获IO流异常
//这里使用read方法将指定长度的字符读入到数组中指定位置
while((len = fr.read(ch))!=-1) {
//此处指定输出存入char数组中的字符
System.out.print(new String(ch,0,len));
System.out.println();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
//这里没有重新try...catch,而是使用try...catch...catch
}catch (IOException e) {
e.printStackTrace();
}finally {
if(fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
步骤:
①创建字符输入流对象
②创建字符输出流对象
③将输入流的数据写入输出流中
④关闭资源
public class CopyFileTest {
public static void main(String[] args) {
copyFile();
}
public static void copyFile() {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("Test.txt");
fw = new FileWriter("AAA.txt",true);
int len = 0;
char[] ch = new char[1024];
while((len = fr.read(ch)) != -1) {
fw.write(len);
fw.flush();
}
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally{
if(fr != null && fw != null) {
try {
fr.close();
fw.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
}
其中对于写入的代码可以有另一种方式
public class CopyFileTest {
public static void main(String[] args) {
copyFile();
}
public static void copyFile() {
FileReader fr = null;
FileWriter fw = null;
try {
fr = new FileReader("Test.txt");
fw = new FileWriter("AAA.txt",true);
//从这里开始使用了另外一种方式
int num = 0;
while((num = fr.read()) != -1) {
fw.write();
fw.flush();
}
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally{
if(fr != null && fw != null) {
try {
fr.close();
fw.close();
}catch(IOException e) {
e.printStackTrace();
}
}
}
}
}
BufferedWriter:高效缓冲区输出流。
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
BufferedWriter(Writer out)
创建使用默认大小的输出缓冲区的缓冲字符输出流。
---------------------------------------------------------------------------------
BufferedWriter(Writer out, int sz)
创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。
---------------------------------------------------------------------------------
由于FileWriter与BufferedWriter都继承与Writer,所以方法基本都一致,有一个BufferedWriter自己的常用扩展方法。
void newLine()
写一行行分隔符。(相当于之前讲的换行("\r\n"))
例:
public static void main(String[] args) {
FileWriter fw = null;
BufferedWriter bw = null;
try {
//创建输出流
fw = new FileWriter("Test.txt");
//创建高效缓冲区输出流
bw = new BufferedWriter(fw);
//当需要指定缓冲大小时,需要使用此构造器
// bw = new BufferedWriter(fw,1024);
//将目标数据写入文件
bw.write("测试写入,写入成功!");
//写入一个换行符
bw.newLine();
bw.write("测试写入,写入成功!");
//清空缓冲区
bw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(bw != null) {
try {
//当关闭BufferWriter时会自动关闭FileWriter
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
BufferedReader:高效缓冲区输入流。从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
BufferedReader(Reader in)
创建使用默认大小的输入缓冲区的缓冲字符输入流。
---------------------------------------------------------------------------------
BufferedReader(Reader in, int sz)
创建使用指定大小的输入缓冲区的缓冲字符输入流。
---------------------------------------------------------------------------------
public static void main(String[] args) {
FileReader fr = null;
BufferedReader br = null;
try {
// 创建输入流
fr = new FileReader("Test.txt");
// 创建高效缓冲区输入流
br = new BufferedReader(fr);
int num = -1;
char[] ch = new char[1024];
// 判断是否读取到文件内容的末尾
while((num = br.read(ch)) != -1) {
// 使用String构造器打印所读取到的数据
System.out.println(new String(ch,0,num));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally {
if(br != null) {
try {
// 关闭高效缓冲区输入流,释放资源
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
由于FileReader与BufferedReader都继承与Reader,所以方法基本都一致,有一个BufferedReader自己的常用扩展方法。
String readLine()
读取一个文本行。 (当没有足够数据时会返回null)
例:
public static void main(String[] args) {
FileReader fr = null;
BufferedReader br = null;
try {
// 创建输入流
fr = new FileReader("Test.txt");
// 创建高效缓冲区输入流
br = new BufferedReader(fr);
String line = null;
// 判断数据是否为空
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}finally {
if(br != null) {
try {
// 关闭高效缓冲区输入流,释放资源
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
步骤:
①创建字符输入流对象
②创建高效缓冲区的输入流对象
③创建字符输出流对象
④创建高效缓冲区的输出流对象
⑤读取数据并写入到另一个文件中
⑥释放资源
public class BufferCopyTest {
public static void main(String[] args) {
copyFiles();
}
public static void copyFiles() {
// 创建字符输入流对象
FileReader fr = null;
// 创建高效缓冲区输入流对象
BufferedReader bfr = null;
// 创建字符输出流对象
FileWriter fw = null;
// 创建高效缓冲区输出流对象
BufferedWriter bfw = null;
try {
fr = new FileReader("Test.txt");
bfr = new BufferedReader(fr);
fw = new FileWriter("AAA.txt");
bfw = new BufferedWriter(fw);
String str = null;
// 使用readLine方法,并判断是否为空
while((str = bfr.readLine()) != null) {
// 将数据输出到目标文件中
bfw.write(str);
// 当源文件中有换行时副本文件也会换行
bfw.newLine();
}
// 刷新缓冲区
bfw.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally {
if(bfw != null && bfr != null) {
try {
// 关闭输入、输出流,释放资源
bfr.close();
bfw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}