目录
需要笔记的可以关注私聊我发给你
IO流
学习IO流的目的?
1,将数据写到文件中,实现数据永久化存储
2,把文件中的数据读取到内存中(Java程序)
3,在网络中数据的传输
IO流概述
I 表示intput ,是数据从硬盘进内存的过程,称之为读数据。
O 表示output ,是数据从内存到硬盘的过程。称之为写数据
IO流分类
按流向区分
输入流
输出流
按类型区分
字节流
操作所有类型的文件
包括音视频,图片等
字符流
只能操作完成纯文本文件
包括java文件,txt文件
字节输出流
字节流写数据步骤
1.创建字节输出流对象
注意事项:
如果文件不存在,就创建。
如果文件存在就清空。
// 1 创建字节输出流对象
// public FileOutputStream(String name) : 往String类型的路径中写入数据
// 如果字节输出流指向的不存在 , 会创建一个空的文件
// 如果字节输出流指向的文件存在 , 会把文件内容清空
FileOutputStream fos = new FileOutputStream("day10_demo\\abc.txt");
2.写数据
注意事项:
写出的整数,实际写出的是整数在码表上对应的字符
// 2 写数据
fos.write(97);
fos.write(98);
3.释放资源
注意事项:
每次使用完流必须要释放资源
// 3 释放资源
fos.close();
package com.itheima.outputstream_demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
字节输出流写数据快速入门
第一部分 : 字节输出流类
OutputStream类 : 字节输出流最顶层的类 , 抽象类
public class FileOutputStream extends OutputStream
第二部分 : 构造方法
FileOutputStream类 :
public FileOutputStream(File file) : 往file类型的路径中写入数据
public FileOutputStream(String name) : 往String类型的路径中写入数据
第三部分 : 字节输出流步骤
1 创建字节输出流对象
2 写数据
3 释放资源
'a' = 97 ...
'A' = 65 ...
'0' = 48 ...
*/
public class OutputStreamDemo1 {
public static void main(String[] args) throws IOException {
// 1 创建字节输出流对象
// public FileOutputStream(String name) : 往String类型的路径中写入数据
// 如果字节输出流指向的不存在 , 会创建一个空的文件
// 如果字节输出流指向的文件存在 , 会把文件内容清空
FileOutputStream fos = new FileOutputStream("day10_demo\\abc.txt");
// 2 写数据
fos.write(97);
fos.write(98);
fos.write(99);
// while(true){}
// 3 释放资源
fos.close();
}
}
创建字节输出流对象 , 会不会自动创建文件 ?
如果文件不存在,会自动创建一个文件
如果文件存在 , 会把文件中的内容清空
字节流写数据的三种方式
void write(int b) 一次写一个字节数据
// void write(int b) 一次写一个字节数据
fos.write('a');// 'a' --- 97 --- 写到文件中 --- 文件在把97转成 'a'
void write(byte[] b) 一次写一个字节数组数据
//2 void write(byte[] b) 一次写一个字节数组数据
byte[] bys = {65, 66, 67, 68, 69};
fos.write(bys);
void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据
byte[] bys = {65, 66, 67, 68, 69};
// 3 void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据
fos.write(bys , 1 , 3);
//从bys的2索引开始写3个元素
把字符串转成字节数组写入文件
fos.write("abc".getBytes());
字节流写数据换行与追加
字节流写数据如何实现换行呢?
写完数据后,加换行符
windows : \r\n
linux : \n
mac : \r
for (int i = 0; i < 10; i++) {
fos.write("hello".getBytes());
fos.write("\r\n".getBytes());
}
结果:
hello
hello
hello
......
package com.itheima.outputstream_demo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
/*
字节流写数据的换行和追加写入
1 字节流写数据如何实现换行呢?
写完数据后,加换行符
windows : \r\n
linux : \n
mac : \r
2 字节流写数据如何实现追加写入呢?
通过构造方法 : public FileOutputStream(String name,boolean append)
创建文件输出流以指定的名称写入文件。如果第二个参数为true ,不会清空文件里面的内容, 追加写数据
*/
public class OutputStreamDemo3 {
public static void main(String[] args) throws IOException {
// 通过构造方法 : public FileOutputStream(String name,boolean append)
FileOutputStream fos = new FileOutputStream("day10_demo\\a.txt", true);
// 写数据
// fos.write("abcdfghjkl".getBytes());
for (int i = 0; i < 10; i++) {
fos.write("hello".getBytes());
fos.write("\r\n".getBytes());
}
// 释放资源
fos.close();
}
}
字节流写数据如何实现追加写入呢?
public FileOutputStream(String name,boolean append)
创建文件输出流以指定的名称写入文件。如果第二个参数为true ,不会清空文件里面的内容
FileOutputStream fos = new FileOutputStream("day10_demo\\a.txt", true);
字节输入流
字节流读数据(一次读一个字节)步骤
创建字节输入流对象。
注意事项:
如果文件不存在,就直接报错
// 1 创建输入流对象
// 输入流指向的文件, 如果不存在直接抛出异常
FileInputStream fis = new FileInputStream("day10_demo\\a.txt");
读数据
注意事项:
读出来的是文件中数据的码表值。 a -> 97
//每次读一个字节:
by = fis.read();
System.out.println(by);
//一直读文件:
// 掌握!
// 记录的是每次读到的字节数据
int by;
while( (by = fis.read()) != -1 ){
System.out.println(by);
}
释放资源
注意事项:
每次使用完流必须要释放资源。
//一直读文件:
// 掌握!
// 记录的是每次读到的字节数据
int by;
while( (by = fis.read()) != -1 ){
System.out.println(by);
}
案例:复制文件
需求:把“xxx.jpg”复制到当前模块下
分析:
复制文件,其实就把文件的内容从一个文件中读取出来(数据源),然后写入到另一个文件中(目的地)
数据源:xxx.jpg --- 读数据 --- FileInputStream
目的地:模块名称\\copy.jpg --- 写数据 --- FileOutputStream
public class FileInputStreamDemo2 {
public static void main(String[] args) throws IOException {
// 创建字节输入流
FileInputStream fis = new FileInputStream("D:\\传智播客\\安装包\\IO资源 图片\\liqin.jpg");
// 创建字节输出流
FileOutputStream fos = new FileOutputStream("day10_demo\\copy.jpg");
// 一次读写一个字节
int by;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 释放资源
fis.close();
fos.close();
}
}
IO资源的处理
JDK7前后对比
JDK7版本前捕获处理异常
使用try...catch...finally , 把释放资源操作,放在
finally代码块中,虽然一定可以释放资源
但是属于手动释放资源 , 但是代码过于复杂
package com.itheima.inputstream_demo;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
JDK7版本之前处理方式 :
try...catch ...finally
*/
public class FileInputStreamDemo4 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// System.out.println(3 / 0);
// 创建字节输入流
fis = new FileInputStream("D:\\传智播客\\安装包\\IO资源 图片\\liqin.jpg");
// 创建字节输出流
fos = new FileOutputStream("day10_demo\\copy.jpg");
// 一次读写一个字节
int by;
while ((by = fis.read()) != -1) {
fos.write(by);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fis != null && fos != null) {
try {
// 释放资源
fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
JDK7版本捕获处理异常优化
使用try-with-resource , 需要把流对象放在try的小扩中 , 流资源在使用完毕 , 会自动释放资源 , 代码相对于做了简化
package com.itheima.inputstream_demo;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
JDK7版本优化处理方式
1 JDK7优化后可以使用 try-with-resource 语句 , 该语句确保了每个资源在语句结束时自动关闭。
2 简单理解 : 使用此语句,会自动释放资源 , 不需要自己在写finally代码块了
格式 :
try (创建流对象语句1 ; 创建流对象语句2 ...) {
// 读写数据
} catch (IOException e) {
处理异常的代码...
}
注意 :
使用前提 , 资源的类型必须是AutoCloseable接口的实现类
需求 : 对上一个复制图片的代码进行使用捕获方式处理
*/
public class FileInputStreamDemo3 {
public static void main(String[] args) {
try (
// 创建字节输入流
FileInputStream fis = new FileInputStream("D:\\传智播客\\安装包\\IO资源 图片\\liqin.jpg");
// 创建字节输出流
FileOutputStream fos = new FileOutputStream("day10_demo\\copy.jpg");
) {
// 一次读写一个字节
int by;
while ((by = fis.read()) != -1) {
fos.write(by);
}
// 释放资源
// fis.close();
// fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
字节输入流-读字节数组
提高拷贝速度的解决方案
public int read(byte[] b):
1 从输入流读取最多b.length个字节的数据
2 返回的是真实读到的数据个数
3 如果不到数据 , 那么会返回-1
String类
public String(byte[] bys) : 把字节数组中的内容转成一个字符串
public String(byte[] bytes, int startIndex, int length) : 把字节数组的一部分转成字符串
需求1 : 在当前模块下创建一个文件 , 文件存储数据hello world , 定义长度为5的字节数组进行读取数据
public class FileInputStreamDemo5 {
public static void main(String[] args) throws IOException {
// 创建字节输入流对象
FileInputStream fis = new FileInputStream("day10_demo\\abc.txt");// 2000字节
// 一次读一个字节数组
byte[] bys = new byte[1024];// 1024数据 976
// 记录的是每次真实读到数据的个数
int len;// 976
while ((len = fis.read(bys)) != -1) {
System.out.print(new String(bys, 0, len));
}
// 释放资源
fis.close();
}
}
字节流缓冲流
BufferOutputStream:缓冲输出流
字节缓冲输出流:BufferedOutputStream(OutputStream out)
BufferedInputStream:缓冲输入流
字节缓冲输入流:BufferedInputStream(InputStream in)
为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
字节缓冲流仅仅提供缓冲区,不具备读写功能 , 而真正的读写数据还得依靠基本的字节流对象进行操作
需求 : 使用缓冲流进行复制文件
数据源 : D:\传智播客\安装包\好看的图片\liqin2.jpg
目的地 : day11_demo\copy.jpg
public class BufferedStreamDemo1 {
public static void main(String[] args) throws IOException {
// 字节缓冲输出流:BufferedOutputStream(OutputStream out)
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day10_demo\\a.txt"));
bos.write(97);
bos.close();
// 字节缓冲输入流:BufferedInputStream(InputStream in)
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day10_demo\\a.txt"));
int by;
while((by = bis.read()) != -1){
System.out.print(by);
}
bis.close();
}
}
案例:复制视频
需求:把“xxx.avi”复制到模块目录下的“copy.avi” , 使用四种复制文件的方式 , 打印所花费的时间
基本的字节流一次读写一个字节
public class BufferedStreamDemo2 {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
method1();
long end = System.currentTimeMillis();
System.out.println(end-start);
}
//1 基本的字节流一次读写一个字节
private static void method1() throws IOException {
//创建字节输入流
FileInputStream fis = new FileInputStream("day10_demo\\copy.wmv");
//创建字节输出流
FileOutputStream fos = new FileOutputStream("day10_demo\\统计文件个数文件夹\\copy.wmv");
int by;//一次写一个字节数组
while ((by=fis.read())!=-1){
fos.write(by);
}
//释放流
fis.close();
fos.close();
}
基本的字节流一次读写一个字节数组
private static void method2() throws IOException {
//创建字节输入流
FileInputStream fis1 = new FileInputStream("day10_demo\\copy.wmv");
//创建字节输出流
FileOutputStream fos1 = new FileOutputStream("day10_demo\\统计文件个数文件夹\\copy.wmv");
//一次读一个字节数组
byte[] but = new byte[1024];
int len;
while ((len=fis1.read(but))!=-1){
fos1.write(but,0,len);
}
//释放资源
fis1.close();
fos1.close();
}
缓冲流一次读写一个字节
private static void method3() throws IOException {
//创建高效字节输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day10_demo\\copy.wmv"));
//创建高效字节输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day10_demo\\统计文件个数文件夹\\copy.wmv"));
int but;//每次写一个字节
while ((but= bis.read())!=-1){
bos.write(but);
}
//释放锁
bis.close();
bos.close();
}
缓冲流一次读写一个字节数组
private static void method4() throws IOException {
//创建高效字节输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("day10_demo\\copy.wmv"));
//创建高效字节输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("day10_demo\\统计文件个数文件夹\\copy.wmv"));
byte[] but = new byte[1024];
int len;//每次写一个字节
while ((len= bis.read(but))!=-1){
bos.write(but,0,len);
}
//释放锁
bis.close();
bos.close();
}