java学习笔记279-289 IO流,字节流

前言
b站java课程学习笔记整理。
b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程
279.IO流概述和分类
- IO是输入和输出。流时一种抽象的概念,指的是对数据传输的总称。
- IO流就是用来处理设备间数据传输问题的(例如文件复制,上传和下载)。
把数据从硬盘上加载到内存上,这个动作就是对应的输入:读数据。
把内存中的内容输出到硬盘上,这个动作对应的是写数据。 一般来说,IO流分类是按照数据类型来分的。
分为字符流和字节流:
如果数据可以通过记事本打开,那么就可以使用字节流,如果打不开,那么就使用字符流。默认使用字节流。
280.字节流写数据
字节流抽象类:
InputSteam
: 这个抽象类是表示子节输入流的所有类的超类。OutputStream
: 这个抽象类是表示字节输出流的所有类的超类。- 子类名特点:子类名称都是以其父类名作为子类名的后缀。
package FileOutputStreamDemo;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("idea_test\\FileOutputStreamDemo.txt");
/* 做了三件事:
1.调用系统功能创建了文件。
2.创建了字节输出流对象。
3.让字节输出流对象指向创建好的文件。*/
//写入ASCII码为97的字符‘a’
fos.write(97);
// 写入字符9和7
fos.write(57);
fos.write(55);
//最后释放资源
fos.close();
}
}
总结:
- 创建字节输出流对象
- 写入
- 释放资源
281.字节流写数据的三种方式
方法名 | 说明 |
---|---|
void write(int b) |
将指定的子节写入此文件输出流。一次写入一个字节数据 |
void write(byte[] b) |
将b.length子节从指定的字节数组写入此文件输出流,一次写一个字节数组数据 |
void write(byte[] b, int off, int len) |
从off位置开始,写入长度为len的字节数据 |
package FileOutputStreamDemo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
// 两种构造方法
FileOutputStream fos = new FileOutputStream("idea_test\\FileOutputStreamDemo.txt");
File file = new File("idea_test\\FileOutputStreamDemo2.txt");
FileOutputStream fos2 = new FileOutputStream(file);
// 输出
fos.write(97);
fos.write(98);
fos.write(99);
fos.write(100);
byte[] bytes = {97,98,99,100};
//fos2.write(bytes);
String line = "abcdefg";
byte[] byte2 = line.getBytes(StandardCharsets.UTF_8);
// fos2.write(byte2);
fos2.write(byte2,1,3);
// 释放资源
fos.close();
fos2.close();
}
}
282.字节流写数据的换行和追加写入
package FileOutputStreamDemo;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
// 两种构造方法
FileOutputStream fos = new FileOutputStream("idea_test\\FileOutputStreamDemo.txt");
for(int i = 0; i < 10; i++){
fos.write("hello".getBytes(StandardCharsets.UTF_8));
fos.write("\n".getBytes(StandardCharsets.UTF_8));
}
fos.close();
//可以追加写入
FileOutputStream fos2 = new FileOutputStream("idea_test\\FileOutputStreamDemo2.txt",true);
for(int i = 0; i < 10; i++){
fos2.write("hello".getBytes(StandardCharsets.UTF_8));
fos2.write("\n".getBytes(StandardCharsets.UTF_8));
}
fos2.close();
}
}
老师说windows的记事本是/r/n
,linux是/n
,mac是/r
,但是我windows也可以识别/n
……
283.字节流写数据加异常处理
finally
:在异常处理时会提供finally
块来执行所有清除操作,比如IO流中的释放资源。
特点: 被finally
控制的语句一定会执行,除非JVM退出。
标准格式:
try{
可能出现异常的代码
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}
示例代码
package FileOutputStreamDemo;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class FileOutputStreamDemo {
public static void main(String[] args) {
// 两种构造方法
FileOutputStream fos = null;
try {
//fos = new FileOutputStream("Z:\\idea_test\\FileOutputStreamDemo.txt");
fos = new FileOutputStream("idea_test\\FileOutputStreamDemo.txt");
fos.write("hello".getBytes(StandardCharsets.UTF_8));
fos.write("\n".getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
e.printStackTrace();
} finally{
if(fos!= null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
284.字节流读数据
需求:把txt文件内容读取出来在控制台
和写数据流程一样,都是三步。
package FileInputStreamDemo;
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("idea_test\\FileOutputStreamDemo.txt");
// 第一次读取一个数据
int read = fis.read();
System.out.println((char)read);
// 第二次读取一个数据
read = fis.read();
System.out.println((char)read);
System.out.println("-------------------");
// 读取所有的数据,文件到达末尾,返回值为-1
/* int by = fis.read();
while (by != -1){
System.out.println((char)by);
by = fis.read();
}*/
// 优化上面的程序
int by;
while((by = fis.read())!=-1){
System.out.println((char)by);
}
fis.close();
}
}
这个是可以读换行的。
285.字节流复制文本文件
需求:把rookie文件夹下的rookie.txt复制到theshy文件夹下。
package 复制文本文件;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyDemo {
public static void main(String[] args) throws IOException {
String source = "E:\\Javacode\\JavaSE Code\\rookie\\rookie.txt";
String destination = "E:\\Javacode\\JavaSE Code\\theshy\\theshy.txt";
FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(destination);
int by;
while((by=fis.read())!=-1){
fos.write(by);
}
fis.close();
fos.close();
}
}
注意:用字节流时目标路径一定要指向文件,而不是文件夹。否则会抛出拒绝访问的报错。
286.字节流读数据(一次读一个字节数组的数据)
现在有文本文档内容为:
如果执行如下代码:
package 字节流读取字节数组数据;
import java.io.FileInputStream;
import java.io.IOException;
public class FileOutputStreamRead {
public static void main(String[]args)throws IOException {
FileInputStream fis = new FileInputStream("idea_test\\FileOutputStreamDemo.txt");
byte[] bys = new byte[5];
// 第一次读取
int len = fis.read(bys);
System.out.println(len);
System.out.println(new String(bys));
// 第二次读取
len = fis.read(bys);
System.out.println(len);
System.out.println(new String(bys));
// 但三次读取
len = fis.read(bys);
System.out.println(len);
System.out.println(new String(bys));
fis.close();
}
}
返回的是一串很奇怪的东西:
原理: 文本文档的真实内容是
hello\n
world\n\n
len是实际读取的fis的数据个数。
定义的数组长度为5。可以理解为 \[$ $ $ $ $]
;
第一次读取,len = 5,即读取到了五个字符,得到的字符数组为\[h e l l o]
;
第二次读取,len = 5, 即读取到了5个字符,得到的字符数组为\[\n w o r l]
;
第三次读取, len = 3, 即读取到了3个字符,得到的字符数组为\[**d** **\n** **\n** r l]
;
第三次只读到了**d**
和两个 **\n**
,只能替换之前\[\n w o r l]
里面的前三个字符,就变成了这样。
改进:
package 字节流读取字节数组数据;
import java.io.FileInputStream;
import java.io.IOException;
public class FileOutputStreamRead {
public static void main(String[]args)throws IOException {
FileInputStream fis = new FileInputStream("idea_test\\FileOutputStreamDemo.txt");
byte[] bys = new byte[5];
// 第一次读取
int len = fis.read(bys);
System.out.println(len);
System.out.println(new String(bys,0,len));
// 第二次读取
len = fis.read(bys);
System.out.println(len);
System.out.println(new String(bys,0,len));
// 但三次读取
len = fis.read(bys);
System.out.println(len);
System.out.println(new String(bys,0,len));
fis.close();
}
}
使用String
方法,读取几个,转成几个字符串;
使用循环的终极改进:
package 字节流读取字节数组数据;
import java.io.FileInputStream;
import java.io.IOException;
public class FileOutputStreamRead {
public static void main(String[]args)throws IOException {
FileInputStream fis = new FileInputStream("idea_test\\FileOutputStreamDemo.txt");
// 一般给1024及其整数倍
byte[] bys = new byte[1024];
int len;
while ((len = fis.read(bys))!=-1){
System.out.println(new String(bys, 0, len));
}
fis.close();
}
}
0是offset
,也就是读取的偏移值。
byte
数组一般定义为1024或者1024的整数倍长度。
287.字节流复制图片
package 字节流复制图片;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyImage {
public static void main(String[] args) throws IOException {
String source = "E:\\Javacode\\JavaSE Code\\rookie\\rookie.jpg";
String destination = "E:\\Javacode\\JavaSE Code\\theshy\\rookie.jpg";
FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(destination);
byte[] bys = new byte[1024];
int len;
while((len = fis.read(bys))!=-1){
fos.write(bys,0,len);
}
fis.close();
fos.close();
}
}
所以文本文档用字节来复制,图片用字节数组来复制。
288.字节缓冲流
为字节流提供一个缓冲区,说人话就是”凑够一车人再发车“,可以有效地”省油“。
package 字节缓冲流;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class Demo {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("idea_test\\FileOutputStreamDemo.txt");
// 直接封装了一个大小为8192字节的数组。
BufferedOutputStream bos = new BufferedOutputStream(fos);
bos.write("hello\r\n".getBytes(StandardCharsets.UTF_8));
bos.write("world\r\n".getBytes(StandardCharsets.UTF_8));
//fos.close();
bos.close();
FileInputStream fis = new FileInputStream("idea_test\\FileOutputStreamDemo.txt");
// 直接封装了一个大小为8192字节的数组。
BufferedInputStream bis = new BufferedInputStream(fis);
/* int by;
while((by = bis.read())!=-1){
System.out.println((char)by);
}*/
//fis.close();
//bis.close();
byte[] bys = new byte[1024];
int len;
while((len = bis.read(bys))!=-1){
System.out.println(new String(bys,0,len));
}
//bis.close();
}
}
方法和之前的非缓冲区一样。这个的作用是可以更快的读取和写入。
289.字节流复制视频
package 字节流复制视频;
import java.io.*;
public class CopyVideo {
public static void main(String[] args) throws IOException {
String source = "E:\\Javacode\\JavaSE Code\\rookie\\沙皇一推五.webm";
String destination = "E:\\Javacode\\JavaSE Code\\theshy\\沙皇一推五.webm";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destination));
byte[] bys = new byte[1042];
int len;
while( (len = bis.read(bys))!=-1){
bos.write(bys,0,len);
}
bis.close();
bos.close();
}
}
这种方式在复制大型文件(例如视频)时快很多。