转换流
使用场景:读写文件时,中文乱码的问题。
为什么产生中文乱码问题?编码和解码时使用的码表不一致。
编码:符号→码值。解码:码值→符号。
输出字符流:OutputStreamWriter
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字节。它的作用的就是,将字符串按照指定的编码表转成字节,在使用字节流将这些字节写出去。OutputStreamWriter继承自Writer。
public class Demo {
public static void main(String[] args) throws IOException {
//OutputStreamWriter需要字节输出流
FileOutputStream fos = new FileOutputStream("UTF-8_1.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
osw.write("你好");
osw.close();
}
}
OutputStreamWriter流对象,它到底如何把字符转成字节输出的呢?
其实在OutputStreamWriter流中维护自己的缓冲区,当我们调用OutputStreamWriter对象的write方法时,会拿着字符到指定的码表中进行查询,把查到的字符编码值转成字节数存放到OutputStreamWriter缓冲区中。然后再调用刷新功能,或者关闭流,或者缓冲区存满后会把缓冲区中的字节数据使用字节流写到指定的文件中。
输入字符流:InputStreamReader
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的字符编码表读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。InputStreamReader继承自Reader。
public class Demo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("UTF-8_2.txt");
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
int ch;
while ((ch = isr.read()) != -1) {
System.out.println((char) ch);
}
isr.close();
}
}
缓冲流
Java中提高了一套缓冲流,它的存在,可提高IO流的读写速度。缓冲流,根据流的分类分类为字节缓冲流与字符缓冲流。
字节缓冲流
字节缓冲流根据流的方向,共有2个。
-
写入数据到流中,字节缓冲输出流 BufferedOutputStream。
-
读取流中的数据,字节缓冲输入流 BufferedInputStream。
它们的内部都包含了一个缓冲区,通过缓冲区读写,就可以提高了IO流的读写速度。缓冲流中byte数组默认长度是8192。
字节缓冲输出流BufferedOutputStream
通过字节缓冲流,进行文件的读写操作 写数据到文件的操作。
构造方法:
public BufferedOutputStream(OutputStream out)
:创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*高效字节流
高效字节输出流
OutputStream
BufferedOutputStream
构造方法:
BufferedOutputStream(OutputStream out)
成员方法:
void write(int b)
void write(byte[] b)
void write(byte[] b, int off, int len)
BufferedOutputStream原理:
底层使用了一个长度为8192的字节数组,我们再利用write写数据的时候都会写到
底层的字节数组中,我们可以通过手动刷新(将字节数组中的内容刷到文件)或者关流
(关流包含:先刷新在关流)
*/
public class Demo {
public static void main(String[] args) throws IOException {
//method01();
// method02();
FileOutputStream fos = new FileOutputStream("buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] bArr = {98, 99, 100, 101, 102};
bos.write(bArr, 2, 2);
bos.close();
}
private static void method01() throws FileNotFoundException, IOException {
//1.需要创建一个字节流对象关联文件
FileOutputStream fos = new FileOutputStream("buffer.txt");
//2.对FileOutputStream进行高效
BufferedOutputStream bos = new BufferedOutputStream(fos);
//3.向buffer.txt中写内容
bos.write(97);
bos.flush();
//4.关流释放资源
bos.close();
}
private static void method02() throws FileNotFoundException, IOException {
FileOutputStream fos = new FileOutputStream("buffer.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos);
byte[] bArr = {97, 98, 99, 100};
bos.write(bArr);
bos.close();
}
}
字节缓冲输入流 BufferedInputStream
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/*
高效字节输入流 InputStream BufferedInputStream
构造方法:
BufferedInputStream(InputStream in)
成员方法:
int read()
int read(byte[] b)
BufferedInputStream的原理:
底层也是使用一个长度为8192的字节数组,那么利用BufferedInputStream进行的读操作
都是读到底层这个8192字节数组中,read()返回值返回的字节都是从8192字节数组中取出来的
*/
public class Demo {
public static void main(String[] args)throws IOException {
// method01();
FileInputStream fis=new FileInputStream("buffer2.txt");
BufferedInputStream bis=new BufferedInputStream(fis);
byte[] bArr=new byte[3];
int len=bis.read(bArr);//bArr={97,98,99}
System.out.println(new String(bArr,0,len));
System.out.println(len);
bis.close();
}
private static void method01() throws FileNotFoundException, IOException {
//1.新建一个基本输入流关联文件
FileInputStream fis=new FileInputStream("buffer2.txt");
//2.创建高效流对象
BufferedInputStream bis=new BufferedInputStream(fis);
//3.读取文件内容
int b=bis.read();
System.out.println(b);
//5.关流
bis.close();
}
}
利用高效字节流拷贝图片
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 利用高效字节输入流和高效字节输出流进行图片拷贝
* 1.png → copy.png
*/
public class Demo {
public static void main(String[] args)throws IOException {
//1.利用基本流关联文件
FileInputStream fis=new FileInputStream("1.png");
FileOutputStream fos=new FileOutputStream("copy.png");
//2.对基本流进行高效
BufferedInputStream bis=new BufferedInputStream(fis);
BufferedOutputStream bos=new BufferedOutputStream(fos);
//3.进行读写操作
int b;
while((b=bis.read())!=-1){
bos.write(b);
}
//4.关流
bos.close();
bis.close();
}
}
字符缓冲流
字符缓冲输入流:BufferedReader,字符缓冲输出流:BufferedWriter。用于完成文本数据的高效的写入与读取的操作。
字符缓冲输出流:BufferedWriter,BufferedReader继承自Writer。
构造方法:BufferedWriter(Writer out):创建一个默认大小的输出缓冲区的缓冲字符输出流。
成员方法:
void newLine()//写入一个行分隔符
void write(char[] cbuf,int off,int len)//写入字符数组的某一部分
void write(int c)//写入单个字符
void write(String s,int off,int len)//写入字符串的某一部分
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
void newLine():根据当前的系统,写入一个换行符。
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/*高效字符输出流
* Writer
* BufferedWriter
* 构造方法:BufferedWriter(Writer out)
* 成员方法:
void write(int c)
void write(String str)
void write(char[] cbuf)
void write(char[] cbuf, int off, int len)
void newLine():写入一个换行标志 ,跨平台方法,在不同的操作系统(windows,linux,mac)下会写入不同的换行符
BufferedWriter底层原理:
声明了一个长度为8192的字符数组,所有的写操作都会写到这个字符数组中
所以我们需要通过手动刷新或者关流,来让数组的内容到文件中
*/
public class Demo {
public static void main(String[] args)throws IOException{
//1.在高效流传入基本流对象,基本流关联文件
BufferedWriter bw=new BufferedWriter(new FileWriter("buffer3.txt"));
//2.利用高效流做写操作 a你好abcbc
bw.write(97);
bw.newLine();
// bw.write("\r\n");
bw.write("你好");
char[] chArr={'a','b','c'};
bw.write(chArr);
bw.write(chArr,1,2);
//bw.flush();
//3.关流释放资源
bw.close();
}
}
字符缓冲输入流 BufferedReader
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。BufferedReader继承自Reader。
构造方法:BufferedReader(Reader in):创建一个默认大小输入缓冲区的缓冲字符输入流。
成员方法
int read()//读取单个字符
int read(char[] cbuf,int off,int len)//将字符读入数组的某一部分
String readLine()//读取一个文本行
public String readLine() 读取一个文本行,包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null。
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/*高效字符输入流体系
* Reader
* BufferedReader
* 构造方法:
* BufferedReader(Reader in)
* 成员方法:
* int read()
int read(char[] cbuf)
* String readLine():读取一行数据,不会读该行的换行符,返回的是当前行数据
如果读到文件末尾则返回null
BufferedReader的原理:
底层也是使用一个长度为8192的字符数组,所有读动作都是从底层的字符数组读的
* */
public class Demo {
public static void main(String[] args)throws IOException{
//method01();
BufferedReader br=new BufferedReader(new FileReader("buffer4.txt"));
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
}
private static void method01() throws FileNotFoundException, IOException {
//1.创建一个高效字符输入流,传入一个基本字符输入流对其高效
BufferedReader br=new BufferedReader(new FileReader("buffer4.txt"));
//2.从buffer4.txt读内容
int ch=br.read();
System.out.println(ch);//97
char[] chArr=new char[2];
int len=br.read(chArr);//chArr={'b','c'}
System.out.println(new String(chArr));//"bc"
System.out.println(len);//2
//3.关流释放资源
br.close();
}
}
使用字符缓冲流完成文本文件的复制
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
*利用BufferedReader和BufferedWriter来做拷贝文件
* buffer5.txt -> copy.txt
* 用到BufferedReader
* String readLine():读取一行数据,不会读该行末尾换行符,返回的是当前行数据
如果读到文件末尾则返回null
用到BufferedWriter特有方法
void newLine():写入一个换行标志 ,跨平台方法,
在不同的操作系统(windows,linux,mac)下会写入不同的换行符
*/
public class Demo {
public static void main(String[] args)throws IOException {
//1.利用高效流,在高效流中传入基本流
BufferedReader br=new BufferedReader(new FileReader("buffer5.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("copy.txt"));
//2.循环的读写操作
String line;
while((line=br.readLine())!=null){
bw.write(line);//第一循环 line="你好吗" 写入你好吗
//第二次循环 line="我很好" 写入我很好
//...
bw.newLine();//写入一个换行
}
//3.关流释放资源
bw.close();
br.close();
}
}
IO标准处理异常
我们在做IO流的操作都是把异常直接throws出去,我们现在用try…catch处理IO异常。
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*以字节输出流为例进行IO标准异常处理
* try{
* //可能出现异常的代码
* }catch(异常类型 变量名){//捕获异常
* //处理异常的代码
* }finally{
* //无论try中是否发声异常,finally中的语句一定执行
* }
*
*/
public class Demo {
public static void main(String[] args){
FileOutputStream fos=null;//提升fos变量的作用域,因为在finally中需要使用fos
try{
//1.用输出流关联文件
fos=new FileOutputStream("1.txt");//FileNotFoundException
//2.向文件中写一个字节
fos.write(100);
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
//3.关流释放资源
try{
if(fos!=null){//如果new FileOutputStream("1.txt")抛异常,那么fos的值为null
//fos.close()会引发空指针异常,因此我们加一个null判断
fos.close();//无论try中是否报异常,我们都需要关流释放资源
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
数据流
数据流将“基本数据类型与字符串类型“作为数据源,从而允许程序以与机器无关的方式从底层输入输出流中操作Java基本数据类型与字符串类型。主要读写基本数据类型,对二进制文件读写。
DataInputStream和DataOutputStream提供了可以存取与机器无关的所有Java基础类型数据(如:int、double、String等)的方法。
使用步骤:
1、创建对象:writeDouble(), readDouble()。
2、释放资源。
import java.io.*;
public class Demo {
public static void main(String[] args) throws IOException {
write();
read();
}
private static void write() throws IOException {
//创建对象
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
//输出数据
dos.writeInt(97);//int
dos.writeDouble(12.23);//double
//释放资源
dos.close();
}
private static void read() throws IOException {
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
int num1 = dis.readInt();
double num2 = dis.readDouble();
System.out.println(num1+","+num2);
dis.close();
}
}
IO+Map统计字符串中字符的个数
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/*
* IO+String+Map
* 需求:创建记事本文件aa.txt,FileWriter向aa.txt输入一些字符串
* 高效流读取aa.txt的内容,统计每个字符出现的次数存Map
* 结果a---5
* b---7
* map保存的数据结果,输出bb.txt
* abc
* */
public class Demo {
public static void main(String[] args) throws Exception{
//aa.txt输出任意字符串
FileWriter fw = new FileWriter("aa.txt");
fw.write("wwwwgdugweihdwuogugdwfi");
fw.write("\n");
fw.write("wdwquduou");
fw.close();
//读取aa.txt,统计
BufferedReader br = new BufferedReader(new FileReader("aa.txt"));
String str;
StringBuffer sb = new StringBuffer();
while ((str=br.readLine())!=null){
sb.append(str);
}
System.out.println(sb);
//统计字符串出现次数
char[] cs = sb.toString().toCharArray();
Map<Character,Integer> map = new HashMap<>();
int num = 1;//默认每个符号都是第一次存储
for (char c : cs) {
if (map.containsKey(c)){
//不是第一次存储,现有存储次数+1
num = map.get(c)+1;
}
map.put(c,num);
}
//输出统计结果,并将统计后的字符写出bb.txt
Set<Character> keys = map.keySet();//获取map所有的key
FileWriter fw2 = new FileWriter("bb.txt");
for (Character c : keys) {
System.out.println(c+"========"+map.get(c));
//文件中
fw2.write(c);
}
fw2.close();
}
}
评论区