JavaIO学习笔记
文章目录
1.JavaIO基本概念
1.1.JavaIO流基本概念
如果想实现内存与磁盘间的文件读写的话,那么就需要接触**“流”这个概念。流好比是管道,从磁盘到内存是输入,从内存到到磁盘是输出,衍生出来的概念就是输入流和输出流**。有时候我们从磁盘读写的是多媒体等文件,有时候我们从磁盘读写的纯文本文件(.java,.txt),那么流又可以从另外一个维度划分为字节流和字符流。
总而言之,根据输入输出和字节字符的区分把流分为如下四个大类:
四个抽象类都继承了Closeable,这个Closeable中有一个方法叫做close,其作用是当流不再需要时,调用此方法释放与流相关的系统资源。而Closeable继承自AutoCloseable,AutoCloseable的一个典型应用就是try-with-resources,如下所示:
//模拟纯文本复制的案例
try(FileWriter out = new FileWriter("IO/properties/demo2.txt");
FileReader in = new FileReader("IO/properties/demo1.txt")
) {
//每次读10个字符
char [] charArray = new char[10];
int readCount;
while ((readCount=in.read(charArray))!=-1){
out.write(charArray,0,readCount);
}
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
在try语句块中可以写任意与资源(类必须实现AutoCloseable接口)相关的赋值语句,用分号;隔开,这样就可以避免用户没有手动释放资源的情况发生。这里可以看出任意与流相关的资源都可以采用try-with-resources的语法。
字节输出流和字符输出流都实现了Flushable接口,这个接口的一个重要方法是flush,即强制将缓冲区的字符或是字节写入到磁盘当中,避免数据的丢失。
事实上,close和flush方法在四大抽象类的各个实现类中可能有不同的重写,其功能肯定得到了一定的扩展,这一点需要注意。其次,以Stream为结尾的流都是字节流,以Writer/Reader结尾的是字符流。
1.2.JavaIO核心掌握流
需要掌握的流如下
1.文件流:
FileInputStream
FileOutputStream
FileWriter
FileReader
2.转换流(字节转为字符)
InputStreamReader
OutputStreamWriter
3.缓冲流
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
4.数据流
DataInputStream
DataOutputStream
5.标准输出流
PrintWriter
PrintStream
6.对象流
ObjectInputStream
ObjectOutputStream
2.文件流
2.1FileInputStream
文件字节输入流,无敌存在,任何类型文件都可以用这个流来读。主要弄清楚它的构造方法和核心方法
构造方法
FileInputStream(File file);
FileInputStrem(String name);
二者本质差不多,都是说明文件的路径在哪里。文件的路径分为绝对路径和相对路径。**而相对路径以项目为根路径。关于路径的规定适用于任意其他的流。**在Windows中,反斜杠和正斜杠都是可以的,不过需要注意反斜杠是转义字符
FileWriter out = new FileWriter(“IO/properties/demo2.txt”);
FileWriter out = new FileWriter(“IO\\properties\\demo2.txt”);
实例方法
// 读一个字节 返回字节的ASCII码值 当无字节可读时,返回-1
int read();
/* 每一次最多读arr.length大小的字节,并存储到arr中
当字节数没有达到arr.length(即文件最后几个字节达不到arr.length时),
这些字节会覆盖掉arr的一部分,而另一部分不会被覆盖掉
该方法返回读到的字节数量,当无字节可读时返回-1
*/
int read(byte [] arr)
/*
每一次最多读len大小的字节,并从off位置开始存储到arr中
该方法返回读到的字节数量,当无字节可读时返回-1
其实这个方法用得还是比较少
*/
int read(byte [] arr,int off ,int len)
//返回文件剩余未读的个数
int available();
// 跳过n个字节不读,并返回实际跳过没读的字节数
long skip(long n);
//关闭与输入流相关的资源
void close()
注意:上面的byte [] arr 实际上说的就是缓冲区
实战
问题描述
仅利用FileInputStream读取含中文字符的文本文件,并打印到控制台中。
基本思路
- String有构造函数,传入byte数组即可转为String
- 中文字符是两个字节,所以考虑将所有字节都存储到ArrayList中,然后再转化为byte数组,这样可以避免乱码
- byte数组不能挑选得很大,毕竟数组占用连续的内存空间。
文本内容
代码
package com.lordbao.fileinputstream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @Author Lord_Bao
* @Date 2020/9/4 11:19
* @Version 1.0
*/
public class Main2 {
public static void main(String[] args) {
try(FileInputStream fis = new FileInputStream("IO\\properties\\123.txt") ) {
//一次读5个字节
byte [] byteArray = new byte[5];
//用ArrayList存储字节数组
List<Byte> byteArrayList = new ArrayList<>();
int readCount;
//每次从byteArray缓冲区中读取 readCount大小的字节,存储到ArrayList中
while ((readCount=fis.read(byteArray)) !=-1){
for (int i=0;i<readCount;i++){
byteArrayList.add(byteArray[i]);
}
}
//调用List的toArray(T [])方法 ,拿到Byte数组
Byte [] finalByteArray = new Byte[byteArrayList.size()];
finalByteArray = byteArrayList.toArray(finalByteArray);
//Byte数组 转为 byte数组
byte [] finalbyteArray = new byte[finalByteArray.length];
for (int i=0;i<finalByteArray.length;i++){
finalbyteArray[i] = finalByteArray[i];
}
//通过byte数组转为String
String s = new String(finalbyteArray);
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果
666 老铁
礼物走起来
注意
byte [] byteArray = new byte[fis.available()];
虽然可以这样写,但是真正情况下,要考虑数组占用内存的问题,毕竟文本的大小是未知的。
2.2FileOutputStream
文件字节输出流,它的作用是将缓冲区的字节写入到文件中,和FileInputStream类似,主要研究它的构造方法和实例方法。
构造方法
//创建文件输出流以写入由指定的 File对象表示的文件。文件不存在就创建
FileOutputStream(File file)
//创建文件输出流以写入由指定的 File对象表示的文件。文件不创建就创建,boolean表示是否在源文件进行追加。true表示追加,false表示覆盖
FileOutputStream(File file, boolean append)
//同上面类似
FileOutputStream(String name)
//同上面类似
FileOutputStream(String name, boolean append)
实例方法
//关闭此文件输出流并释放与此流相关联的任何系统资源。
void close()
//将 b.length个字节从指定的字节数组写入此文件输出流。
void write(byte[] b)
//将 len字节从位于偏移量 off的指定字节数组写入此文件输出流。
void write(byte[] b, int off, int len)
//将指定的字节写入此文件输出流。
void write(int b)
//刷新
void flush()
实战
问题描述
利用FileInputStream和FileOutputStream 实现文件的复制
基本思路
使用FIleInputStream和FileoutputStream边读边写
代码
package com.lordbao.fileoutputsream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @Author Lord_Bao
* @Date 2020/9/4 15:09
* @Version 1.0
*
* 文件复制
*/
public class Main2 {
public static void main(String[] args) {
try(FileInputStream fis = new FileInputStream("IO/properties/demo1.txt");
FileOutputStream fos=