I/O全名:Input Output,输入输出的意思
•IO流用来处理设备之间的数据传输
•流操作分两种:字节流,字符流
•流按流向分为:输入流,输出流
•字节流的抽象积累
◦InputStream
◦OutputStream
•字符流的抽象基类
◦Reader
◦Writer
FileWriter
•需求:在硬盘上创建一个文件,并且写入数据
那我们怎么去做?他构造函数比较多的,我们看例子
public class HelloJJAVA {
public static void main(String[] args) {
/** * 需求:在硬盘上创建一个文件,并且写入数据 */
// 一被初始化就必须要有被操作的文件
// 如果不指定位置,就创建在同目录下
// 如果目录下存在同名文件,覆盖
try {
FileWriter fileWriter = new FileWriter("test.txt");
// 写入数据到内存
fileWriter.write("abcde");
// 刷新该流的缓冲
// fileWriter.flush();
// 关闭流 关闭之前会刷新,和flush的区别在于flush刷新后流可以继续工作
fileWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这样在我们的项目根目录下就可以看到生成的文件了
文件续写
我们知道,文件存在的话就会覆盖,但是我们不想这样,我们想在原有的数据中续写,这该去怎么做?
public class HelloJJAVA {
public static void main(String[] args) {
try {
//参数2代表不覆盖已有的文件,支持续写
FileWriter fileWriter = new FileWriter("demo.txt",true);
fileWriter.write("你好");
fileWriter.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
构造传参的时候设置为true就可以续写文件了
FileReader
既然写已经会了,那我们就来读取了
public class HelloJJAVA {
public static void main(String[] args) {
try {
// 创建一个文件读取流对象,和指定名称的文件关联,保证文件存在,
// 如果不存在,异常
FileReader fileReader = new FileReader("demo.txt");
// 读取单个字符,自动往下读
int cd = fileReader.read();
System.out.println((char) cd);
//全部打印
int ch = 0;
while ((ch = fileReader.read()) != -1) {
System.out.println(ch);
}
fileReader.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
这样就可以按照字节读取了,我们也可以把读到的字符存储在数组中
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class HelloJJAVA {
public static void main(String[] args) {
try {
FileReader fileReader = new FileReader("demo.txt");
char[] buf = new char[3];
int num = fileReader.read(buf);
System.out.println("num:" + num + new String(buf));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
文本复制
读写都说了,我们来看下其他的操作,我们首先来看复制
•复制原理:其实就是将C盘下的文件数据存储到D盘的一个文件中
实现的步骤:
1.在D盘创建一个文件,用于存储文件中的数据
2.定义读取流和文件关联
3.通过不断的读写完成数据的存储
关闭资源
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class HelloJJAVA {
public static void main(String[] args) {
copy_1();
copy_2();
}
// 从c盘读一个字符,就往D盘写一个字符
public static void copy_1() {
try {
// 创建目的地
FileWriter fw = new FileWriter("copy_1.txt");
// 与已有文件关联
FileReader fr = new FileReader("copy_1.txt");
int ch = 0;
while ((ch = fr.read()) != -1) {
// 读一个 写一个
fw.write(ch);
}
fw.close();
fr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void copy_2() {
FileWriter fw = null;
FileReader fr = null;
try {
fw = new FileWriter("copy_2.txt");
fr = new FileReader("copy_2.txt");
char[] buf = new char[1024];
int len = 0;
while ((len = fr.read(buf)) != -1) {
fw.write(buf, 0, len);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}}
这里做了两种方式的拷贝方式,其实都是整理好思路,读和写的一个过程罢了!
字符流的缓冲区,提高了对数据的读写效率,他有两个子类
•BufferedWriter
•BufferedReader
我们还是复制文件这个问题,现在我们有缓冲区,我们要怎么样复制文件?
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class HelloJJAVA {
public static void main(String[] args) {
/** * 缓冲区文件复制 */
BufferedReader bufr = null;
BufferedWriter bufw = null;
try {
bufr = new BufferedReader(new FileReader("buffer.txt"));
bufw = new BufferedWriter(new FileWriter("buffercopy.txt"));
String line = null;
while((line = bufr.readLine()) != null){
bufw.write(line);
}
//关闭流
bufr.close();
bufw.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
字节流读取操作
字符流我们讲的差不多了,我们接着说字节,其实他们类似的,知识他操作的是字节而已
•inputStream:读
•outputStream:写
我们还是从例子开始
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class HelloJJAVA {
public static void main(String[] args) {
writeFile();
}
// 写文件
public static void writeFile() {
try {
FileOutputStream fo = new FileOutputStream("demo.txt");
fo.write("test".getBytes());
fo.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
专门处理的字节流
public static void readFile2() {
try {
FileInputStream fs = new FileInputStream("demo.txt");
int num = fs.available();
System.out.println(num);
fs.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
我们发现直接用available就可以拿到字节了,原理其实是这段代码
public static void readFile2() {
try {
FileInputStream fs = new FileInputStream("demo.txt");
byte[] buf = new byte[fs.available()];
fs.read(buf);
System.out.println(new String(buf));
fs.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
字节流的缓冲区
这个,和我们的字符流基本上没有什么差别,我们来拷贝mp3,看例子
// 通过字节流的缓冲区拷贝图片
public static void copyMp3() {
try {
FileInputStream fi = new FileInputStream("audio.mp3");
BufferedInputStream buf = new BufferedInputStream(fi);
FileOutputStream fio = new FileOutputStream("audioCapy.mp3");
BufferedOutputStream buo = new BufferedOutputStream(fio);
int ch = 0;
while ((ch = buf.read()) != -1) {
buo.write(ch);
}
buf.close();
buo.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//这样,就直接拷贝了
转换流InputStreamReader
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class HelloJJAVA {
public static void main(String[] args) throws IOException {
//获取键盘录入对象
InputStream in = System.in;
//转换
InputStreamReader isr = new InputStreamReader(in);
//提高效率
BufferedReader bur = new BufferedReader(isr);
String line = null;
while((line = bur.readLine()) != null){
if(line.equals("over"))
break;
System.out.println(line.toString());
}
}
}
写入转换流
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class HelloJJAVA {
public static void main(String[] args) throws IOException {
//获取键盘录入对象
InputStream in = System.in;
//转换
InputStreamReader isr = new InputStreamReader(in);
//提高效率
BufferedReader bur = new BufferedReader(isr);
OutputStream os = System.out;
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bufw = new BufferedWriter(osw);
String line = null;
while((line = bur.readLine()) != null){
if(line.equals("over"))
break;
bufw.write(line.toString());
bufw.newLine();
bufw.flush();
}
}
}
如何选择流?
◦1.明确源和目的
■源:输入流 InputStream Reader
■目的:输出流 OutputStream writer
◦2.明确操作的数据是否是纯文本
■是:字符流
■不是:字节流