字节流
在前面的学习过程中,我们一直都是在操作文件或者文件夹,并没有给文件中写任何数据。现在我们就要开始给文件中写数据,或者读取文件中的数据
字节输出流OutputStream
OutputStream
此抽象类,是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法
输出流中定义都是写write
方法,如下图:
FileOutputStream类
OutputStream
有很多子类,其中子类FileOutputStream
可用来写入数据到文件。
FileOutputStream
类,即文件输出流,是用于将数据写入File
的输出流
构造方法
FileOutputStream类写入数据到文件中
将数据写到文件中
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
// 创建储存数据文件
File file = new File("c:\\test.txt");
// 创建一个用于文件操作文件的字节流对象,一旦创建就必须明确数据储存目的地
// 输出流是文件 会自动创建 如果存在会覆盖
FileOutputStream fos = new FileOutputStream(file);
// 调用父类的write方法
byte[] data = "abcde".getBytes();
fos.write(data);
// 关闭流资源
fos.close();
}
}
给文件中续写和换行
我们直接new FileOutputStream(file)
这样创建对象,写入数据,会覆盖原有的文件,那么我们想在原有的文件中续写内容怎么办呢?
继续查阅FileOutputStream
的API。发现在FileOutputStream
的构造函数中,可以接受一个boolean
类型的值,如果值true
,就会在文件末位继续添加
构造方法
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
// 创建储存数据文件
File file = new File("c:\\test.txt");
// 加true表示在原有的内容追加
FileOutputStream fos = new FileOutputStream(file, true);
// 调用父类的write方法
byte[] data = "abcde".getBytes();
fos.write(data);
// \r\n表示换行
byte[] data2 = "\r\n123".getBytes();
fos.write(data2);
// 关闭流资源
fos.close();
}
}
IO异常的处理
在前面编写代码中都发生了IO的异常。我们在实际开发中,对异常时如何处理的,我们来演示一下
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
// 创建储存数据文件
File file = new File("c:\\test.txt");
// 定义FileOutputStream的引用
FileOutputStream fos = null;
try{
// 创建FileOutpuStream对象
fos = new FileOutputStream(file);
// 写入数据
fos.write("abcde".getBytes());
}catch(IOException e){
throw new RuntimeException("文件写入失败");
}finally{
// 一定要判断fos是否为null 只有不为null时 才可以关闭
try {
if (fos != null){
fos.close();
}
} catch (IOException e) {
throw new RuntimeException("关闭资源失败");
}
}
}
}
字节输入流InputStream
过前面的学习,我们可以把内存中的数据写出到文件中,那如何想把内存中的数据读到内存中,我们通过InputStream
可以实现。InputStream
此抽象类,是表示字节输入流的所有类的超类。定义了字节输入流的基本共性功能方法
FileInputStream类
InputStream
有很多子类,其中子类FileInputStream
可用来读取文件内容,FileInputStream
从文件系统中的某个文件中获得输入字节
构造方法
FileInputStream类读取数据read方法
image.pngimport java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
// 创建储存数据文件 里面存了“abcde”
File file = new File("c:\\test.txt");
// 创建FileInputStream流
FileInputStream fis = new FileInputStream(file);
// 创建字节数组
byte[] b = new byte[2];
// 读取缓冲到数组里
// 返回读取到有效个字节数
int len = fis.read(b);
// String构造器中把byte数组转为字符串
System.out.println(new String(b)); // ab
System.out.println(len); // 2
int len2 = fis.read(b);
System.out.println(new String(b)); // cd
System.out.println(len2); // 2
int len3 = fis.read(b);
System.out.println(new String(b)); // ed
System.out.println(len3); // 1
int len4 = fis.read(b);
System.out.println(new String(b)); // ed
System.out.println(len4); // -1
fis.close();
}
}
原理图
image.png
刚开始两次复制两个字节,第三次只有一个字节,所有只复制了一个e,d是上次复制保留在数组中的,最后一次指针走完了,返回-1
字节流复制文件读取字节数组
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 字节流复制文件
* 采用数组缓冲提高效率
* 字节数组
* FileInputStream 读取字节数组
* FileOutputStream 写字节数组
*/
public class Copy {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("c:\\test.txt");
fos = new FileOutputStream("d:\\test.txt");
// 定义字节数组缓冲
byte[] bytes = new byte[1024];
// 读取数组 写入数组
int len = 0;
while((len = fis.read(bytes)) != -1){
fos.write(bytes, 0, len);
}
} catch (IOException e) {
System.out.println(e);
throw new RuntimeException("文件复制失败");
}finally{
try {
if(fos != null){
fos.close();
}
} catch (Exception e2) {
throw new RuntimeException("释放资源失败");
}finally{
try{
if(fis!=null)
fis.close();
}catch(IOException ex){
throw new RuntimeException("释放资源失败");
}
}
}
}
}
字节流
字符输出流FileWriter类
用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的
方法介绍
- void
write(int c)
写入单个字符 - void
write(String str)
写入字符串 - void
write(String str, int off, int len)
写入字符串的某一部分 - void
write(char[] cbuf)
写入字符数组 - abstract void
write(char[] cbuf, int off, int len)
写入字符数组的某一部分
import java.io.FileWriter;
import java.io.IOException;
public class Test2 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("c:\\test.txt");
// 写入一个字符, 写入是d
fw.write(100); // d
// FileWriter必须使用flush
fw.flush();
// 写入字符串数组
char[] c = {'a', 'b', 'c'};
fw.write(c);
fw.flush(); // abc
// 写入字符数组一部分
// 从1开始的位子写2给字符
fw.write(c, 1, 2);
fw.flush(); // bc
// 写入字符串
fw.write("cuzz");
fw.flush(); // cuzz
fw.close();
}
}
字符输入流FileReader类
方法介绍:
- int
read()
读取单个字符 - int
read(char[] cbuf)
将字符读入数组 - abstract int
read(char[] cbuf, int off, int len)
将字符读入数组的某一部分
import java.io.FileReader;
import java.io.IOException;
public class Test3 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("c:\\test.txt");
char[] ch = new char[1024];
int len = 0;
while((len = fr.read(ch)) != -1){
System.out.println(new String(ch, 0, len));
}
fr.close();
}
}
flush方法和close方法区别
-
flush()
方法
用来刷新缓冲区的,刷新后可以再次写出,只有字符流才需要刷新 -
close()
方法
用来关闭流释放资源的的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出
字符流复制文本文件
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 字符流复制文本文件,必须文本文件
* 字符流查询本机默认的编码表,简体中文GBK
* FileReader读取数据源
* FileWriter写入到数据目的
*/
public class Copy_2 {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try{
fr = new FileReader("c:\\test.txt");
fw = new FileWriter("d:\\test.txt");
char[] cbuf = new char[1024];
int len = 0 ;
while(( len = fr.read(cbuf))!=-1){
fw.write(cbuf, 0, len);
fw.flush();
}
}catch(IOException ex){
System.out.println(ex);
throw new RuntimeException("复制失败");
}finally{
try{
if(fw!=null)
fw.close();
}catch(IOException ex){
throw new RuntimeException("释放资源失败");
}finally{
try{
if(fr!=null)
fr.close();
}catch(IOException ex){
throw new RuntimeException("释放资源失败");
}
}
}
}
}
网友评论