java 文件字节和字符流 缓冲流

时间:2023-03-09 13:42:29
java 文件字节和字符流 缓冲流

流的原理

java 文件字节和字符流 缓冲流

1) 在 Java 程序中,对于数据的输入/输出操作以“流”
(stream) 方式进行;
2) J2SDK 提供了各种各样的“流”类,用以获取不同种类的
数据;程序中通过标准的方法输入或输出数据。
3) Java 的流类型一般位于 java.io 包中

IO流基本概念:----->https://www.cnblogs.com/oubo/archive/2012/01/06/2394638.html

文件字节流

FileInputStream/FileOutputStream

使用 FileInputStream 读取文件内容
1) abstract int read( ); //一次读取一个字节,读到文件末尾为-1
2) int read( byte b[ ] ); //从该输入流读取最多 b.length个字节的数据为字节数组。
3) int read( byte b[ ], int off, int len );
4) int available( ); //估算文件字节数
5) close( );  //关闭文件输入流

FileInputStream fis=new FileInputStream(new File("D:\\test.txt")); //在此之前"D:\\test.txt"不存在则new File(path)

如果"D:\\test.txt"已经存在,则不需new,直接FileInputStream fis=new FileInputStream("D:\\test.txt");即可

 import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; public class TestInpuStream {
public static void main(String[] args) throws IOException {
//(1)数据源与应用程序之间搭建管道
FileInputStream fis=new FileInputStream(new File("D:\\test.txt"));
//(2)从数据源开始向程序中读数据
int count=fis.available();
System.out.println("文件中大概有"+count+"个字节"); //中转站比较小,一次读一个字节
//System.out.println(fis.read()); //读取一个字节
//System.out.println(fis.available()); //文件中还有多少字节未读取 int buf=0;//存储读到的字节
int i=0;
while((buf=fis.read())!=-1){
i++;
System.out.print((char)buf);
}
//(3)关闭
fis.close();
System.out.println(i);
}
}
 import java.io.FileInputStream;
import java.io.IOException; public class TestInputStream2 {
public static void main(String[] args) throws IOException {
//(1)搭桥
FileInputStream fis=new FileInputStream("D:\\test.txt");
//(2)创建大一些的中转站
byte [] buf=new byte[1024];
int len=0;//用于存储每次读到的实际字节
int i=0;
while((len=fis.read(buf))!=-1){
i++;
//借助String类构造方法
System.out.println(new String(buf,0,len));
}
//(3)关闭
fis.close();
System.out.println(i);
}
}

使用 FileOutputStream 写内容到文件
1) abstract void write( int b );  //一次写一个字节
2) void write( byte b[ ] );  //将 b.length个字节从指定的字节数组写入此文件输出流。
3) void write( byte b[ ], int off, int len );
4) void flush( );//刷新缓冲区
5) void close( ); //关闭

 import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; public class TestFileOutputStream {
public static void main(String[] args) {
//(1)搭桥
FileOutputStream fos=null;
try {
fos = new FileOutputStream("D:\\a.txt",true);//如果有true这个参数则写入方式为追加,前提是有这个文件
//(2)写数据,一次写一个字节
//fos.write(97);
//(2)一次写多个字节
byte [] buf="helloworld".getBytes();//使用平台的默认字符集将此 String编码为字节序列,将结果存储到新的字节数组中。
fos.write(buf);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//(3)关闭
try {
if(fos!=null){
fos.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

使用字节流实现文件复制

文件复制的原理

java 文件字节和字符流 缓冲流

文件复制的代码实现

1.没经过异常处理前的代码

 import java.io.FileInputStream;
import java.io.FileOutputStream; public class TestFileCopy { public static void main(String[] args) {
//数据源是文件
FileInputStream fis = new FileInputStream("D:\\test.txt");
//目的地
FileOutputStream fos = new FileOutputStream("E:\\tager.txt"); int b = 0;//用于存储读到的字节,中转站
while( (b = fis.read()) != -1 ) {
//写入文件
fos.write(b);
}
//关闭
fos.close();
fis.close();
}
}

2.经过异常处理的代码:选中要处理的代码块(7~16行),按住Alt+Shift+Z,选第一个添加try/cath,写个finally把关闭io流放到里面去,在finally还要处理关闭io异常

先分别为两个关闭io流添加try/cath,在try中添加判断,如果io流不为null再关闭(为null会抛出一个空指针异常), 每次只读一个字节太费io,改为一次读字节数组个字节

 import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; public class TestFileCopy { public static void main(String[] args) {
//数据源是文件
FileInputStream fis = null;
//目的地
FileOutputStream fos = null;
try {
fis = new FileInputStream("D:\\test.txt");
fos = new FileOutputStream("E:\\tager.txt");
byte[] buf = new byte[1024];//中转站
int len = 0;//用于存储每次读到的字节个数
while( ((len = fis.read(buf)) != -1)) {
fos.write(buf,0,len);
}
/*int b = 0;//用于存储读到的字节,中转站
while( (b = fis.read()) != -1 ) {
//写入文件
fos.write(b);
}*/
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally {//无论程序是否产生异常,最后io都要关闭
//关闭
try {
if(fos != null) {
fos.close();
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
try {
if(fis != null) {
fis.close();
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}

文件字符流

Reader/Writer

使用 Reader 读取文件内容
1) int read( );
2) int read( char [ ]cbuf );

3) int read( char [ ]cbuf, int off, int len ); //将字符读入数组的一部分  cbuf目标缓冲区   off开始存储字符的偏移量  len要读取的最大字符数

4) int available( );
5) close( );

 import java.io.FileReader;
import java.io.IOException; public class TestFileReader {
public static void main(String[] args) throws IOException {
//(1)搭桥
FileReader reader=new FileReader("D:\\test.txt");
//(2)读取
//int b=reader.read(); //读到的字符的int类型数据
//System.out.println((char)b);
/*int b=0;//用于存储每次读到的字符数据的整数值
while((b=reader.read())!=-1){
System.out.println((char)b);
}*/
char [] cbuf=new char[1024];
int len=0;//用于存储读到的字符的个数
while((len=reader.read(cbuf))!=-1){
System.out.println(new String(cbuf,0,len));
}
//(3)关闭
reader.close();
}
}

使用 Writer 写内容到文件
1) void write( int c );
2) void write( char[]cbuf); 
3) abstract void write( char [ ]cbuf, int off, int len ); //cbuf缓冲区   off从中开始编写字符的偏移量  要写入的 len

4) void write(String str);  //直接把字符串str写入
5) abstract void flush( );  //刷新缓冲区
6) void close( );

 import java.io.FileWriter;
import java.io.IOException; public class TestWriter {
public static void main(String[] args) {
//创建对象
FileWriter writer=null;
try {
writer = new FileWriter("D:\\b.txt");
//写数据
writer.write("你好吗?");//写到了缓冲区中,
writer.flush(); //刷新缓冲区,如不刷新则需关闭才能写入
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭
try {
if(writer!=null){
writer.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

缓冲字节流
BufferedInputStream / BufferedOutputStream

FileInputStream 和 FileOutputStream 是节点流

java 文件字节和字符流 缓冲流

 import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; public class Filecopy { public static void main(String[] args) throws IOException {
//数据源
FileInputStream fis = new FileInputStream("F:\\java学习\\【API】jdk api 1.8_google.CHM");
//目的地
FileOutputStream fos = new FileOutputStream("F:\\java学习\\【API】jdk api 1.8_google2.CHM");
//读数据和写数据
long start = System.currentTimeMillis();
byte [] buf = new byte[1024];//中转站
int len = 0;
while( (len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
fos.flush();//手动刷新缓冲区
}
long end = System.currentTimeMillis();
System.out.println("文件复制一共用了"+(end-start)+"毫秒");//文件复制一共用了1143毫秒
//关闭
fos.close();
fis.close();
}
}

文件大小41M,用节点流在本机(机子性能较差)跑为1143毫秒。

BufferedInputStream 和 BufferedOutputStream 是处理流(包装
流)

java 文件字节和字符流 缓冲流

1) 读文件和写文件都使用了缓冲区,减少了读写次数,从而
提高了效率
2) 当创建这两个缓冲流的对象时时,会创建了内部缓冲数组,
缺省使用 32 字节大小的缓冲区.
3) 当读取数据时,数据按块读入缓冲区,其后的读操作则直
接访问缓冲区
4) 当写入数据时,首先写入缓冲区,当缓冲区满时,其中的
数据写入所连接的输出流。使用方法 flush()可以强制将缓
冲区的内容全部写入输出流
5) 关闭流的顺序和打开流的顺序相反.只要关闭高层流即可,
关闭高层流其实关闭的底层节点流
6) Flush 的使用:手动将 buffer 中内容写入文件

 import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException; public class TestCopy { public static void main(String[] args) throws IOException {
//数据源
FileInputStream fis = new FileInputStream("F:\\java学习\\【API】jdk api 1.8_google.CHM");
//目的地
FileOutputStream fos = new FileOutputStream("F:\\java学习\\【API】jdk api 1.8_google2.CHM"); /*
* 使用缓冲流
*/
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos); //读数据和写数据
long start = System.currentTimeMillis();
byte [] buf = new byte[1024];//中转站
int len = 0;
while( (len = bis.read(buf)) != -1) {
bos.write(buf, 0, len);
bos.flush();//手动刷新缓冲区
}
long end = System.currentTimeMillis();
System.out.println("文件复制一共用了"+(end-start)+"毫秒");//文件复制一共用了863毫秒
//关闭
bos.close();
bis.close();
}
}

同样的文件用缓冲流(处理流)时间为863

缓冲字符流
BufferedReader
readLine() 读取一个文本行的数据

BufferedWriter
newLine();写入一个行分隔符。

 import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; public class TestBuffered { public static void main(String[] args) {
//缓冲字符流
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader("D:\\a.txt"));
bw = new BufferedWriter(new FileWriter("D:\\copya.txt"));
String line = null;//用于存储读到的字符串
while( (line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
bw.flush();
}
} catch (FileNotFoundException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}finally {
try {
if(bw != null) {
bw.close();
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
try {
if(br != null) {
br.close();
}
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}

纯文本使用字符流,提高读取效率和写入效率使用缓冲字符流,其他情况都可使用字节流来完成