I/O是Input/Output的缩写,用于处理设备之间的数据传输。
Java程序中,对于数据的输入/输出操作”流(stream)"的方式进行
Java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据
- 按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
- 按数据流的流向不同分为:输入流,输出流
- 按流的角色的不同分为:节点流,处理流
- Java的IO流共涉及40多个类,实际上是从如下4个抽象基类派生的。
- 由着四个类派生出来的子类名称都是以其父类名作为子类名后缀。
抽象基类 字节流 字符流 输入流 InputStream Reader 输出流 OutputStream Writer
/** * 一。流的分类 * 1.操作数据单位:字节流,字符流 * 2.数据流的流向:输入流,输出流 * 3.流的角色:节点流,处理流 * * 二。流的体系结构 * 抽象基类 节点流(文件流) 缓冲流 * InputStream FileInputStream BufferedInputStream * OutPutStream FileOutputStream BufferedOutputStream * Reader FileReader BufferedReader * Writer FileWriter BufferedWriter */
File文件的读取
public void testFileReader(){
FileReader fr = null;
try {
//1.实例化File类的对象,指明要操作的文件
//相较于当前的module
File file = new File("hello.txt");
//2.提供具体的流
fr = new FileReader(file);
//3.数据的读入
//read():返回读入的一个字符。如果达到文件末尾,返回-1
int data = fr.read();
while (data != -1){
System.out.print((char)data);
data = fr.read();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//4.流的关闭操作
try {
fr.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
输出结果:
helloworld1
对read()操作升级:使用read的重载方法
注意,一开始设置数组的读取长度,可能遇见文件最后一段长度没有数组长度长,所以不能直接 数组.length(),每次读取都是覆盖上一次数组的内容,所以如果最后一次我文件读取长度不够没有完全覆盖会读出来脏数据。
所以通过每次读取的length变量来判断
//对read()操作升级:使用read的重载方法
@Test
public void testFileReader1() {
FileReader fileReader = null;
try {
//1.File类的实例化
File file = new File("hello.txt");
//2.FileReader流的实例化
fileReader = new FileReader(file);
//3.读入的操作
//read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,则返回-1
char [] cbuf = new char[5];
//4.资源的关闭
int len;
while ((len = fileReader.read(cbuf))!=-1){
//一种是for循环输出
for (int i=0;i<len;i++){
System.out.println(cbuf[i]);
}
//一种是转换为String类型
String str = new String(cbuf,0,len);
System.out.println(str);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fileReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
输出结果:
hellohello
worldworld
11
FileWritre文件的写入
/** * 从内存张写出数据到硬盘的文件里。 * * 说明: * 1.输出操作,对应的File可以不存在的。并不会报错 * 2. * File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件 * File对应的硬盘中的文件如果存在: * 如果流使用的构造器是:FileWriter(file,false)/FileWriter(file):对原有文件的覆盖 * 如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有的基础上追加内容 */大家注意,fileWriter的执行顺序!!!!!!!!!!!!!
@Test
public void testFileWriter() throws IOException {
//1.提供File类的对象,指明写出到的文件
File file = new File("hello1.txt");
//2.提供FileWriter的对象,用于数据的写出
FileWriter fileWriter = new FileWriter(file);
FileWriter fileWriter1 = new FileWriter(file,true);
//3.写出的操作
fileWriter.write("I have a dream ! \n");
fileWriter1.write("I have a dream aaaaaa! \n");
fileWriter.write("you need Fucking dream too!");
//4.流资源的关闭
fileWriter.close();
fileWriter1.close();
}
FileReader和FileWriter实现简单的文件复制(文本文件)
@Test
public void testFileReaderFileWriter(){
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
//1.创建File类的对象,指明读入和写出的文件
File srcFile = new File("hello.txt");
File srcFile1 = new File("hello1.txt");
//2.创建输入流和输出流的对象
fileReader = new FileReader(srcFile);
fileWriter = new FileWriter(srcFile1,true);
//3.数据的读入和写出操作
char[] charbuff = new char[5];
int len;
while ((len=fileReader.read(charbuff)) != -1){
fileWriter.write(new String(charbuff,0,len));
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
//4.关闭流资源
try {
fileReader.close();
fileWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
测试FileInputStream和FileOutputStream的使用
* 结论: * 1。对于文本文件(。txt,.java,.c,.cpp),使用字符流处理 * 2.对于非文本文件(.jpg,mp3,.mp4,.avi,.doc,.ppt),使用字节流处理
public class FileInputOutputStreamTest {
//使用字节流FileInputStream处理文本文件是可能出现乱码的,中文情况
@Test
public void testFileInputStream(){
FileInputStream fp = null;
try {
File file = new File("hello.txt");
fp = new FileInputStream(file);
byte[] buffer = new byte[5];
int len;
while ((len=fp.read(buffer))!=-1){
System.out.print(new String(buffer,0,len));
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fp.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
输出结果:helloworld1在���啊与目标
缓冲流的使用BufferedInputStream BufferedOutputStream
/** * 处理流之一:缓冲流的使用 * 1.缓冲流: * BufferedInputStream * BufferedOutputStream * BufferedReader * BufferedWriter * * 2.作用:提高流的读取,写入的速度 * */关闭外层流的时候,会自动关闭内层流,所以可以省略关闭内层流的那一步
/**
* 实现非文本文件的复制
*/
@Test
public void BufferedStreamTest(){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
BufferedInputStream bist = null;
BufferedOutputStream bost = null;
try {
//1.造文件
File file = new File("2.jpg");
File file1 = new File("1.jpg");
//2.造流
fileInputStream = new FileInputStream(file);
fileOutputStream = new FileOutputStream(file1);
//2.1造缓冲流
bist = new BufferedInputStream(fileInputStream);
bost = new BufferedOutputStream(fileOutputStream);
//3.复制的细节:读取,写入
byte[] bytes = new byte[10];
int len;
while ((len=bist.read(bytes))!=-1){
bost.write(bytes,0,len);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
//4.关闭流
//要求:先关闭外层的流,在关闭内层的流
bist.close();
bost.close();
//说明:关闭外层的流的同时,内层流也会自动的关闭,所以关闭内层流的关闭可以省略
//fileInputStream.close();
//fileOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
缓冲流与节点流的对比
/**
* 实现非文本文件的复制 缓冲流
*/
@Test
public void BufferedStreamTest(){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
BufferedInputStream bist = null;
BufferedOutputStream bost = null;
try {
//1.造文件
File file = new File("1.jpg");
File file1 = new File("4.jpg");
//2.造流
fileInputStream = new FileInputStream(file);
fileOutputStream = new FileOutputStream(file1);
//2.1造缓冲流
bist = new BufferedInputStream(fileInputStream);
bost = new BufferedOutputStream(fileOutputStream);
//3.复制的细节:读取,写入
byte[] bytes = new byte[10];
int len;
while ((len=bist.read(bytes))!=-1){
bost.write(bytes,0,len);
//bost.flush(); 刷新缓冲区
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
//4.关闭流
//要求:先关闭外层的流,在挂你不内层的流
bist.close();
bost.close();
//说明:关闭外层的流的同时,内层流也会自动的关闭,所以关闭内层流的关闭可以省略
//fileInputStream.close();
//fileOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
//实现文件复制的方法 节点流
public void copyFileWithBuffered(String srcPath,String destPath){
FileInputStream fip = null;
FileOutputStream fop = null;
try {
File srcFile = new File(srcPath);
File destFile = new File(destPath);
fip = new FileInputStream(srcFile);
fop = new FileOutputStream(destFile);
byte[] buffer = new byte[10];
int len;
while ((len = fip.read(buffer)) != -1){
fop.write(buffer,0,len);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fip.close();
fop.close();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
fip.close();
fop.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
@Test
public void testCopyFileWithBuffer(){
long start = System.currentTimeMillis();
String srcPath="1.jpg";
String destPath="3.jpg";
copyFileWithBuffered(srcPath,destPath);
long end = System.currentTimeMillis();
System.out.println(end-start);
long start1 = System.currentTimeMillis();
BufferedStreamTest();
long end1 = System.currentTimeMillis();
System.out.println(end1-start1);
}
输出结果:
403
10
使用BufferedReader和BufferedWriter实现文本文件的复制
public void testBufferedReaderBufferedWriter(){
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
bufferedReader = new BufferedReader(new FileReader(new File("hello.txt")));
bufferedWriter = new BufferedWriter(new FileWriter(new File("bufferread.txt")));
//方式一:使用[char]数组
//int len;
//char[] c =new char[5];
//
//while ((len=bufferedReader.read(c))!=-1){
// bufferedWriter.write(new String(c),0,len);
//}
//方式二:使用string readline读取一行
String data;
while((data = bufferedReader.readLine())!=null){
//方法一 实现换行
//bufferedWriter.write(data+"\n");
//方法二 实现换行
bufferedWriter.write(data);
bufferedWriter.newLine();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
bufferedReader.close();
bufferedWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
处理流之二:转换流的使用
/** * 处理流之二:转换流的使用 * 1.转换流:属于字符流 * InputStreamReader:将一个字节的输入流转换成字符的输入流 * OutputStreamWriter:将一个字符的输出流转换为字节的输出流 * 2.作用:提供字节流与字符流之间的转换 * * 3.解码:字节,字节数组-->转换为字符串,字符数组 * 编码:字符串,字符数组-->转换为字节,字节数组 */
InputStream实现字节流到字符流的转换
/**
*InputStream实现字节流到字符流的转换
*/
@Test
public void test1() throws IOException {
FileInputStream fip = new FileInputStream("hello.txt");
//使用系统默认字符集
//InputStreamReader inputStreamReader = new InputStreamReader(fip);
//选择自己所需的字符集
InputStreamReader inputStreamReader = new InputStreamReader(fip,"utf-8");
char[] c = new char[20];
int len;
while ((len=inputStreamReader.read(c))!= -1){
String str = new String(c,0,len);
System.out.println(str);
}
inputStreamReader.close();
}
综合使用InputStream和OutputStreamWriter,实现写入编码格式改变
/**
* 综合使用InputStream和OutputStreamWriter
*/
@Test
public void test2(){
InputStreamReader isr = null;
OutputStreamWriter osw = null;
try {
File file1 = new File("hello.txt");
File file2 = new File("hello-copy.txt");
FileInputStream fileInputStream = new FileInputStream(file1);
FileOutputStream fileOutputStream = new FileOutputStream(file2);
isr = new InputStreamReader(fileInputStream,"utf-8");
osw = new OutputStreamWriter(fileOutputStream,"GBK");
char[] c = new char[5];
int len;
while ((len = isr.read(c))!=-1){
osw.write(c,0,len);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
isr.close();
osw.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}