Java学习笔记 -IO流1
概述
1. 按照字节的方式读取:
- 等同于一次读取8个二进制位;
- 是万能的,什么类型都能读取,包括文本、声音、图片。。
- 例如:a重点
- 第一次读取a 一个字节;第二次读取“重”的前半部分 一个字节
2. 按照字符去读取数据,一次读取一个字符,为了方便读取普通的文本文件
- 不能读取除了普通文本之外的任何类型,连Word文件也无法读取
- 例如:a重点
- 第一次读取a 一个字节;第二次读取“重” 两个字节
3. Java IO流四大家族
(1)四大首领:
-
java.io.InputSteam 字节输入流
-
java.io.OutputStream 字节输出流
-
java.io.Reader 字符输入流
-
java.io.Writer 字符输出流
(2)相关知识:
- 以"Stream"结尾都是字节流,以"Reader/Writer"结尾都是字符流
- 四大家族的首领都是抽象类 (abstract class)
- 所有流都实现了java.io.closeable接口,都是可以关闭的,都有close()方法
- 所有的输出流都实现了java.io.Flushable接口,输出流在最终输出之后,一定要flush()
表示刷新一下,这个刷新将管道中剩余的未输出的数据强行输出完,如果没有flush()可能导致数据丢失
4. 16个常用的类
(1)文件专属:
- FileInputStream
- FileOutputStream
- FileReader
- FileWriter
(2)转换流:(将字节流转换未字符流)
- InputStreamReader
- OutputStreamWriter
(3)缓冲流:
- BufferedReader
- BufferedWriter
- BufferedInputStream
- BufferedOutputStream
(4)数据流:
- DataInputStream
- DataOutputStream
(5)标准输出流:
- PrintWriter
- PrintStream
(6)对象专属流:
- ObjectInputStream
- ObjectOutputStream
文件专属流
- 本段通过几个示例程序表述知识点
- 文件字节流和字符流的用法类似,所以只讲字节流
- 有一点区别:字节流使用byte[]数组缓存,字符流使用char[]数组缓存
- 文件字节流读取含中文的普通文本可能会乱码,读取含中文的普通文本最好使用文件字符流
示例1 -FileInputStream:
(1)知识点:
- 文件路径:绝对路径 & 相对路径
- 方法:int read() 返回读取字符的编码,如果读取到了文件结尾就返回-1
(2)程序:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputSteamTest01 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
/*
(1)绝对路径的两种表达: "\\"因为\表示转义
FileInputStream fis = new FileInputStream("D:\\biancheng\\java\\file\\chapter19\\111.txt");
fis = new FileInputStream("D:/biancheng/java/file/chapter19/111.txt");
(2)相对路径:
IDEA默认的当前目录是工程初始模块的根目录下
*/
fis = new FileInputStream("src/1/111.txt");
//如果都到末尾没有数据,会返回-1
int readData = 0;
while((readData = fis.read()) != -1){
System.out.println(readData);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
示例2 -FileInputStream:
(1)知识点:
- 使用示例1的方法,会造成和硬盘的交互次数过多,应该提高每一次交互所读取的字节数
- 方法:int read(byte[] b) 一次最多读取b.length个字节,返回读取的字节数,如果读取到了文件结尾就返回-1
- 常用方法:int available() 返回剩下未读取的字节数量
- 常用方法:long skip(long n) 跳过n个字节不读,返回实际跳过的字节数目
(2)程序:
public class FileInputStreamTest02 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("src/1/111.txt");
int retValue = 0;
//这个方式不适合读大文件,因为bytes数组不能太大
byte[] bytes = new byte[fis.available()]; //实例化一个和文件字节数相同的byte数组
fis.skip(3); //跳过3个字符不读取
fis.read(bytes);
System.out.println(new String(bytes));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
示例3 -FileOutputStream:
(1)知识点:
-
构造方法:fos = new FileOutputStream(String name,boolean append)
append:是否以追加模式写入,默认是false
其他构造方法查阅参考手册 -
方法:write(byte b)
write(byte b, int off, int len) -
方法:flush(): 在最后一次输出之后,一定要调用flush(),就好像把水管里还剩余的水全部输送出去
(2)程序:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest01 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
//以追加模式写入,默认是false
fos = new FileOutputStream("myfile",true);
byte[] bytes = {96,97,98,99};
fos.write(bytes);
//写入bytes数组的部分内容
fos.write(bytes, 0, 2);
//写完之后,一定要刷新一下
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
示例4 -复制文件
- 重点掌握这种写法
程序:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyTest01 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("D:\\迅雷下载\\星露谷\\README.md");
fos = new FileOutputStream("D:\\myPicture.png");
//一次读取最多读取1M
byte[] bytes = new byte[1024 * 1024];
int retValue = 0;
while ((retValue = fis.read(bytes)) != -1){
//一定要指定offset和长度,否则如果读取byte数组不满时,会写入一部分上一次读取的字符
fos.write(bytes,0,retValue);
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//分别进行try catch,防止一个出现异常,另一个无法关闭
if(fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}