I/O流
IO流就是用来处理设备间数据传输问题的。常见的应用有:文件复制、文件上传、文件下载。
流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输称为流,流的本质是数据传输。
I/O流的分类:
-
按照数据的流向
-
输入流:读数据
-
输出流:写数据
-
-
按照数据类型来分
-
字节流
-
字节输入流
-
字节输出流
-
-
字符流
-
字符输入流
-
字符输出流
-
-
I/O流的使用场景:
-
如果操作的是纯文本文件,优先使用字符流
-
如果操作的是图片、视频、音频等二进制文件。优先使用字节流
-
如果不确定文件类型,优先使用字节流。字节流是万能的流
下面让我们先来了解字节流!!!
字节流
-
字节流抽象基类
-
InputStream:这个抽象类是表示字节输入流的所有类的超类
-
OutputStream:这个抽象类是表示字节输出流的所有类的超类
-
子类名特点:子类名称都是以其父类名作为子类名的后缀
-
-
字节输出流
-
FileOutputStream(String name):创建文件输出流以指定的名称写入文件
-
-
使用字节输出流写数据的步骤
-
创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
-
调用字节输出流对象的写数据方法
-
释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
-
public class FileOutputStreamDemo01 {
public static void main(String[] args) throws IOException {
//创建字节输出流对象
//FileOutputStream(String name):创建文件输出流以指定的名称写入文件
FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt");
/*
做了三件事情:
A:调用系统功能创建了文件
B:创建了字节输出流对象
C:让字节输出流对象指向创建好的文件
*/
//void write(int b):将指定的字节写入此文件输出流
fos.write(97);
// fos.write(57);
// fos.write(55);
//最后都要释放资源
//void close():关闭此文件输出流并释放与此流相关联的任何系统资源。
fos.close();
}
}
字节流写数据的方法分类:
方法名 | 说明 |
void write(int b) | 将指定的字节写入此文件输出流 一次写一个字节数据 |
void write(byte[] b) | 将 b.length字节从指定的字节数组写入此文件输出流 一次写一个字节数组数据 |
void write(byte[] b, int off, int len) | 将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流 一次写一个字节数组的部分数据 |
public class FileOutputStreamDemo02 {
public static void main(String[] args) throws IOException {
//FileOutputStream(String name):创建文件输出流以指定的名称写入文件
FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt");
//FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件
// File file = new File("myByteStream\\fos.txt");
// FileOutputStream fos2 = new FileOutputStream(file);
// FileOutputStream fos2 = new FileOutputStream(new File("myByteStream\\fos.txt"));
//void write(int b):将指定的字节写入此文件输出流
// fos.write(97);
// fos.write(98);
// fos.write(99);
// fos.write(100);
// fos.write(101);
// void write(byte[] b):将 b.length字节从指定的字节数组写入此文件输出流
// byte[] bys = {97, 98, 99, 100, 101};
//byte[] getBytes():返回字符串对应的字节数组
byte[] bys = "abcde".getBytes();
// fos.write(bys);
//void write(byte[] b, int off, int len):将 len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流
// fos.write(bys,0,bys.length);
fos.write(bys,1,3);
//释放资源
fos.close();
}
}
-
字节流写数据如何实现换行
-
windows:\r\n
-
linux:\n
-
mac:\r
-
-
字节流写数据如何实现追加写入
-
public FileOutputStream(String name,boolean append)
-
创建文件输出流以指定的名称写入文件。如果第二个参数为true ,则字节将写入文件的末尾而不是开头
-
public class FileOutputStreamDemo03 {
public static void main(String[] args) throws IOException {
//创建字节输出流对象
// FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt");
FileOutputStream fos = new FileOutputStream("myByteStream\\fos.txt",true);
//写数据
for (int i = 0; i < 10; i++) {
fos.write("hello".getBytes());
fos.write("\r\n".getBytes());
}
//释放资源
fos.close();
}
}
-
异常处理格式
-
try-catch-finally
try{ 可能出现异常的代码; }catch(异常类名 变量名){ 异常的处理代码; }finally{ 执行所有清除操作; }
-
finally特点
-
被finally控制的语句一定会执行,除非JVM退出
-
-
-
字节输入流
-
FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream ,该文件由文件系统中的路径名name命名
-
-
字节输入流读取数据的步骤
-
创建字节输入流对象
-
调用字节输入流对象的读数据方法
-
释放资源
-
public class FileInputStreamDemo01 {
public static void main(String[] args) throws IOException {
//创建字节输入流对象
//FileInputStream(String name)
FileInputStream fis = new FileInputStream("myByteStream\\fos.txt");
int by;
/*
fis.read():读数据
by=fis.read():把读取到的数据赋值给by
by != -1:判断读取到的数据是否是-1
*/
while ((by=fis.read())!=-1) {
System.out.print((char)by);
}
//释放资源
fis.close();
}
}
让我们一起来看一道简单地例题!
题目要求:编写一个应用程序,将用户从键盘输入的10个整数存入文件,再顺序读出。
public class ScannerInt {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("D:\\file\\number.txt");
Scanner sc = new Scanner(System.in);
System.out.println("输入整数:");
for (int i = 0; i < 10; i++) {
String line = sc.nextLine();
fos.write(line.getBytes());
}
fos.flush();
fos.close();
FileInputStream fis = new FileInputStream("D:\\file\\number.txt");
int num;
System.out.println("顺序读出:");
while ((num = fis.read()) != -1) {
System.out.print((char)num+" ");
}
}
}
字节缓冲流
缓冲流
普通流每次读写一个字节,程序与磁盘的交互是不是很多,尤其是数据量过大的时候,程序的效率就会很低。缓冲流就很好的解决了这个问题,缓冲流在内存中设置一个缓冲区,我们把数据先放入缓冲区,缓冲区有一定的大小,等缓冲区满了,再将缓冲区中的数据与磁盘或内存交互,减少了程序与磁盘的交互次数,自然也就提高了程序的效率。
字节缓冲流
-
BufferOutputStream:该类实现缓冲输出流。 通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
-
BufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数组。 当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
构造方法
方法名 | 说明 |
---|---|
BufferedOutputStream(OutputStream out) | 创建字节缓冲输出流对象 |
BufferedInputStream(InputStream in) | 创建字节缓冲输入流对象 |
//使用缓冲流实现a.jpg文件复制为b.jpg文件的操作
public class BufferCopyJpg {
public static void main(String[] args) throws IOException {
BufferedInputStream is=new BufferedInputStream(new FileInputStream("D:\\file\\file1\\file3\\b.jpg"));
BufferedOutputStream os=new BufferedOutputStream(new FileOutputStream("D:\\file\\file1\\file2\\c.jpg"));
//一次读一个字节数组的数据
byte[] bys = new byte[1024];
int len;
while ((len=is.read(bys))!=-1) {
os.write(bys,0,len);
}
//释放资源
os.close();
is.close();
}
}
分别使用字节流和字节缓冲流,实现文本文件/图片/视频文件的复制。
并比较二者在数据复制方面的效率(提示:日期类)
public class CompareCopy {
public static void main(String[] args) throws IOException {
long startTxt1=System.currentTimeMillis();
streamTxt();
long endTxt1=System.currentTimeMillis();
System.out.println(endTxt1-startTxt1);
long startTxt2=System.currentTimeMillis();
bufferedTxt();
long endTxt2=System.currentTimeMillis();
System.out.println(endTxt2-startTxt2);
long startJpg1=System.currentTimeMillis();
streamJpg();
long endJpg1=System.currentTimeMillis();
System.out.println(endJpg1-startJpg1);
long startJpg2=System.currentTimeMillis();
bufferedJpg();
long endJpg2=System.currentTimeMillis();
System.out.println(endJpg2-startJpg2);
long startAvi1=System.currentTimeMillis();
streamAvi();
long endAvi1=System.currentTimeMillis();
System.out.println(endAvi1-startAvi1);
long startAvi2=System.currentTimeMillis();
bufferedAvi();
long endAvi2=System.currentTimeMillis();
System.out.println(endAvi2-startAvi2);
}
public static void streamTxt() throws IOException {
FileInputStream fis=new FileInputStream("D:\\file\\file1\\file3\\test2.txt");
FileOutputStream fos=new FileOutputStream("D:\\file\\file1\\file2\\a.txt");
byte[] bys = new byte[1024];
int len;
while ((len=fis.read(bys))!=-1) {
fos.write(bys,0,len);
}
fos.close();
fis.close();
}
public static void bufferedTxt() throws IOException {
BufferedInputStream is=new BufferedInputStream(new FileInputStream("D:\\file\\file1\\file3\\test3.txt"));
BufferedOutputStream os=new BufferedOutputStream(new FileOutputStream("D:\\file\\file1\\file2\\b.txt"));
byte[] bys = new byte[1024];
int len;
while ((len=is.read(bys))!=-1) {
os.write(bys,0,len);
}
os.close();
is.close();
}
public static void streamJpg() throws IOException {
FileInputStream fis=new FileInputStream("D:\\file\\file1\\file3\\a.jpg");
FileOutputStream fos=new FileOutputStream("D:\\file\\file1\\file2\\a1.jpg");
byte[] bys = new byte[1024];
int len;
while ((len=fis.read(bys))!=-1) {
fos.write(bys,0,len);
}
fos.close();
fis.close();
}
public static void bufferedJpg() throws IOException {
BufferedInputStream fis=new BufferedInputStream(new FileInputStream("D:\\file\\file1\\file3\\b.jpg"));
BufferedOutputStream fos=new BufferedOutputStream(new FileOutputStream("D:\\file\\file1\\file2\\b1.jpg"));
byte[] bys = new byte[1024];
int len;
while ((len=fis.read(bys))!=-1) {
fos.write(bys,0,len);
}
fos.close();
fis.close();
}
public static void streamAvi() throws IOException {
FileInputStream fis=new FileInputStream("D:\\file\\file1\\file3\\File类概述.avi");
FileOutputStream fos=new FileOutputStream("D:\\file\\file1\\file2\\File类概述1.avi");
byte[] bys = new byte[1024];
int len;
while ((len=fis.read(bys))!=-1) {
fos.write(bys,0,len);
}
fos.close();
fis.close();
}
public static void bufferedAvi() throws IOException {
BufferedInputStream fis=new BufferedInputStream(new FileInputStream("D:\\file\\file1\\file3\\File类概述.avi"));
BufferedOutputStream fos=new BufferedOutputStream(new FileOutputStream("D:\\file\\file1\\file2\\File类概述2.avi"));
byte[] bys = new byte[1024];
int len;
while ((len=fis.read(bys))!=-1) {
fos.write(bys,0,len);
}
fos.close();
fis.close();
}
}