Java基础—IO流
参考文章
IO流主要的分类方式有以下3种:
- 按数据流的方向:输入流、输出流
- 按处理数据单位:字节流、字符流
- 按功能:节点流、处理流
字节流和字符流的其他区别:
- 字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。
- 字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。
- 用一句话说就是:字节流可以处理一切文件,而字符流只能处理纯文本文件。
- 字节流本身没有缓冲区,缓冲字节流相对于字节流,效率提升非常高。
- 而字符流本身就带有缓冲区,缓冲字符流相对于字符流效率提升就不是那么大了。
节点流与包装类(处理流)的说明
- 当一个流的构造方法需要一个流(参数)的时候,这个被传递进来的流叫:节点流
- 外部负责保证的这个流叫:包装流 或 处理流
输入流与输出流的说明
- 输入流—输入:数据流向内存
- 输出流—输出:数据从内存中流出
java.io包下需要掌握的流有16个:
文件专属: File
- java.io.FileInputstream (掌握)
- java.io.FileOutputstream (掌握)
- java.io.FileReader
- java.io.FileWriter
转换流:(将字节流转换成字符流)
- java.io.InputstreamReader
- java.io.OutputstreamWriter
缓冲流专属: Buffered
- java.io.BufferedReader
- java.io.BufferedWriter
- java.io.BufferedInputstream
- java.io.Bufferedoutputstream
数据流专属: Data
- java.io.DataInputstream
- java.io.DataOutputstream
标准输出流: Print
- java.io.PrintWriter
- java.io.Printstream
对象专属流: object
- java.io.objectInputstream (掌握)
- java.io.Objectoutputstream(掌握)
tip:
-
在java中只要
类名以"Stream"结尾的都是字节流,以"Reader、Writer"结尾的都是字符流 -
所有的流都
实现了 Closeable接口,都有close()方法,都是可以关闭的。 Stream流使用时要开启管道传输(建立通信机制),这个是内存和硬盘之间的通道,用完之后一定要关闭!不然会占用很多资源。 -
所有的输出流都
实现了 Flushable接口,都有flush()方法,都是可刷新的。表示把管道中的剩余未输出的数据,输出到指定位置上。
文件流 File
- java.io.FileInputstream
- java.io.FileOutputstream
- java.io.FileReader
- java.io.FileWriter
1. 文件字节流 FileInputStream、FileOutputStream
字节流的方式效率较低,不建议使用
FileInputStream方法摘要
FileOutputStream方法摘要
FileInputStream、FileOutputStream,实现 '文件拷贝' 功能
public class Copy01 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
/**
* bytes:存放读取数据的数组
* readCount:读取的字节数
*/
byte[] bytes = new byte[1024*1024];
int readCount=0;
try {
// 连接管道
fis = new FileInputStream("xxx\xxx\a.mp4");
fos = new FileOutputStream("xxx\xxx\b.mp4");
/**
* readCount:读取到的字节数; 如果没读到数据(读完)则返回-1
* fis.read(bytes):读取数组大小的数据,并存储到数组中
*/
while ((readCount=fis.read(bytes))!=-1){
fos.write(bytes,0,readCount); // 把内存中数组的数据,写入到磁盘
}
fos.flush(); // 输出流最后要刷新
} catch (Exception e) {
e.printStackTrace();
}
// 不能一起关闭(try),如果其中一个异常,会影响另一个的关闭
finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
2. 文件字符流 FileReader、FileWriter
字符流适用于文本文件的读写,
OutputStreamWriter类其实也是借助FileOutputStream类实现的,故其构造方法是FileOutputStream的对象
FileReader
/**
* FileReader
* 文件字符输入流,只读取普通文本
* 读取文本内容时,比较方便,快捷
*/
public class FileRead01 {
public static void main(String[] args) {
FileReader reader = null;
char[] chars = new char[4]; // 一次读取4个字符
try {
reader = new FileReader("a.txt");
int readCount = 0;
while ((readCount = reader.read(chars)) != -1){
System.out.print(new String(chars,0,readCount));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileWriter
tip:文件字符流 可以使用
字符数组或字符串写入
public class FileWriter01 {
public static void main(String[] args) {
FileWriter writer = null;
try {
// 如果不加参数`true`,每次写之前会把之前写的清空,再写入这一次的数据
writer = new FileWriter("src/main/java/IO/FileReader/a.txt",true);
// 字符数组
char[] chars = {'我','是','曼','德'};
writer.write(chars);
writer.write('\n'); // 换行
// 字符串
String s = "观众老爷,来个点赞!";
writer.write(s);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
缓冲流 Buffered
- java.io.BufferedReader
- java.io.BufferedWriter
- java.io.BufferedInputstream
- java.io.Bufferedoutputstream
缓冲字节流是为高效率而设计的,真正的读写操作还是靠
FileOutputStream和FileInputStream,所以其构造方法入参是这两个类的对象也就不奇怪了。tip:BufferReader 带有缓冲区的字符输入流
使用这个流的时候不需要自定义char数组或者byte数组。自带缓冲
BufferReader方法摘要
使用BufferReader的readLine()方法 读取文本
tip:br.readLine()方法读取一个文本行,但不带换行符 '\n'
public class BufferReader01 {
public static void main(String[] args) throws IOException {
// 当一个流的构造方法需要一个流的时候,这个被传递进来的流叫:节点流
// 外部负责保证的这个流叫:包装流 或 处理流
// 像当前这个程序来说:FileReader 就是节点流,BufferedReader就是包装流
FileReader reader = new FileReader("a.txt");
BufferedReader br = new BufferedReader(reader);
// 读取第二行
//String line1 = br.readLine(); // 一次读一行
//System.out.println(line1);
// 读取第二行
//String line2 = br.readLine();
//System.out.println(line2);
String s = null;
// 循环读取,如果到达行尾则返回null
// br.readLine()方法读取一个文本行,但不带换行符 '\n'
while ((s = br.readLine())!=null){
System.out.println(s);
}
/**
* 关闭流
* 对于包装流来说,只需要关闭最外层的流,里面的节点流会自动关闭,可以看源码
*/
br.close();
}
}
转换流
- java.io.InputstreamReader
- java.io.OutputstreamWriter
BufferedReader(Reader in) 因为缓冲字符流只能接收参数是 字符流类型的参数,
如果当前只有字节流,则可以使用到转换流。有这种需求的可以考虑使用~
tip:为了代码美观就把异常抛给方法了,一般情况不会这么做。
public class BufferedReader02 {
public static void main(String[] args) throws Exception {
/**
* 1.创建字符流 2.字节流 用转换流转为 字符流,
* 3.字符流当BufferedReader的参数
*/
FileInputStream fis = new FileInputStream("a.txt");
InputStreamReader in = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(in);
// 合并写法
//br = new BufferedReader(new InputStreamReader(new FileInputStream("a.txt")));
String line = null;
while((line = br.readLine())!=null){
System.out.println(line);
}
br.close();
}
}
数据流 (了解即可)
DataInputStream—数据字节输入流
DataOutputStream写的文件,只能使用DataInputStream去读。并且读的时候需要提前知道写入的顺序。读的顺序需要和写的顺序一致。才可以正常取出数据。
标准输出流
- 标准输出流可以指定位置输出数据,类似于log日志
public class Logger01 {
public static void log(String msg){
try {
// 指向一个日志文件
PrintStream out = new PrintStream(new FileOutputStream("log.txt", true));
// 改变输出方向
System.setOut(out);
// 日期当前时间
Date nowTime = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
String strTime = sdf.format(nowTime);
// 这里的输出 会向指定文件进行输出
System.out.println(strTime+":"+msg);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
测试
public class Test {
public static void main(String[] args) {
Logger01.log("调用了xxx方法");
Logger01.log("调用了xxx方法,出现异常!");
Logger01.log("用户尝试登录,登录失败!");
}
}