JAVA_基础IO流原理及流的分类(二)
IO流的分类
I/O
是input/output
的缩写,I/O
技术是非常实用的技术,用于处理设备之间的数据传输。如:读写文件、网络通信等。在Java
程序中,对于数据的输入/输出操作以:流(stream
)的方式进行。
流的分类
-
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
-
按数据流的流向不同分为:输入流,输出流
-
按流的角色的不同分为:节点流,处理流
(抽象基类) 字节流 字符流 输入流 inputStream Reader 输出流 OutputStream Writer
IO流体系结构
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer |
访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
访问管道 | PipedInputStream | PipedOutputStream | PipedReader | PipedWriter |
访问字符串 | StringReader | StringWriter | ||
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
转换流 | InputStreamReader | OutputStreamWriter | ||
对象流 | ObjectInputStream | ObjectOutputStream | ||
FilterInputStream | FilterOutputStream | |||
打印流 | PrintStream | printWiter | ||
推回输入流 | PushbackInputStream | PushbackReader | ||
特殊流 | DataInputStream | DataOutputStream |
流的使用
对于处理文本文件(
.txt,.java,.c,.cpp
),使用字符流处理。对于非文本文件(
.jpg,.mp3,.mp4,.avi,.doc,.ppt,....
),使用字节流处理
字符输入流
read()
: 返回读入的一个字符。如果达到文件末尾,返回-1。
异常处理:为了保证流资源一旦执行后,能够执行关闭操作,需要使用try-catch-findlly
处理。
读入的文件一定要存在,否则就会报FileNotfoundException
。
public void testFileReader() {
FileReader fr = null;
try {
// 1.实例化File类的对象,指明要操作的文件
File file = new File("hello.txt");// 相较于当前Module
// 2.提供具体的流
fr = new FileReader(file);
// 3.数据的读入过程
int data = fr.read();
while(data != -1) {
System.out.print((char)data);
data = fr.read();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.流的关闭操作
try {
if(fr != null) fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符输出流
输出操作,对应的File可以不存在的。
File
对应的硬盘中的文件不存在,则在输出的过程中自动创建文件。
File
对应的硬盘中的文件存在:
- 流使用的构造器是
FileWriter(file,false)
或FileWriter(file)
:对源文件做覆盖。 - 流使用的构造器是
FileWriter(file,true)
:对源文件内做追加。
public void testFileWriter() {
FileWriter fileWriter = null;
try {
// 1.提供File类的对象,指明写出到的文件
File file = new File("hello1.txt");
// 2.提供FileWriter的对象,用于数据的写出
// FileWriter fileWriter = new FileWriter(file);
// FileWriter fileWriter = new FileWriter(file,true);
FileWriter fileWriter = new FileWriter(file,false);
// 3.写出的操作
fileWriter.write("I have a dream!\n");
fileWriter.write("you need to have a dream!\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.流资源的关闭操作
if (fileWriter != null) {
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符输入流与字符输出流案例
public void testFileReaderFileWriter() {
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
// 1.创建File类对象,指明读入和写出的文件
File srcFile1 = new File("hello.txt");
File srcFile2 = new File("hello2.txt");
// 2.创建输入流与输出流对象
fileReader = new FileReader(srcFile1);
fileWriter = new FileWriter(srcFile2);
// 3.数据的读入与写出操作
char[] cbuf = new char[5];
int len;// 记录每次读入到数组中字符的个数
while((len = fileReader.read(cbuf)) != -1) {
// 从0开始,每次写出len个字符
fileWriter.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.关闭流资源
try {
if (fileWriter != null) fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (fileReader != null) fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节输入流与字符输出流
FileInputStream
与FileOutputStream
:使用方法与字符流一致,在处理文本文件是有可能出现乱码。
- 创建File类对象,指明读入和写出的文件。
- 创建输入流与输出流对象。
- 数据的读入与写出操作。
- 关闭流资源。
public void testFileInputOutputStream() {
FileInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
File srcFile = new File("image.png");
File destFile = new File("image2.png");
inputStream = new FileInputStream(srcFile);
outputStream = new FileOutputStream(destFile);
// 复制的过程
byte[] buffer = new byte[5];
int len;
while((len = inputStream.read(buffer)) != -1) {
// 从0开始,每次写出len个字符
outputStream.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null) outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (inputStream != null) inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
处理流:缓冲流
作用:提供流的读取、写入的速度。
缓冲流资源关闭:先关闭外层流(缓冲流),在关闭内层的流(节点流)。
在关闭外层流(缓冲流)的同时,内层流(节点流)也会自动的进行关闭。所有内层的关闭流可以省略。
// 非文本文件的复制
public void BufferedStreamTest() {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
// 1.造文件
File srcFile = new File("image.png");
File destFile = new File("image3.png");
// 2.造流
// 2.1 造节点流
FileInputStream fileInputStream = new FileInputStream(srcFile);
FileOutputStream fileOutputStream = new FileOutputStream(destFile);
// 2.2 造缓冲流
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
// 3.复制的细节:读取、写入
byte[] bytes = new byte[10];
int len;
while ((len = bufferedInputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.资源关闭
// 要求:先关闭外层流,在关闭内层的流
try {
if (bufferedOutputStream != null) bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bufferedInputStream != null) bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
// 在关闭外层流的同时,内层流也会自动的进行关闭。所有内层的关闭流可以省略
// fileOutputStream.close();
// fileInputStream.close();
}
}
flush()
:只要是缓冲输出流都会有flush()
刷新操作。
// 实现文件复制的方法
public void copyFileWithBuffered(String srcPath,String destPath) {
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
// 1.造文件
File srcFile = new File(srcPath);
File destFile = new File(destPath);
// 2.造流
// 2.1 造节点流
FileInputStream fileInputStream = new FileInputStream(srcFile);
FileOutputStream fileOutputStream = new FileOutputStream(destFile);
// 2.2 造缓冲流
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
// 3.复制的细节:读取、写入
byte[] bytes = new byte[1024];
int len;
while ((len = bufferedInputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes,0,len);
// bufferedOutputStream.flush();// 刷新缓冲区
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 4.资源关闭
// 要求:先关闭外层流,在关闭内层的流
try {
if (bufferedOutputStream != null) bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bufferedInputStream != null) bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void testCopyFile() {
long start = System.currentTimeMillis();
String srcPath = "F:\\视频.avi";
String destPath = "F:\\视频2.avi";
copyFileWithBuffered(srcPath,destPath);
long end = System.currentTimeMillis();
System.out.println( "复制文件消耗时间:" + (end - start));
}
readLine()
:一次输出一行,不报行换行符。
newLine()
:提供换行操作。
public void testBufferedReaderBufferedWriter() {
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
bufferedReader = new BufferedReader(new FileReader(new File("hello.txt")));
bufferedWriter = new BufferedWriter(new FileWriter(new File("hello3.txt")));
String data;
while((data = bufferedReader.readLine()) != null) {
bufferedWriter.write(data);// data中不包含换行符
bufferedWriter.newLine();// 提供换行操作
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
if (bufferedWriter != null) bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (bufferedReader != null) bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
处理流:转换流
转换流提供了在字节流和字符流之间的转换:
InputStreamReader
(属于字符流):将一个字节的输入流,转换为字符的输入流。
OutputStreamWriter
(属于字符流):将一个字符的输出流,转换为字节的输出流。
public void test2() {
InputStreamReader inputStreamReader = null;
OutputStreamWriter outputStreamWriter = null;
try {
File file1 = new File("dbcp.txt");
File file2 = new File("dbcp_gbk.txt");
FileInputStream fileInputStream = new FileInputStream(file1);
FileOutputStream fileOutputStream = new FileOutputStream(file2);
inputStreamReader = new InputStreamReader(fileInputStream,"UTF-8");
outputStreamWriter = new OutputStreamWriter(fileOutputStream,"GBK");
char[] cbuf = new char[1024];
int len;
while((len = inputStreamReader.read(cbuf)) != -1) {
outputStreamWriter.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (outputStreamWriter != null) outputStreamWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (inputStreamReader != null) inputStreamReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}