一,I/O流概述
I/O流简单的理解就是数据的输入与输出;那数据的的输入与输出又怎么理解呢?
首先我们知道,所有的数据在计算机中都是以二进制的形式存储的.我们看到的字节或者字符形式的文件都是计算机经过解析之后形成的.
那么数据的输入与输出简单地说,就是我们向计算机(通信设备)存数据和取数据的方式,这种方式包括两种,一种是字节形式的存取,一种是字符形式的存取.
那什么时候用字节,什么时候用字符呢?这是我们今天讨论的重点.
二,I/O流的体系(字符流)
如图:
I/O流的体系非常之庞大.但是我们从体系的顶层向下看的话,其实还是很好掌握的;
1)我们从体系图中可以看出
I/O流按照输入和输出来分就是:
输入流:
字节输入流:InputStream
字符输入流:Reader
输出流:
字节输出流:OutputStream
字符输出流:Writer
2)了解的内容:
当处理纯文本内容时,建议使用字符流;
当处理图像,音频文件时,使用字节流;
三,体系解析:
3.1 字符流操作文本文件:
示例1:向计算机硬盘中写入些文字;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterDemo {
//因为考虑到不同系统的的换行符号不一致,所以我们直接调用系统的换行设置
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static void main(String[] args) throws IOException {
//注意当我这里后面不加true的话,表示多次向文件添加内容是,内容无法追加,每写一次都会把上次的内容覆盖掉;
FileWriter fw=new FileWriter("E:\\IO测试\\demo.txt",true);
fw.write("Hello World"+LINE_SEPARATOR+"I LOVE JAVA");
fw.write(LINE_SEPARATOR+"pierce");
//注意要刷新,否则,无法写入内容(前提是流没有关闭)
fw.flush();
//关闭流通道;
fw.close();
}
}
//注意:
关闭流,必须先刷新此流,一旦关闭后,就不能再写数据,和调用flush方法;
假如,我在fw.close()后面,在写一个fw.write("Hello");会报错;
示例二:从计算机指定文件读取数据,输出在控制台上;
方式一:一次读取单个字符的方式,读取文件
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
//创建一个要读取的文件对象
FileReader fr=new FileReader("E:\\IO测试\\demo.txt");
//定义一个变量,用于存储每次读到的那个字符对应的数字
int ch=0;
//每次读一个,读到文件末尾时,返回一个-1,表示文件已经读取完毕;
while((ch=fr.read())!=-1){
//将每次读到的一个字符输出
System.out.print((char)ch);
}
//关闭流通道;
fr.close();
}
}
方式二: 一次读取多个字符的方式,读取文件
import java.io.FileReader;
import java.io.IOException;
public class FileReaderDemo2 {
public static void main(String[] args) throws IOException {
//创建一个要读取的文件对象
FileReader fr=new FileReader("E:\\IO测试\\demo.txt");
//创建一个字符数组,用于存储每次读到的数据
char []ch=new char[1024];//注意这里统一使用计算机的千字节数的整数倍
//读到文件末尾的标记;
int len=0;
while((len=fr.read(ch))!=-1){
//最后一次只需读取有效数据即可
System.out.println(new String(ch,0,len));
}
}
}
方式三,使用高效缓冲流,向文件中写数据;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferWriterDemo {
public static void main(String[] args) throws IOException {
//目标对象
FileWriter fw=new FileWriter("D:\\demo.txt");
//
BufferedWriter bw=new BufferedWriter(fw);
for (int i = 0; i < 4; i++) {
bw.write("嘻嘻");
//BufferedWriter的自有换行操作
bw.newLine();
bw.flush();
}
bw.close();
}
}
方式四:使用高效率流从文件中读取数据;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class BufferReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("D:\\demo.txt");
BufferedReader br=new BufferedReader(fr);
//定义一个变量,用于存储每次读到一行数据;
String line=null;
//当读到文件末尾时,返回null,就结束读取操作
while((line=br.readLine())!=null){
System.out.println(line);
}
}
}
我们已经学会了上面的五中操作方法,都是单方向的操作文件;下面我们来复制一个文件到指定路径下;
案例:复制文件操作:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedTest_CopyFile {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("D:\\demo.txt");
BufferedReader br=new BufferedReader(fr);
FileWriter fw=new FileWriter("E:\\T.txt");
BufferedWriter bw=new BufferedWriter(fw);
String line=null;
//读一行写一行
while((line=br.readLine())!=null){
bw.write(line);
bw.newLine();
bw.flush();
}
//当然,我们也可以一个字节,一个字节的读,或者每次读一个数组长度的方式去读取文件;
/*
* 单字符读取的1方式;
* int ch=0;
* while((ch=br.read())!=-1){
* bw.write(ch);
* }
*/
//读
/* char []char=new char[1024*4];
* int len;
* while((len=br.read(char))!=-1){
* bw.write(char,0,len);
* bw.flush();
* }
*/
bw.close();
br.close();
读取文件时,I/O流异常的处理方式:
import java.io.FileWriter;
import java.io.IOException;
public class IOExceptionDemo {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static void main(String[] args) {
FileWriter fw =null;//在try外面声明引用型变量,再处理异常时再初始化变量;
try {
fw = new FileWriter("E:\\IO测试\\demo.txt",true);
fw.write("Hello World"+LINE_SEPARATOR+"I LOVE JAVA");
fw.write(LINE_SEPARATOR+"pierce");
fw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(fw!=null)//如果写入过程中,出现意外,也要关闭流通道;
try {
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
throw new RuntimeException("关闭失败..");
}
}
}
}
//下面我们看下一个有趣的流:LineNumberReader,它可以拿到每一行文字对应的行号:
//跟踪行号的缓冲字符输入流
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
public class LineNumberReaderDemo {
public static void main(String[] args) throws IOException {
FileReader fr=new FileReader("D:\\d.txt");
LineNumberReader inr=new LineNumberReader(fr);
String line=null;
while((line=inr.readLine())!=null){
System.out.println(inr.getLineNumber()+":"+line);
}
inr.close();
}
}
3.2)转换流操作:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class TransStreamDemo2 {
public static void main(String[] args) throws IOException {
//字节流
//InputStream in=System.in;
//字节转换为字符的桥梁,转换流;
//InputStreamReader isr=new InputStreamReader(in);
//字符流;
//BufferedReader br=new BufferedReader(isr);
//OutputStream out=System.out;
//OutputStreamWriter osw=new OutputStreamWriter(out);
//BufferedWriter bw=new BufferedWriter(osw);
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
// BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\insert.txt")));
String line=null;
while((line=br.readLine())!=null){
if("over".equals(line))
break;
bw.write(line.toUpperCase());
bw.newLine();
bw.flush();
}
}
}
/*
* 如果操作文本需要明确具体的编码,必须要转换流
*
* */
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class TransStreamDemo4 {
public static void main(String[] args) throws Exception {
readText2();
}
private static void readText2() throws Exception, IOException {
InputStreamReader fr=new InputStreamReader(
new FileInputStream("D:\\u8_1.txt"), "UTF-8");
char []ch=new char[10];
int len=fr.read(ch);
String str=new String(ch,0,len);
System.out.println(str);
fr.close();
}
private static void readText3() throws Exception {
FileReader fr=new FileReader("D:\\u8_1.txt");
char []ch=new char[10];
int len=fr.read(ch);
String str=new String(ch,0,len);
System.out.println(str);
fr.close();
}
private static void writeText3() throws IOException, FileNotFoundException {
OutputStreamWriter osw=new OutputStreamWriter(
new FileOutputStream("D:\\u8_1.txt"), "UTF-8");
osw.write("小明");
osw.flush();
osw.close();
}
private static void writeText2() throws Exception {
OutputStreamWriter fw=new OutputStreamWriter(
new FileOutputStream("D:\\gbk_1.txt"), "GBK");
fw.write("小明");
fw.flush();
fw.close();
}
private static void writeText() throws IOException {
// TODO Auto-generated method stub
FileWriter fw=new FileWriter("D:\\gbk_1.txt");
//FileWriter其实就是转换流制订了本机默认编码表的体现,可以更好的操作文本;
/*
* 如果操作文本需要明确具体的编码,必须要转换流
*
* */
fw.write("小明");
fw.flush();
fw.close();
}
}
流的操作规律;
自所以要弄清楚这个规律,是因为流的对象太多,开发时不知道用那个对象合适;
想知道开发时用到哪些对象,只要通过四个明确即可;
1,明确源和目的地;(汇)
源:InputStream Reader;
目的: OutputStream Writer
2,明确数据是否是纯文本数据;
源:是:纯文本:Reader
否: InputStream
目的: 是纯文本:Writer
否: OutputStream
到这里就可以明确需求中具体要使用那个体系;
3,明确具体设备;
源设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
目的设备:
硬盘:File
键盘:System.in
内存:数组
网络:Socket流
4,是否需要其他额外功能.
1,是否需要高效(缓冲区);
是:buffer
需求:
1,复制一个文件:
1,明确源和目的:
源:InputStream Reader;
目的:outputStream Writer;
2,是否为纯文本:
是:Reader;
目的:Writer;
3,明确设备:
源:
硬盘:File
目的:
硬盘:File
FileReader fr=new FileReader("a.txt");
FileWriter fw=new FileWriter("b.txt");
4,是否需要额外功能,
需要:
BufferedReader br=new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("a.txt"));
需求:读取键盘录入信息,并写入到一个文件中;
1,明确源和目的.
源:InputStream Reader;
目的:OutputStream Writer;
2,是否是纯文本:
是;
源:Reader
目的:Writer;
3,明确设备;
源:
键盘:System.in
目的:
硬盘:File
InputStream in=System.in;
FileWriter fw=new FileWriter("b.txt");
这样做可以实现,但是麻烦,将读取的字节转换成字符串,再有字符流操作;
4,需要额外功能吗?
需要;转换;
InputStreamReader isr=new InputStreamReader(new InputStreamReader(System.in));
需求3;将一个文本文件数据显示在控制台上;
1,明确源和目的.
源:InputStream Reader;
目的:OutputStream Writer;
2,是否是纯文本:
是;
源:Reader
目的:Writer;
3,明确设备;
源:
硬盘:File
目的:
控制台:System.out
FileReader fr=new FileReader("a.txt");
OutputStream out=System.out;
4,需要额外功能吗?
需要;转换;
FileReader fr=new FileReader("b.txt");
OutputStreamWriter osw=new OutputStreamWriter(System.out);
需要高效:
BufferedReader br=new BufferedReader(new FileReader("b.txt"));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
==================================================================
4,读取键盘录入数据显示在控制台上;
1,明确源和目的.
源:InputStream Reader;
目的:OutputStream Writer;
2,是否是纯文本:
是;
源:Reader
目的:Writer;
3,明确设备;
源:
键盘:System.in
目的:
控制台:System.out
inputStream in=System.in;
OutputStream out=System.out;
4,额外功能?
需要;
需要转化,因为都是字节流,但是操作的确实文本数据.
所以使用字符流操作起来更为便捷;
InputStreamReader isr=new InputStreamReader(System.in);
OutputStreamWriter osw=new OutputStreamWriter(System.out);
为了高效,
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(Sstem.out);
//本人刚入门菜鸟一枚,这些都是自己整理的资料,感觉I/O流体系太过于庞大,学了一些最常用的流操作方法,其他的流操作日后有时间在整理
//以供大家参阅
来源:https://www.cnblogs.com/pierceming/p/8711857.html