java io基础总结
IO 是什么?其实就是Java中的一种输入和输出功能,也可以理解为对文件的写入和读出的操作,只不过Java中对这种操作叫做对流的操作。而流不只是对文件进行读写,还可以对内存,网络,程度操作。
根据数据的走向可分为输入流和输出流,这个走向是以内存为基准的,即往内存中读数据是输入流,从内存中往外写是输出流。根据处理的数据类型可分为字节流和字符流
1.字节流可以处理所有数据类型的数据,在java中以Stream结尾
2.字符流处理文本数据,在java中以Reader和Writer结尾。
io体系
1.1.1.Reader
抽象类,用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。
1.1.2. BufferedReader
继承自Reader类
从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
通常,Reader 所作的每个读取请求都会导致对底层字符或字节流进行相应的读取请求。因此,建议用 BufferedReader 包装所有其 read() 操作可能开销很高的 Reader(如 FileReader 和 InputStreamReader)。例如
BufferedReader in
= new BufferedReader(new FileReader("foo.in"));
缓冲指定文件的输入。如果没有缓冲,则每次调用 read() 或 readLine() 都会导致从文件中读取字节,并将其转换为字符后返回,而这是极其低效的。
1.1.3. InputStreamReader
继承自Reader
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。
每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。
1.1.4. FileReader
继承自InputStreamReader
用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。
FileReader 用于读取字符流。
@Test
public void fileReader() throws IOException {
File file = new File("E:\\test\\io\\Hello.txt");
FileReader fr = new FileReader(file);
char[] a = new char[50];
fr.read(a); // 读取数组中的内容
for (char c : a)
System.out.print(c); // 一个一个打印字符
fr.close();
}
1.2.1. Writer
抽象类
写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。
1.2.2. BufferedWriter
继承自Writer
将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性 line.separator 定义。并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。
通常 Writer 将其输出立即发送到底层字符或字节流。除非要求提示输出,否则建议用 BufferedWriter 包装所有其 write() 操作可能开销很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如
PrintWriter out
= new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
1.2.3. OutputStreamWriter
继承自Writer
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。
每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给 write() 方法的字符没有缓冲。
为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如
Writer out
= new BufferedWriter(new OutputStreamWriter(System.out));
1.2.4. FileWriter
继承自OutputStreamWriter
用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。
文件是否可用或是否可以被创建取决于底层平台。特别是某些平台一次只允许一个 FileWriter(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。
@Test
public void FileReader() throws IOException {
File file = new File("E:\\test\\io\\Hello.txt");
// 创建文件
file.createNewFile();
FileWriter writer = new FileWriter(file);
// 向文件写入内容
writer.write("This\n is\n an\n example\n");
writer.flush();
writer.close();
}
2.1.1. InputStream
此抽象类是表示字节输入流的所有类的超类。
2.1.2. FileInputStream
继承自InputStream
FileInputStream用于读取诸如图像数据之类的原始字节流
@Test
public void testFileInputStream1() throws Exception {
File file = new File("E:\\test\\io\\Hello.txt");
FileInputStream fis = new FileInputStream(file);
int b;
while ((b = fis.read()) != -1) {
System.out.print((char) b);
}
fis.close();
}
实现文件的复制
@Test
public void testFileInputStream2() throws Exception {
File file1 = new File("E:\\test\\io\\Hello.txt");
File file2 = new File("E:\\test\\io\\Hello2.txt");
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(file1);
fos = new FileOutputStream(file2);
byte[] b = new byte[1024];
int len;
while ((len = fis.read(b)) != -1) {
//错误的写法两种:
//fos.write(b);
//fos.write(b,0,b.length);
fos.write(b, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.1.3. BufferedInputStream
BufferedInputStream 为另一个输入流添加一些功能,即缓冲输入以及支持 mark 和 reset 方法的能力。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。mark 操作记录输入流中的某个点,reset 操作使得在从包含的输入流中获取新字节之前,再次读取自最后一次 mark 操作后读取的所有字节。
2.2.1. OutputStream
此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器。
2.2.2. FileOutputStream
继承自OutputStream
文件输出流是用于将数据写入 File 或 FileDescriptor 的输出流。
@Test
public void testFileOutputStream() {
File file = new File("E:\\test\\io\\Hello3.txt");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(new String("hello3").getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.2.3. BufferedOutputStream
该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
@Test
public void testBufferedOutputStream() {
File file = new File("E:\\test\\io\\Hello4.txt");
BufferedOutputStream fos = null;
try {
fos = new BufferedOutputStream(new FileOutputStream(file));
fos.write(new String("hello3").getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}