常用IO流操作
作者:互联网
基本概念
IO:Java对数据的操作是通过流的方式,IO流用来处理设备之间的数据传输,上传文件和下载文件,Java用于操作流的对象都在IO包中
IO流的分类
字节流
字符流
该如何选择哪种IO流?
如果数据通过Window自带的记事本软件打开,我们还可以读懂里面的内容,就使用字符流,否则使用字节流。 如果你不知道该使用哪种类型的流,就使用字节流。
字节流
字节流基础类
InputStream类
InputStream:字节输入流基类,抽象类是表示字节输入流的所有类的超类。
read():
1.从读取流读取的是一个一个字节
2.返回的是字节的(0-255)内的字节值
3.读一个下次就自动到下一个,如果碰到-1说明没有值了.
read(byte[] bytes)
1.从读取流读取一定数量的字节,如果比如文件总共是102个字节
2.我们定义的数组长度是10,那么默认前面10次都是读取10个长度
3.最后一次不够十个,那么读取的是2个
4.这十一次,每次都是放入10个长度的数组.
read(byte[] bytes,int off ,int len)
1.从读取流读取一定数量的字节,如果比如文件总共是102个字节
2.我们定义的数组长度是10,但是这里我们写read(bytes,0,9)那么每次往里面添加的(将只会是9个长度),就要读12次,最后一次放入3个.
3.所以一般读取流都不用这个而是用上一个方法:read(byte[]);
OutputStream类
OutputStream:字节输出流基类,抽象类是表示输出字节流的所有类的超类。
write(int i);
直接往流写入字节形式的(0-255)int值.
write(byte[] bytes);
往流里边写入缓冲字节数组中的所有内容,不满整个数组长度的”空余内容”也会加入,这个下面重点讲,
write(byte[] bytes,int off,int len);
1.这个是更严谨的写法,在外部定义len,然后每次len(为的是最后一次的细节长度)都等于流往数组中存放的长度
2.如上述read(bytes),前面每次都放入十个,第十一次放入的是2个,如果用第二种write(bytes),将会写入输出流十一次,每次写入十个长度,造成后面有8个空的,比原来的内容多了
3.所以用write(byte[] bytes,int off,int len);就不会出现多出来的空的情况,因为最后一次len不同
字节文件操作流
FileInputStream
FileInputStream:字节文件输入流,从文件系统中的某个文件中获得输入字节,用于读取诸如图像数据之类的原始字节流。
package File;
import java.io.FileInputStream;
import java.io.IOException;
public class IODemo01 {
//字节文件操作流
//FileInputStream FileInputStream:字节文件输入流,从文件系统中的某个文件中获得输入字节,用于读取诸如图像数据之类的原始字节流。
public static void main(String[] args) throws IOException {
FileInputStream fis=new FileInputStream("D:\\java\\code\\IO_File\\1.txt");
int by;
//一次读取一个字节
while((by=fis.read())!=-1)
{
//因为字符在底层存储的时候就是存储的数值。即字符对应的ASCII码。
//所以需要强制转换一下类型
System.out.print((char)by);
}
fis.close();
}
}
package File;
import java.io.FileInputStream;
import java.io.IOException;
public class IODemo02 {
public static void main(String[] args) throws IOException {
FileInputStream fileInputStream=new FileInputStream("D:\\java\\code\\IO_File\\1.txt");
byte[] s1=new byte[10];
int len;
// 一次读取一个字节数组
while((len=fileInputStream.read(s1))!=-1)
{
System.out.println(len);
System.out.println(new String(s1,0,len));
}
// 注: 一次读取一个字节数组,提高了操作效率,IO流使用完毕一定要关闭。
fileInputStream.close();
}
}
FileOutputStream
FileOutputStream:字节文件输出流是用于将数据写入到File,从程序中写入到其他位置。
package File;
//FileOutputStream:字节文件输出流是用于将数据写入到File,从程序中写入到其他位置。
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
//创建字节流输出对象
//调用字节流写入方法
//释放资源
public class IODemo03 {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream=new FileOutputStream("D:\\java\\code\\IO_File\\2.txt");
Scanner scanner=new Scanner(System.in);
for (int i = 0; i < 3; i++) {
int a=scanner.nextInt();
fileOutputStream.write(a);
}
// 注意:
// 会发现输入65 66 67数字变成了字符ABC,因为字符在底层存储的时候就是存储的数值。即字符对应的ASCII码。
scanner.close();
fileOutputStream.close();
}
}
package File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class IODemo04 {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream=new FileOutputStream("D:\\java\\code\\IO_File\\2.txt",true);
Scanner scanner=new Scanner(System.in);
byte[] s1=new byte[10];
for (int i = 0; i < 3; i++) {
s1[i]=scanner.nextByte();
}
fileOutputStream.write(s1);
fileOutputStream.write('\n');
fileOutputStream.write(s1[0]);
byte[] s2="Hello,Link!".getBytes();
fileOutputStream.write('\n');
fileOutputStream.write(s2);
fileOutputStream.close();
// 注:
//输出的目的地文件不存在,则会自动创建,不指定盘符的话,默认创建在项目目录下;输出换行符时不一定是写\r\n或者写\n,因为不同的操作系统、不同文本编辑器对换行符的识别存在差异性。
// 注意:实验多次会发现写入是重新写的,想追加的话需要多传一个参数。
//创建一个向具有指定name的文件中写入数据的输出文件流
//如果第二个参数是true ,则字节将写入文件的末尾而不是开头。
// FileOutputStream(String name, boolean append)
}
}
字节缓冲流(高效流)
BufferedInputStream
BufferedInputStream:字节缓冲输入流,提高了读取效率。
package File;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class IODemo05 {
// 构造方法:
// // 创建一个 BufferedInputStream并保存其参数,即输入流in,以便将来使用。
// BufferedInputStream(InputStream in)
// // 创建具有指定缓冲区大小的 BufferedInputStream并保存其参数,即输入流in以便将来使用
// BufferedInputStream(InputStream in, int size)
public static void main(String[] args) throws IOException {
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("D:\\java\\code\\IO_File\\3.txt"));
byte[] s1=new byte[1024];
int len;
while((len=bis.read(s1))!=-1)
{
System.out.print(new String(s1,0,len));
}
bis.close();
}
}
BufferedInputStream 是缓冲输入流。它继承于FilterInputStream。
BufferedInputStream 的作用是为另一个输入流添加一些功能,例如,提供“缓冲功能”以及支持“mark()标记”和“reset()重置方法”。
BufferedInputStream 本质上是通过一个内部缓冲区数组实现的。例如,在新建某输入流对应的BufferedInputStream后,当我们通过read()读取输入流的数据时,BufferedInputStream会将该输入流的数据分批的填入到缓冲区中。每当缓冲区中的数据被读完之后,输入流会再次填充数据缓冲区;如此反复,直到我们读完输入流数据位置。
FileInputStream也可以实现缓冲区,那么该类的read跟BufferedInputStream的缓冲区有什么区别?
FileInputStream
public int read() throws IOException
从输入流中读取一个字节返回int型变量,若到达文件末尾,则返回-1
public int read(byte[] b) throws IOException
从输入流中读取b.length个字节到字节数组中,返回读入缓冲区的总字节数,若到达文件末尾,则返回-1
在使用read(byte b[])方法时的数组长度至关重要,若长度小于流的字节长度,那么最后得出的内容会出现丢失。若大于流的字节长度,那么最后数组的内存就浪费了,那么就需要根据文件的字节长度来设置数组的长度
public int read(byte[] b,int off,int len) throws IOException
从输入流中读取最多len个字节到字节数组中(从数组的off位置开始存储字节),当len为0时则返回0,如果len不为零,则该方法将阻塞,直到某些输入可用为止--此处存疑
BufferedInputStream
public BufferedInputStream(InputStream in)
Creates a BufferedInputStream and saves its argument, the input stream in, for later use. An internal buffer array is created and stored in buf.
public BufferedInputStream(InputStream in,
int size)
Creates a BufferedInputStream with the specified buffer size, and saves its argument, the input stream in, for later use. An internal buffer array of length size is created and stored in buf.
解释一:FileInputStream实现缓冲区这个实现是没有效率的,关键是要减少操作系统系统调用。BufferedInputStream中,比如你只要读一个字节,内部实现可能是向操作系统请求读100个字节放到缓冲区,下次读下一个字节就可以直接从缓冲区取了。
FileInputStream没有这种选择缓冲区大小的能力,而BufferedInputStream有这种能力,也就是说不需要你来关心这件事,JDK帮你做.
解释二:BufferedInputStream是套在某个其他的InputStream外,起着缓存的功能,用来改善里面那个InputStream的性能(如果可能的话),它自己不能脱离里面那个单独存在。FileInputStream是读取一个文件来作InputStream。所以你可以把BufferedInputStream套在FileInputStream外,来改善FileInputStream的性能。
FileInputStream与BufferedInputStream区别:
FileInputStream是字节流,BufferedInputStream是字节缓冲流,使用BufferedInputStream读资源比FileInputStream读取资源的效率高(BufferedInputStream的read方法会读取尽可能多的字节),且FileInputStream对象的read方法会出现阻塞;
简单说一下阻塞:
假设一个文件的长度是100个字节,要将之读取到内存中,再假设您每次只读取10个字节,那么读完整个文件是不是读取10次的呀?
假设老板让你完成100件事情,老板说,你每天只完成10件就可以了,难道你非得等到第十天才完成第100件事情吗?有一天您在中午下班前就完成了10件事情,下午您不妨多干一点,那么也许在第9天的时候就完成了100件事情。
同理,BufferedInputStream有可能会读取比您规定的更多的东西到内存,以减少访问IO的次数。简单点说阻塞就是你有能力办某一件事,但是,迫于其他压力或什么只能干等着每次只干固定的事,会浪费资源从而造成阻塞。
解释三:BufferedInputStream比FileInputStream多了一个缓冲区,执行read时先从缓冲区读取,当缓冲区数据读完时再把缓冲区填满。
因此,当每次读取的数据量很小时,FileInputStream每次都是从硬盘读入,而BufferedInputStream大部分是从缓冲区读入。读取内存速度比读取硬盘速度快得多,因此BufferedInputStream效率高。
BufferedInputStream的默认缓冲区大小是8192字节。当每次读取数据量接近或远超这个值时,两者效率就没有明显差别了。
BufferedOutputStream和FileOutputStream同理,差异更明显一些。
FileInputStream与BufferedInputStream的对比
FileInputStream inputStream = new FileInputStream("d://vv.mp4");
FileOutputStream outputStream = new FileOutputStream("v.mp4");
int len;
// 一次读取一个字节,每读取一个字节都要实现一次与硬盘的交互操作
while ((len = inputStream.read()) != -1) {
outputStream.write(len);
}
FileInputStream inputStream = new FileInputStream("d://vv.mp4");
FileOutputStream outputStream = new FileOutputStream("v.mp4");
int len;
byte[] bs = new byte[1024];
//这里添加了一个缓存数组,每次从硬盘读取1024个字节,也就是说,每读取1024个字节才与硬盘实现一次交互
while ((len = inputStream.read(bs)) != -1) {
outputStream.write(bs, 0, len);
}
FileInputStream inputStream = new FileInputStream("d://vv.mp4");
BufferedInputStream bis = new BufferedInputStream(inputStream); //默认有8M的缓存
FileOutputStream outputStream = new FileOutputStream("IP.mp4");
BufferedOutputStream bos = new BufferedOutputStream(outputStream);
int len;
byte[] bs = new byte[1024];
while ((len = bis.read(bs)) != -1) {
bos.write(bs, 0, len); //先从硬盘读出8M到缓存中。然后read,这里的read并不是从硬盘中读取,而是从那8M缓存(内存)中读取,自然要比从硬盘中快得多。8M缓存用完后又会从硬盘补充(也就是说,一次从硬盘获取8M字节的数据) 。每8M与硬盘交互一次
}
以上三种方式在效率上递增,用BufferedInputStream效率最高(特别是对小文件)。
另外,对于BufferOutputStream和FileOutputStream也是一样,BufferOutputStream的write是把字节写入自带的缓存中(flush之后才向硬盘写),而FileOutputStream则是一次一个字节的向硬盘写。
BufferedOutputStream
BufferedOutputStream:字节缓冲输出流,提高了写出效率。
构造方法:
// 创建一个新的缓冲输出流,以将数据写入指定的底层输出流
BufferedOutputStream(OutputStream out)
// 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流
BufferedOutputStream(OutputStream out, int size)
常用方法:
// 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流
void write(byte[] b, int off, int len)
// 将指定的字节写入此缓冲的输出流
void write(int b)
// 刷新此缓冲的输出流
void flush()
package File;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class IODemo06 {
public static void main(String[] args) throws IOException {
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("D:\\java\\code\\IO_File\\4.txt"));
bos.write("\n".getBytes());
// String的getBytes()方法是得到一个操作系统默认的编码格式的字节数组。这个表示在不同OS下,返回的东西不一样!
// String.getBytes(String decode)方法会根据指定的decode编码返回某字符串在该编码下的byte数组表示
bos.write("我爱北京天安门".getBytes());
bos.write(66);
bos.close();
}
}
字符流
字符流基类
Reader
Writer
字符转换流
InputStreamReader
InputStreamReader:字节流转字符流,它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
OutputStreamWriter
OutputStreamWriter:字节流转字符流。
package File;
import java.io.*;
public class IODemo07 {
/*
OutputStreamWriter(OutputStream out)
创建一个使用默认字符编码的OutputStreamWriter。
OutputStreamWriter(OutputStream out, Charset cs)
创建一个使用给定字符集cs的OutputStreamWriter。
*/
public static void main(String[] args) throws IOException {
// OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("D:\\java\\code\\IO_File\\5.txt"));
OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("D:\\java\\code\\IO_File\\5.txt"),"GBK");
osw.write("成都");
osw.close();
InputStreamReader isr=new InputStreamReader(new FileInputStream("D:\\java\\code\\IO_File\\6.txt"));
char[] s1=new char[1024];
int len;
while((len=isr.read(s1))!=-1)
{
System.out.print(new String(s1,0,len));
}
isr.close();
}
}
字符缓冲流(高效流)
BufferedReader
BufferedReader:字符缓冲流,从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
package File;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class IODemo08 {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader=new BufferedReader(new FileReader("D:\\java\\code\\IO_File\\7.txt"));
String s;
while ((s=bufferedReader.readLine())!=null)
{
System.out.println(s);
}
bufferedReader.close();
}
}
BufferedWriter
BufferedWriter:字符缓冲流,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
package File;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class IODemo09 {
public static void main(String[] args) throws IOException {
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter("D:\\java\\code\\IO_File\\8.txt",true));
for (int i = 0; i < 10; i++) {
bufferedWriter.write("我爱学习Java");
bufferedWriter.newLine();
bufferedWriter.write("我爱学习BufferedWriter");
bufferedWriter.newLine();
}
bufferedWriter.close();
}
}
标签:常用,java,字节,BufferedInputStream,FileInputStream,IO,new,操作,读取 来源: https://blog.csdn.net/weixin_38195506/article/details/116891633