Java编程基础之IO流
Posted Ocean:)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java编程基础之IO流相关的知识,希望对你有一定的参考价值。
IO流
IO流基类
-
InputStream
输入流基类
read
-
OutputStream
输出流基类
write
IO流分类
-
流向分类
输入输出
-
文件操作处理单元分类
字节流和字符流
-
FileInputStream
文件操作输入字节流
-
FileOutputStream
文件操作输出字节流
-
FileReader
文件操作输入字符流
-
FileWriter
文件操作输出字符流
文件操作字节流
文件操作输入字节流
FileInputStream
Constructor构造方法
-
FileInputStream(File file);
这里是根据提供的File类对象创建对应的文件操作输入字节流
-
FileInputStream(String pathName);
这里是根据提供的String类型文件路径,创建对应的文件操作输入字节流
两个方法都会抛出FileNotFoundException文件未找到异常
Method成员方法
-
int read();
从文件中读取一个字节数据返回到方法外
虽然返回值是一个int类型,但是整个int类型当中存储的数据是一个byte类型,有且只有低8位数据有效
-
int read(byte[] buf);
读取文件的内容是存储在byte类型数组中,返回值是读取到的字节个数
-
int read(byte[] buf, int offset, int count);
读取文件的内容是存储在byte类型数组中,要求byte数组offset位置开始,到count长度结束,返回值是读取到的字节个数
这三个方法,如果读取到文件末尾,返回值都是-1 EOF (End Of File),并且都要抛出IOException异常
FileInputStream实例:
package obj_file;
import java.io.File;
import java.io.FileInputStream;
public class Demo6 {
public static void main(String[] args) {
// 打开文件创建句柄
File file = new File("D:\\\\JavaCode\\\\test\\\\1.txt");
// 2.字节输入流读取文件对象
FileInputStream fileInputStream = null;
try {
// 3.根据File类对象创建对应的字节输入流
fileInputStream = new FileInputStream(file);
// 4.准备一个8KB字节缓冲数组
byte[] buf = new byte[1024 * 8];
int length = -1;
// 5.读取数组
while ((length = fileInputStream.read(buf)) != -1) {
System.out.println(new String(buf));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 在finally代码中关闭资源
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
使用缓冲区速度会提高很多
FileOutputStream
FileOutputStream 文件操作输出字节流
Constructor构造方法
-
FileOutputStream(File file);
根据File类对象创建对应的文件的输出字节流对象
-
FileOutputStream(String pathName);
根据String类型文件路径创建对应的文件输出字节流对象
两个构造方法都是删除写方式,删除原文件后创建新文件写入数据
-
FileOutputStream(File file, boolean append);
根据File类对象创建对应的文件的输出字节流对象
-
FileOutputStream(String pathName, boolean append);
根据String类型文件路径创建对应的文件输出字节流对象
append为true表示追加写
Method成员方法
-
void write(int b);
写入一个字节数据到当前文件中,参数是int类型,但是有且指挥操作对应的第八位数据
-
void write(byte[] buf);
写入字节数组中的内容到文件中
-
void write(byte[] buf, int offset, int length);
写入字节数组中的内容到文件中,从指定的offset开始,到指定长度length
以上方法会抛出IOException异常
实例:
package obj_file;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo8 {
public static void main(String[] args) {
copyTest();
}
public static void copyTest() {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
// 1.创建文件输入字节流
fis = new FileInputStream("D:\\\\JavaCode\\\\test\\\\1.txt");
// 2.创建文件输出字节流
fos = new FileOutputStream("D:\\\\JavaCode\\\\test\\\\2.txt");
// 3.准备一个缓冲数组8KB
byte[] buf = new byte[1024 * 8];
int length = -1;
// 4.读取文件数据
while ((length = fis.read(buf)) != -1) {
fos.write(buf, 0, length);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 先开的后关,先关的后开
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
文件操作字符流
字符流特征
字符流 = 字节流 + 解码过程
字符组合过程 => 对应当前环境编码集的一个字符
如果字符找不到,该数据无效,需要被删除
如果是字符内容操作,效率较高,如果是非字符操作效率较低
文件操作字符输入流
Constructor构造方法
-
FileInputStream(File file);
这是根据提供的File类对象创建对应的文件操作输入字节流
-
FileInputStream(String pathName);
这里是根据提供的String类型文件路径,创建对应的文件操作输入字节流
两个构造方法都会抛出异常,FileNotFoundException文件未找到异常
Method成员方法
-
int read();
从文件中读取一个字节数据返回到方法外
虽然返回值是一个int类型,但是在整个int类型中存储的数据是一个byte类型,有且只有低8位数据有效
-
int read(byte[] buf);
读取文件的内容是存储在byte类型数组中,返回值是读取到的字节个数
-
int read(byte[] buf, int offset, int count);
读取文件的内容是存储在byte类型数组中,要求从byte数组offset位置开始,到count长度结束,返回值是读取到的字节个数
这三个方法如果读取到文件末尾,返回值都是-1 EOF End Of File,都要抛出异常IOException
实例
统计字符串内每个英文字母的个数
package obj_file;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
public class Demo9 {
public static void main(String[] args) throws IOException {
FileReader fileReader = new FileReader(new File("D:\\\\JavaCode\\\\test\\\\1.txt"));
int[] counts = new int[52];
char[] buf = new char[1024];
int length = -1;
length = fileReader.read(buf);
for (int i = 0; i < length; i++) {
if (buf[i] >= 'A' && buf[i] <= 'Z') {
counts[buf[i] - 65] += 1;
} else if (buf[i] >= 'a' && buf[i] <= 'z') {
// 71 = 97 -26
counts[buf[i] - 71] += 1;
}
}
System.out.println(Arrays.toString(counts));
fileReader.close();
}
}
输出结果
结果有些抽象,但是计算很快,从左到右分别表示大写字母A到Z的个数,小写字母a到z的个数
文件操作字符输出流
Constructor
写入过程中,发生问题会产生IOException
package obj_file;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Demo10 {
public static void main(String[] args) {
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(new File("D:\\\\JavaCode\\\\test\\\\test.txt"));
fileWriter.write("O");
fileWriter.write("C");
fileWriter.write("E");
fileWriter.write("A");
fileWriter.write("N");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流文件拷贝
如果文件不是文本文件,拷贝可能因为编码方式不同,导致文件损坏
缓冲流
使用缓冲数组以后,整体的读取,写入效率提升很大
降低了CPU通过内存访问硬盘的次数
-
字节输入缓冲
BufferInputStream
-
字节输出缓冲
BufferInputStream
-
字符输入缓冲
BufferedReader
-
字符输出缓冲
BufferedWrite
注意:所有的缓冲流都没有任何的读取,写入文件能力,这里都需要对应的输入流和输出流来提供对应的能力
在创建缓冲流对象时,需要传入对应的输入流对象和输出流对象
底层就是提供了一个默认大小的缓冲数组,用于提高效率
字节缓冲流
-
输入
BufferedInputStream(InputStream in);
这里需要的对象是一个字节输入流基类对象,同时也可以传入InputStream子类对象
-
输出
BuffedOutputStream(OutputStream out);
这里需要的对象是一个字节输出流基类对象,同时也可以传入OutputStream子类对象
以上传入的InputStream和OutputStream都是用于提供对应文件的读写能力
实例:
package obj_file;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Demo11 {
public static void main(String[] args) throws IOException {
// 1.找到对应文件
File file = new File("D:\\\\JavaCode\\\\test\\\\1.txt");
// 2.创建对应的FileInputStream输入流
FileInputStream fileInputStream = new FileInputStream(file);
// 3.根据文件操作字节输入流对象,创建对应的缓冲流对象
BufferedInputStream bis = new BufferedInputStream(fileInputStream);
// 4.读取数据过程,读取过程中使用的方法是FileInputStream提供的方法
int content = -1;
while ((content = bis.read()) != -1) {
}
bis.close();
}
}
运行速度大大提升
字节输入流缓冲效率问题
- 在BufferedInputStream底层中有一个默认容量为8KB的byte类型缓冲数组
- fill方法是一个操作核心
- 从硬盘中读取数据,读取的数据容量和缓冲数组容量一致
- 所有read方法,都是从缓冲数组中读取数据
- 每一次读取数据之前,都会检查缓冲区内是否有数据,如果没有,fill方法执行,填充数据
- 利用缓冲,fill方法,可以极大的降低cpu通过内存访问硬盘的次数,同时程序操作的数据是在内存中进行交互的
字节输出缓冲效率问题
- BufferedOutputStream类对象,默认有一个8KB的byte类型缓冲数组
- 数据写入文件时并不是直接保存到文件中,而是保存在内容8KB字节缓冲数组中
- 如果8KB空间填满,会直接flush缓冲区,数据保存到硬盘中,同时清空整个缓冲区
- 在BufferedOutputStream关闭时,首先会调用flush方法,保存数据到文件,清空缓冲区,并且规划缓冲区占用内存,同时关闭缓冲流使用的字节输出流
字符缓冲流
-
BufferedReader
字符缓冲输入流
BufferedReader(Reader reader);
-
BufferedWriter
字符缓冲输出流
BufferedWriter(Writer writer)
实例:
package obj_file;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;import javax.lang.model.type.NullType;
public class Demo12 {
public static void main(String[] args) {
bufferedReader();
bufferedWriter();
}
private static void bufferedWriter() {
BufferedWriter bw = null;
try {
bw = new BufferedWriter(new FileWriter(new File("D:\\\\JavaCode\\\\test\\\\1-1.txt")));
bw.write("ocean");
bw.newLine();
bw.write("ocean");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static void bufferedReader() {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(new File("D:\\\\JavaCode\\\\test\\\\1.txt")));
System.out.println(br.readLine());
System.out.println(br.readLine());
System.out.println(br.readLine());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
以上是关于Java编程基础之IO流的主要内容,如果未能解决你的问题,请参考以下文章
java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段
java基础之 IO 流(RandomAccessFile类)
java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段