I/O流(A)
IO流这部分,算上学习File文件类的时间,总共花了三天时间学习,知识庞杂,种类繁多。但是说到底,各种各样的IO流,核心的方法无外乎构造()、read()、write()三种,根据文件类型的不同,选取不同的IO流。 东西太多,一次整理不完,因此分成几篇文章来整理,这里是IO概述、文件字节流、文件字符流、转换流四部分
I/O流概述
输入输出的概念
输入输出指的是系统内存与外部设备,网络等进行交互的过程。 |
I/O概念
流是一个抽象的概念。当Java程序需要从数据源读取数据时,会开启一个到数据源的流,这个流就是输出流,数据源可以是文件,内存或者网络等。同样,当程序需要输出数据到目的地时也一样会开启一个流,这个流就是输入流,数据目的地也可以是文件、内存或者网络等。流的创建是为了更方便地处理数据的输入输出。 流对象的操作依赖于操作系统,流通道本身并没有作用。
流分类
四大父类(抽象基类)
类名类名操作属性操作对象
字节输入流InputStream读入字节字符输入流Reader读入字符字节输出流OutputStream写出字节字符输出流Writer写出字符
* 根据是否具有额外功能:
类名类名操作属性操作对象额外功能
转换流InputStreamReaderOutputStreamWriter输入转换流输出转换流字节和字符转换字节到字符缓冲流BufferedXXXXXX的功能XXX的操作对象可以通过缓冲原理实现加速并且实现一些新功能
流对象操作步骤
创建流子类对象,绑定数据目的(数据源和目标文件)调用流方法进行读写操作.close();释放流对象(Java在程序结束时会自动关闭所有打开的流,但即便如此,显式的关闭任何打开的流仍是一个良好的习惯)。
I/O流注意事项
I/O流只能对整个文件进行操作,对文件中个别数据进行操作只能用数据库才能实现。流对象进行操作的时候经常会抛出IOException异常,所以需要用try{}catch{}语句来写。
文件字节流和文件字符流
主要区别
文件字节流可以读写任意文件(不包括文件夹),每次只操作文件中的一个字节。利用字节流创建的新文件可以保证不出错。文件字符流只能读写文本文件(用.txt格式打开之后能读懂的文件就是文本文件),用字符流创建除文本文件以外任意文件都会造成文件损坏。字节流不能直接操纵unicode字符,这时字符流的必要性就体现出来,因为一次操纵一个字符(即两个字节),这样就避免了数据传输中,汉字出现乱码等问题。
文件字节流
类名类名操作属性操作对象
文件字节输入流FileInputStream从文件中读入字节文件字节输出流FileOutputStream写出到文件中字节
文件字节输入流
构造器
作用是绑定输入数据源
文件字节输入流有两种构造方法: ——————————|FileInputStream(String filePath);||FileInputStream(File file); |——————————
示例代码
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class MyInputStream {
public static void main(String[] args) {
File file =
new File(
"d:\\java\\全职高手.txt");
FileInputStream
in =
null;
try {
in =
new FileInputStream(file);
}
catch (IOException ea) {
ea.getMessage();
throw new RuntimeException(
"\n运行发生错误,请尝试重新运行:");
}
finally {
try {
if (
in !=
null)
in.close();
}
catch (IOException eb) {
eb.getMessage();
throw new RuntimeException(
"\n输入流关闭失败,请尝试重新运行程序");
}
}
}
}
常用方法
方法表达式返回值注意事项
read();int(字节值)每次只读取一个字节,方法返回字节值,到达文件末尾返回-1read(byte b[])int(实际读取的字节个数)每次读取最多b空间大小的数量的字节,到达末尾返回-1b的大小太大会浪费空间,太小又影响速度,所以一般定义大小为1024read(byte b[], int off, int len)int(实际读取的字节个数)off指定数据存放在数组中的位置,len指定方法读取的最大字节数close();void显式关闭输入流
文件字节输出流
构造器
作用是绑定输出的输出目的
文件字节输出流有四种构造方法: ———————————————-|FileOutputStream(String filePath); ||FileOutputStream(File file); | |FileOutputStream(String filePath, boolean append); ||FileOutputStream(File file, boolean append); |———————————————-
输出流对象的构造方法可以创建对象,但是如果源文件存在,默认会覆盖原来的文件。
所有在构造方法的参数后边常常可以添加另外一个参数boolean append来决定如果文件存在是否覆盖,当apped**值为true**时,输出流会创建新文件覆盖目标文件,否则不覆盖,在目标文件中进行续写。
常用方法
方法表达式返回值注意事项
write(int b);void参数虽然是int类型,但是实际传参必须是byte类型write(byte b[])void写入b空间大小的数量的字节b的大小太大会浪费空间,太小又影响速度,所以一般定义大小为1024write(byte b[], int off, int len)voidoff指定数据存放在数组中的位置,即偏移量,len指定方法写入的最大字节数close();void显式关闭输出流
文件字符流
类名类名操作属性操作对象
文件字节输入流FileReader从文件中读入字节文件字节输出流FileWriter写出到文件中字节
* 转换流失文件字符流的父类,继承关系: * java.io.FileReader extends java.io.inputStreamReader; * java.io.inputStreamReader extends java.io.Reader; * java.io.Reader extends java.lang.Object; * 文件字符输入流和文件字符输出流都采用系统默认的编码表,中文版Windows系统默认系统编码表为GBK;
文件字符输入流
构造器
作用是绑定输入数据源文件字符输入流有两种构造方法: ————————–|FileReader(String filePath);||FileReader(File file); |————————–
常用方法
方法表达式返回值注意事项
read();int(字符值)每次只读取一个字节,方法返回字节值,到达文件末尾返回-1read(byte b[])int(实际读取的字符个数)每次读取最多b空间大小的数量的字节,到达末尾返回-1b的大小太大会浪费空间,太小又影响速度,所以一般定义大小为1024read(byte b[], int off, int len)int(实际读取的字符个数)off指定数据存放在数组中的位置,len指定方法读取的最大字节数close();void显式关闭输入流
文件字节输出流
构造器
作用是绑定输出的输出目的文件字符输出流有四种构造方法: —————————————-|FileWriter(String filePath); ||FileWriter(File file); | |FileWriter(String filePath, boolean append); ||FileWriter(File file, boolean append); |————————————– 输出流对象的构造方法可以创建对象,但是如果源文件存在,默认会覆盖原来的文件。所有在构造方法的参数后边常常可以添加另外一个参数boolean append来决定如果文件存在是否覆盖,当apped**值为true**时,输出流会创建新文件覆盖目标文件,否则不覆盖,在目标文件中进行续写。与文件字节输出流不同,文件字符输出流只能创建有效的文本文件。
常用方法
方法表达式返回值注意事项
write(int c);void参数虽然是int,但是实际传参要传char类型write(char b[])voidwrite(byte b[], int off, int len)voidoff指定数据存放在数组中的位置,即偏移量,len指定方法写入的最大字符数write(String str)把字符串中所有字符写到文件中write(String str, int off, int len)voidflush()void冲流,将数据写入文件(不进行冲流则数据无法写入文件)每次写入数据后进行一次冲流是一个好习惯close();void显式关闭输出流,再关闭流的同时进行一次冲流操作
文件字节流复制文件代码举例
import java.io.*;
class ClsByte {
private String originalpath, finalpath;
private long starttime, endtime;
public ClsByte(String a, String b) {
this.originalpath = a;
this.finalpath = b;
}
public void function() {
System.
out.println(
"字节流复制文件,开始执行:");
starttime = System.currentTimeMillis();
File orifile =
new File(originalpath);
File tarfile =
new File(finalpath);
FileOutputStream
out =
null;
FileInputStream
in =
null;
byte[] data =
new byte[
1024];
try {
in =
new FileInputStream(orifile);
out =
new FileOutputStream(tarfile,
false);
int len =
0;
while ((len =
in.read(data)) != -
1) {
out.write(data,
0, len);
}
}
catch (IOException e) {
e.getStackTrace();
throw new RuntimeException(
"\n文件传输中发生错误,请重试");
}
finally {
try {
if (
in !=
null) {
in.close();
}
}
catch (IOException e) {
throw new RuntimeException(
"\n输入流关闭失败,请重试");
}
try {
if (
out !=
null) {
out.close();
}
}
catch (IOException e) {
throw new RuntimeException(
"\n输出流关闭失败,请重试");
}
}
endtime = System.currentTimeMillis();
System.
out.println(
"文件复制成功\n源文件" + orifile.getAbsolutePath() +
"源文件大小" + orifile.getTotalSpace() +
"B");
System.
out.println(
"目标文件" + tarfile.getAbsolutePath() +
"目标文件大小" + tarfile.getTotalSpace() +
"B");
System.
out.println(
"消耗时间" + (endtime - starttime) +
"millseconds");
}
}
文件字符流复制文件代码举例
import java.io.*;
import java.util.*;
class ClsChar {
private String originalpath, finalpath;
private long starttime, endtime;
public ClsChar(String a, String b) {
this.originalpath = a;
this.finalpath = b;
}
public void function() {
System.
out.println(
"\n字符流复制文件,开始执行:");
starttime = System.currentTimeMillis();
File orifile =
new File(originalpath);
File tarfile =
new File(finalpath);
FileReader
in =
null;
FileWriter
out =
null;
char [] data =
new char [
1024];
try {
in =
new FileReader(orifile);
out =
new FileWriter(tarfile,
false);
int len =
0;
while ((len =
in.read(data)) != -
1) {
out.write(
new String(data,
0, len));
out.flush();
}
}
catch (IOException e) {
e.getStackTrace();
throw new RuntimeException(
"\n文件传输中发生错误,请重试");
}
finally {
try {
if (
in !=
null) {
in.close();
}
}
catch (IOException e) {
throw new RuntimeException(
"\n输入流关闭失败,请重试");
}
try {
if (
out !=
null) {
out.close();
}
}
catch (IOException e) {
throw new RuntimeException(
"\n输出流关闭失败,请重试");
}
}
endtime = System.currentTimeMillis();
System.
out.println(
"文件复制成功\n源文件" + orifile.getAbsolutePath() +
"源文件大小" + orifile.getTotalSpace() +
"B");
System.
out.println(
"目标文件" + tarfile.getAbsolutePath() +
"目标文件大小" + tarfile.getTotalSpace() +
"B");
System.
out.println(
"消耗时间" + (endtime - starttime) +
"millseconds");
}
}
转换流
转换流和文件字符流的区别
文件字符流是转换流的子类文件字符流的编码表已指定为系统默认编码表,转换流则可以指定编码表
FileWriter和FileReader:作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接用子类就完成操作了,简化了代码。
*
InputStreamReader isr =
new InputStreamReader(
new FileInputStream(
"a.txt"));
InputStreamReader isr =
new InputStreamReader(
new FileInputStream(
"a.txt"),
"GBK");
FileReader fr =
new FileReader(
"a.txt");
这三句代码的功能是一样的,其中第三句最为便捷。注意:一旦要指定其他编码时,绝对不能用子类,必须使用字符转换流。什么时候用子类呢?
条件:
操作的是文件。使用默认编码。
构造器
InputStreamReader(InputStream in)
创建的转换流使用默认字符集InputStreamReader(InputStream in, Charset cs)
创建的转换流使用指定的字符集”cs” OutputStreamWriter(OutputStream out)
创建的转换流使用默认字符集OutputStreamWriter(OutputStream out, Charset cs)
创建的转换流使用指定的字符集”cs”