按照数据的流向
输入流:读数据
输出流:写数据
按照数据类型来分
字节流 : 字节输入流 ; 字节输出流
字符流 : 字符输入流 ; 字符输出流 --记事本,可以读懂的
一般来说,IO流的分类是按照数据类型来分的
字节流抽象基类
lnputStream : 这个抽象类是表示字节输入流的所有类的超类
OutputStream : 这个抽象类是表示字节输出流的所有类的超类
子类名特点 :子类名称都是以其父类名作为了类名的后缀
FileOutputStream : 文件输出流用于将数据写入File
FileOutputStream(String name) : 创建文件输出流以指定的名称写入文件
--String name会自动封装成File
FileOutputStream fos = new FileOutputStream("项目名\\fos.txt");
/*
做了三件事情: - 创建字节输出流对象
1:调用系统功能创建了文件
2:创建了字节输出流对象
3:让字节输出流对象指向创建好的文件
*/
fos.write(97); //void write(int b)将指定字节写入此文件输入流 - 97对应字符"a"
//最后释放资源 关闭此文件输出流并释放与此流相关联的任何系统资源。
fos.close();
方法名 | 说明 |
---|---|
void write(int b) | 将指定的字节写入此文件输出流一次写一个字节数据 ↑↑↑ |
void write(byte[] b) | 将b.length字节从指定的字节数组写入此文件输出流一次写一个字节数组数据 |
ltoid write(byte[] b, int off, int len) | 将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流—次写一个字节数组的部分数据 |
//void write (byte[] b)
byte[] bys1 = {97,98,99,100,101}; //对应abcde
//byte[] getBytes ():返回字符串对应的字节数组
byte[] bys2 = "abcde".getBytes(); //等效于上面
?
fos.write(bys); //bys1,bys2结果均为添加数据"abcde"
?
fos.write(bys,1,3); //写入"bcd"
fos.close();
字节流写数据如何实现换行呢?
window : \r\n
linux : \n
mac : \r
字节流写数据如何实现追加写入呢?
public FileOutputStream(String name,boolean append)
创建文件输出流以指定的名称写入文件
如果第二个参数为true , 则字节将写入文件的末尾而不是开头
FileOutputStream fos = null;
try { //try-catch方法
fos = new FileOutputstream("项目名\\fos.txt");
fos.write("he11o".getBytes();
} catch(IOException e) {
e.printStackTrace();
} finally {
if(fos != nu11) {
try {
fos.closeo();
} catch(IoException e) {
e.printstackTrace();
}
}
}
//创建字节输入流对象 FileInputputStream(String name)
FileInputputStream fos = new FileInputputStream("项目名\\fos.txt");
//读取数据 int read() --文件到达末尾,返回值-1
int by = fis.read();
System.out.println((char)by);// a,如不转换数据类型读取97
?
/***读数据标准代码***/
int by;
while((by=fis.read())!=-1) {
System.out.print((char)by);
//fos.wsrite(by);写入字节
}
fis.close();
FileInputStream fis = new FileInputStream("项目名\fos.txt");
/*
文件内容:
hello
world
*/
byte[] bys = new byte[5];
//第一次
int len = fis.read(bys); //返回读取的数据长度
System.out.print1n(len); //5
System.out.print1n(new string(bys,0,len)); // "hello"
//第二次
int len = fis.read(bys);
System.out.print1n(len); //5
System.out.print1n(new string(bys,0,len)); // "wor"\r\n
//第三次
int len = fis.read(bys);
System.out.print1n(len); //4
System.out.print1n(new string(bys,0,len)); // \r\n"ld""r"--最后一个r没有被覆盖
//已经读取完,如果再读取数据,返回-1
fis.close();
/***读取字节标准代码***/
byte[] bys = new byte[1024]; //1024及其整数倍
int len;
while((len=fis.read(bys)) != -1) {
System.out.print(new String(bys,0,len));
//fos.write(bys,0,len);写入数组
}
fis.close();
根据数据源创建字节输入流对象
根据目的地创建字节输出流对象
读写数据,复制文本文件(一次读取一个字节,一次写入一个字节)
释放资源
FileInputStream fis = new FileInputStream("输入流对象地址\\test.txt");
FileOutputStream fos = new FileOutputStream("输出流对象地址\\test.txt");
int by;
while((by=fis.read())!=-1){
fos.write(by);
} //一次一个字节
fos.close();
fis.close();
根据数据源创建字节输入流对象
根据目的地创建字节输出流对象
读写数据,复制图片(一次读取一个字节数组,一次写入一个字节数组)
释放资源
FileInputStream fis = new FileInputStream("输入流对象地址\\test.jpg");
FileOutputStream fos = new FileOutputStream("输出流对象地址\\test.jpg");
?
byte[] bys = new byte[1024];
int len;
while((len=fis.read(bys)) != -1) {
fos.write(bys,0,len);
} //一次一个字节数组
fos.close();
fis.close();
根据数据源创建字节输入流对象
根据目的地创建字节输出流对象读写数据
复制视频
释放资源
四种方式实现复制视频,并记录每种方式复制视频的时间
1基本字节流一次读写一个字节 非常慢
2基本字节流一次读写一个字节数组 比4慢,比3快
3字节缓冲流一次读写一个字节 必1快很多,比24慢
4字节缓冲流一次读写一个字节数组 最快(一般使用的方法)
FileInputStream fis = new FileInputStream("地址\\test.MP4");
FileOutputStream fos = new FileOutputStream("地址\\test.MP4");
?
//2.基本字节流一次读写一个字节数组
byte[] bys = new byte[1024];
int len;
while((len=fis.read(bys))!=-1) {
fos.write(bys,0,len);
}
fos.close();fis.close();
//4.字节缓冲流一次读写一个字节数组
byte[] bys = new byte[1024];
int len;
while((len=fis.read(bys))!=-1) {
fos.write(bys,0,len);
}
fos.close();fis.close();
BufferedOutputStream : 该类实现缓冲输出流。
通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
BufferedInputStream : 创建BufferedInputStream将创建一个内部缓冲区数组。
当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作
构造方法 | 内容 |
---|---|
BufferedOutputStream(OutputStream out) | 字节缓冲输出流 |
BufferedInputStream(InputStream in) | 字节缓冲输入流 |
FileOutputStream fos = new FileOutputStream("地址\\test.txt");
BufferedOutputStream b = new BufferedOutputStream(fos);
//合并书写
BufferedOutputStream b=new BufferedOutputStream(new FileOutputStream("."));
//写数据
b.write("he11o\r\n".getBytes());
b.write("world\r\n".getBytes());
b.close();
?
?
BufferedInputStream bi=new BufferedInputStream(new FileOutputStream("."));
//读数据 --一次一个字节
int by;
while((by=bi.read())!=-1) {
System.out.print((char)by);
}
//读数据 --一次一个数组
byte[ ] bys = new byte[1024];
int len;
while((len=bi.read(bys)) != -1) {
System.out.print(new String(bys,0,len)) ;
}
bi.close();
字符流 = 字节流+编码表
一个汉字存储 :
如果是GBK编码,占用2个字节
如果是UTF-8编码,占用3个字节
如果以一个字节一个字节读取数据,将乱码,因为无法读取一个完整汉字的所有字节
/*编码*/
String s = "中国"; //汉字存储时,所有编码首字节一定为负数
byte[] bys = s.getBytes(); //默认使用UTF-8
byte[] bys = s.getBytes("UTF-8"); //[-28, -72, -83, -27, -101, -67] --默认
byte[] bys = s.getBytes("GBK"); //[-42, -48, -71 ,-6]
System.out.println(Arrays.toString(bys));
常见字符集有ASCII字符 集 , GBXXX字符集 , Unicode字符集...
ASCII : 使用7位表示一个字符,共128个字符 . ASCII扩展字符集使用8位,共256个字符
GB2312 : 简体中文码表。小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字...
GBK : 最常用的中文码表。**是在GB2312标准基础上的扩展规范,使用了双字节编方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字...
GB18030 : 最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个,2个或4个字节组成 . 支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字...
Unicode : 为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国码。它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案,UTF-8、UTF-16和UTF32。最为常用的UTF-8编码。
编码规则 :
128个US-ASCIl字符,只需一个字节
编码拉丁文等字符,需要一个字节编码
大部分常用字(含中文),使用三个字节编码
其他极少使用的Unicode辅助字符,使用四字节编码
编码:
byte[ ] getBytes():使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
byte[ ] getBytes(String charsetName);使用指定的字符集将该―String编码为一系列字节,将结果存储到新的字节数组中
解码:
String(byte[ ] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的 String
String(byte[ ] bytes,String charsetName):通过指定的字符集解码指定的字节数组来构造新的 string
/*解码 使用什么方法编码就要用什么方式解码*/
String ss = new string(bys); //默认使用UTF-8 "中国"
String ss = new string(bys,"UTF-8"); //"中国"
String ss = new string(bys,"GBK"); // --如果使用UTF-8编码会乱码
System.out.println(ss);
InputStreamReader:是从字节流到字符流的桥梁
它读取字节,并使用指定的编码将其解码为字符
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
OutputStreamWriter:是从字符流到字节流的桥梁
是从字符流到字节流的桥梁,使用指定的编码将写入的字符编码为字节
它使用的字符集可以由名称指定,也可以被明确指定,或者可以接受平台的默认字符集
OutputStreamWriter o = new OutputStreamWriter(new FileOutputStream("路径\\o.txt")/*,可加编码格式-默认UTF-8*/);
o.write("中国");
o.close();
?
InputStreamReader i = new InputStreamReader(new FileOutputStream("路径\\o.txt")/*,可加编码格式-默认UTF-8*/);
int ch; //一次读取一个字符
while((ch=i.read())!=-1){
System.out.print((char)ch);
}
i.close();
五种写数据方法(前三种一样) | 描述 |
---|---|
void write(int c) | 写一个字符 |
void write(char[] cbuf) | 写入一个字符数组 |
void write(char[] cbuf, int off, int len) | 写入字符数组的一部分 |
void write(String str) | 写一个字符串 |
void write(String str,int off, int len) | 写一个字符串的一部分 |
//字符流不能直接写数据 void flush() 刷新流 缓冲问题
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("路径\\osw.txt"));
osw.write(97); //写入一个字符
void flush(); //写入a
?
char[]chs[‘a‘,‘b‘,‘c‘,‘d‘,‘e‘};
osw.write(chs); //abcde 写入一个字符数组
osw.write(chs,1,3); //bcd 写入字符数组的一部分
osw.write("abcde"); //abcde 写一个字符串
osw.write("abcde",1,3); //bcd 写一个字符串的一部分
osw.close(); //close流,先刷新,后关闭,关闭后不能继续写入数据
与字节流方法类似 | 描述 |
---|---|
int read() | 一次读一个字符数据 |
int read(char[] cbuf) | 一次读一个字符数组数据 |
需求 : 把模块目录下的“test.java”复制到模块目录下的“Copy.java"
根据数据源创建字符输入流对象
根据目的地创建字符输出流对象
读写数据,复制文件
释放资源
InputStreamReader isr = new InputStreamReader(new FileInputStream("目录\\test.java"));
OutputStreamwniter osw = new OutputStreamdlriter(new FileOutputStream("目录\\Copy.java"));
?
char[] chs = new char[1024];
int len;
while((len=isr.read(chs)) != -1) {
osw.write(chs,0,len) ;
}
isr.close();osw.close();
改进 :
分析:
转换流的名字比较长,而我们常见的操作都是按照本地默认编码实现的,所以,为了简化书写,转换流提供了对应的子类
以下简化类不能规定编码格式,使用默认格式UTF-8
FileReader : 用于读取字符文件的便捷类
FileReader(String fileName)
FileWriter : 用于写入字符文件的便捷类
FileWriter(String fileName)
数据源和目的地的分析:
数据源 : 项目名\ \test.java --- 读数据 --- Reader --- lnputstreamReader --- FileReader
目的地 : 项目名\ \Copy.java --- 写数据 --- Writer --- OutputStreamWriter --- FileWriter
FileReader fr = new FileReader("....");
FileWriter fw = new FileWriter("....");
?
char[] chs = new char[1024];
int len;
while((len=fr.read(chs)!=-1) {
fw.write(chs,0,len);
}
fw.close();fr.close();
BufferedWriter : 将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于突多数用途
BufferedReader : 从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。默认值足够大,可用于大多数用途
构造方法:
BufferedWriter(Writer out)
BufferedReader(Reader in)
//BufferedWriter,BufferedReader 默认大小8192
BufferedWriter bw = new BufferedWriter(new FileWriter("...."));
bw.write("hello\r\n"); //写
bw.close();
?
BufferedReader br = new BufferedReader(new FileWriter("...."));
char[] chs = new char[1024]; //读
int len;
while((len=br.read(chs))!=-1) {
System.out.print(String(chs,0,len));
}
br.close();
BufferedWriter bw = new BufferedWriter(new FileWriter("...."));
BufferedReader br = new BufferedReader(new FileWriter("...."));
?
char[] chs = new char[1024];
int len;
while((1en=br.read(chs))1=-1){
bw.write(chs,0,len);
}
br.close();bw.close();
//使用字符缓冲流 特有功能
BufferedWriter bw = new BufferedWriter(new FileWriter("...."));
BufferedReader br = new BufferedReader(new FileWriter("...."));
?
string line;
while((1ine=br.readLine())!=null) {
bw.write(line); //因为上面没有读取到换行符,写入的时候需手动写入
bw.newLine();
bw.flush();
}
bw.close();br.close();
BufferedWriter:
void newLine() : 写一行行分隔符,行分隔符字符串由系统属性定义
BufferedReader:
public String readLine() : 读一行文字。结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为null
BufferedWriter bw = new BufferedWriter(new FileWriter("...."));
BufferedReader br = new BufferedReader(new FileWriter("...."));
?
for(int i = 0;i < 10;i++) {
bw.write("hello" + i);
//bw.write("\r\n"); 换行Windows系统
bw.newLine(); //换行 推荐
bw.flush(); //刷新流
}
?
string line;
while((1ine=br.readLine())!=null) {
System.out.print1n(line); //某一行为空则返回null,结束循环
} //此处输出不包含所有终止符 包括换行符 所以使用println
bw.close();br.close();
字节流 (有5种方式 , 一般采用字节缓冲流一次读写一个字节数组的方式)
字节输入流:
FilelnputStream
BufferedInputStream
字节输出流:
FileOutputStream
BufferedOutputStream
字符流 (字符流只能复制文本数据 , 有5种方式 , 一般采用字符缓冲流的特有功能)
字符输入流(Reader):
lnputStreamReader --FileReader
BufferedReader
字符输出流(Writer):
OutputStreamWriter --FileWriter
BufferedWriter
原文:https://www.cnblogs.com/miku-jl/p/15129691.html