IO流之字节流、字符流
-
InputStream抽象类是所有字节输入流类的超类,使用此类的方法可以从流中读取一个或一批字节,具体方法见API;注意:使用mark()和reset()方法之前,需要判断该文件是否支持这两个方法;
-
InputStream常用的子类:
-
FileInputStream:从文件中读取数据
-
ByteArrayInpuStream类:将字节数组转换为字节输入流,从中读取字节
-
PipedInputStream类:连接到一个PipedOutputStream(管道输出流)
-
BufferedInputStream:缓冲字节输入流(也可操作文件)
-
ObjectInputStream:对象字节输入流
-
FileInputStream
表示从文件系统的某个文件中获取输入字节。创建该类对象时,如果找不到指定的文件将会抛出FileNotFoundException异常,该异常必须捕获或声明抛出;
捕获异常快捷键:ctrl + alt + t
-
构造方法
-
FileInputStream(File file);
-
FileInputStream(FileDescriptor fbObj);
-
FileInputStream(String name);name为文件路径
-
-
常用方法
-
public int read() throws IOException:从该输入流读取一个字节的数据。 读取完毕返回-1;正常读取返回字符对应的char值
-
public int read(byte[] b) throws IOException:从该输入流读取最多b.length()字节的数据,存储到b中。 读取完毕返回-1;正常读取,返回读取到的字节数
-
//使用read()读取文件
String filePath = "e:\\hello.txt";
int readData = 0;//用于接收字符的char值
FileInputStream fileInputStream = null;
try{
//创建 FileInputStream 对象,用于读取文件,实参为文件路径
fileInputStream = new FileInputStream(filePath);
//read()从该输入流读取一个字节的数据。
//如果读取完毕,返回-1
while ((readData = fileInputStream.read()) != -1){
//System.out.print(readData);
System.out.print((char)readData);
}
}catch(IOException e){
e.printStackTrace();
}finally {
//关闭文件流,释放资源
try {//捕获close的异常
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//使用read(byte[] b)读取文件
String filePath = "e:\\hello.txt";
int readData = 0;//用于接收读取字符的数量
byte[] buffer = new byte[8];//一次读取8个字节
FileInputStream fileInputStream = null;//try外声明,以便捕获关闭流时抛出异常
try{
//创建 FileInputStream 对象,用于读取文件
fileInputStream = new FileInputStream(filePath);//创建
//从该输入流读取最多b.length字节的数据。
//如果读取完毕,返回-1
//正常读取,返回读取到的字节数
//每次读取,对byte[] buffer从0位开始覆盖
while ((readData = fileInputStream.read(buffer)) != -1){
System.out.print(readData);
//字符数组从0-读取的个数转成字符串显示
System.out.print(new String(buffer, 0, readData));
}
}catch(IOException e){
e.printStackTrace();
}finally {
//关闭文件流,释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
OutputStream
-
OutputStream类是所有字节输出流的父类,使用此类的方法可以从流中读取一个或一批字节,具体方法见API;
-
其常用子类有:
-
FileOutputStream类:向文件中写入数据
-
ByteArrayOutpuStream类:向内存缓冲区的字节数组中写数据
-
PipedOutputStream类:连接到一个PipedInputStream(管道输入流)
-
ObjectOutputStream:将对象序列化
-
FileOutputStream
同一个流对象中,使用多种写入方法,不会覆盖前面方法写入的字符,但下一个流对象会覆盖原文件的内容,设置true后,则是文件拼接,而不是文件覆盖
-
构造方法
-
FileOutputStream(File file);创建文件输出流以写入由指定的
File
对象表示的文件。默认覆盖原文件 -
FileOutputStream(File file, boolean append);创建文件输出流以写入由指定的
File
对象表示的文件;可以指定append为true或false,以指定文件是在原文件的基础上拼接还是覆盖; -
详见API
-
-
常用方法
-
write(int b) ;写入char值为b的字符,或者字符b;
-
write(byte [] b);将 字节数组b中的每个字节写入此文件输出流;
-
write(byte[] b, int off, int len);从字符数组b中的off位置开始,写入len个字符
-
详见API
-
往文件中写入汉字,通过字符串转成字符数组写入时,需将每个汉字的全部字符写入(UTP-8中汉字占3个字符)
多次写入需要换行时,可以写入换行符String str = "\r\n";
说明:
-
构造方法中指定目标文件时,目标文件可以不存在
-
目标文件的名称及后缀任意,可以使用记事本等工具打开并浏览
-
目标文件所在目录必须存在,否则抛出异常:java.io.FileNotFoundException
-
目标文件的名称不能是已存在的目录,否则抛出异常:java.io.FileNotFoundException
//创建FileOutputStream对象,可选择默认,true,false(默认)
String filePath = "e:\\a.txt";//创建文件路径名称
FileOutputStream fileOutputStream = null;//声明
try {//捕获异常
fileOutputStream = new FileOutputStream(filePath,true);//创建
//写入一个字节
fileOutputStream.write('a');
//写入字符串
String str = "hello,world";
//str.getBytes()将str转为字符数组
fileOutputStream.write(str.getBytes());
fileOutputStream.write(str.getBytes(),0,4);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
文件拷贝
-
完成文件拷贝,将e:\image-20220807162602134.jpg拷贝到d:\
-
1、创建输入流,将文件读取到程序
-
2、创建输出流,将程序中读取到的输出到目标文件
-
3、边读边写,循环运行“输入-->输出”,以完成文件拷贝(避免文件过大,一次性输入输出)
String filePathOld = "e:\\\\image-20220807162602134.jpg";
String filePathNew = "d:\\xxx.jpg";
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(filePathOld);
fileOutputStream = new FileOutputStream(filePathNew);
//定义一个字节数组
byte [] buff = new byte[1024];//一次读取1024个字符
int readLen = 0;//接收读取的字符个数
while ((readLen = fileInputStream.read(buff)) != -1){//无限循环读取,直至完毕
//读取到后,写入文件
fileOutputStream.write(buff,0,readLen);//多次写入
}
System.out.println("拷贝成功");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (fileInputStream != null){
fileInputStream.close();//关闭
}if (fileOutputStream != null){
fileOutputStream.close();//关闭
}
} catch (IOException e) {
e.printStackTrace();
}
}
Reader
尽管Java中字节流几乎可以直接或间接地处理任何类型的输入/输出操作,但利用它却不能直接操作16位的Unicode字符,这就要用到字符流。
-
Reader类是所有字符流输入流的父类,该类定义了许多方法,这些方法对所有子类都是有效的
-
常用子类:
-
CharArrayReader类:将字符数组转换为字符输入流,从中读取字符
-
StringReader类:将字符串转换为字符输入流,从中读取字符
-
PipedReader类:连接到一个PipedWriter
-
InputStreamReader类:将字节输入流转换为字符输入流,可以指定字符编码
-
-
常用方法
-
int read():返回读取的一个字符的值对应的数字;读取完毕,返回-1
-
int read(char [] b):读取若干个字符,保存到字符数组b中,返回读取的字符个数;读取完毕返回-1
-
int read(char [] b,off,len):读取len个字符,从字符数组下标off处开始保存;返回读取的字符个数,读取完毕,返回-1
-
FileReader
-
相关方法
-
new FileReader(File/String):构造器
-
read:每次读取单个字符,返回该字符,读取结束返回-1;
-
read( char []):批量读取多个字符到数组,返回读取的字符数,读取完毕返回-1;
-
-
相关API
-
new String (char []):将char[]转换成String
-
new String (char [] ,off,len):将char[]的指定部分转换成String
-
String filePath = "e:\\a.txt";
FileReader fileReader = null;
int data = 0;
try {
fileReader = new FileReader(filePath);
//循环读取,使用read,返回读取字符对应的数字
while ((data = fileReader.read()) !=-1){
System.out.print((char)data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
String filePath = "e:\\a.txt";
FileReader fileReader = null;
int data = 0;
char [] buff = new char[8];
try {
fileReader = new FileReader(filePath);
//循环读取,使用read(buff),返回读取的字符个数
while ((data = fileReader.read(buff)) !=-1){
System.out.println(new String(buff,0,data));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Writer
-
Writer类是所有字符流输出流的父类,该类定义了许多方法,这些方法对所有子类都是有效的
-
常用子类:
-
CharArrayWriter类:向内存缓冲区的字符数组写数据
-
StringWriter类:向内存缓冲区的字符串(StringBuffer)写数据
-
BufferedWriter类:为其他字符输出流提供写缓冲区
-
PipedWriter类:连接到一个PipedReader
-
OutputStreamReader类:将字节输出流转换为字符输出流,可以指定字符编码
-
-
常用方法:
-
writer():
-
append():
-
详见API
-
注意:Writer类所有的方法在出错的情况下都会引发 IOException 异常。关闭一个流后,再对其进行任何操作都会产生错误。
FileWriter
-
相关方法
-
new FileWriter(File/Strign):覆盖模式,数据写入文件,会覆盖原文件内容
-
new FileWriter(File/String,true):追加模式,在原文件基础上进行续写
-
writer(int b):写入单个字符
-
writer(char []):写入指定数组
-
writer(char [],off,len):写入指定数组的指定部分
-
writer(string):写入整个字符串
-
writer(string,off,len):写入字符串的指定部分
-
-
相关API
-
String类:toCharArray:将String转换成char[]
-
注意:FileWriter使用后,必须关闭(close)或刷新(flush),否则写入不到指定的文件!
String filePath = "e:\\xxt.txt";
//先创建fileWriter
FileWriter fileWriter = null;//声明
char ch = 'H';//
char [] ch_ = {'a','b','c','e'};
String str = "风雨过后,必见彩虹";
try {
fileWriter = new FileWriter(filePath);//创建
fileWriter.write(ch);//写入字符
fileWriter.write(ch_);//写入字符数组
fileWriter.write(ch_,1,2);//写入字符数组的指定部分
fileWriter.write(str);//写入字符串
fileWriter.write(str,1,3);//写入字符串的指定部分
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
节点流
-
节点流可以从数据源读写数据;如:FileReader、FileWriter
-
节点流和处理流的区别和联系:
-
节点流是底层流/低级流,直接跟数据源相接;
-
处理流包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出;
-
处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相接;
修饰器设计模式,详见
io.bufferfile
包简单模拟设计模式
-
-
处理流的功能主要体现在以下两个方面
-
性能的提高:主要以增加缓冲的方式来提高输入输出的效率;
-
操作的便捷:处理流提高了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便;
-