字节输入输出流
File
- 用file类对象可以获得文件的地址,目录,文件的长度,读写权限等,但是不能直接对文件进行读写.
- 使用File类并不会创建文件,可以将File类对象理解为文件的一个小名,总不能在程序中每次用到这个文件的时候都把绝对地址输入进去吧.
- 初始化:
三种初始化方式:
File file = new File("writed.txt");//文件与当前程序在同一目录中 File f = new File("D:\java的练习\IO流","file2.txt"); File file1 = new File(file,"writed.txt");
FileInputStream
FileInputStream可以用来读取文件,如果只是简单读取文件,可以使用FileInputStream类,这里说的简单指的是:首先,文件大小应该尽量小些,因为FileInputstream读取文件是比较慢的,所以,如果文件很大的话读取文件要耗费很长时间.其次,读出的内容尽量不含中文,或者读取的内容不需要直接输出显示.因为Unicode对中文的编码是三个字节,所以如果是中文的话,直接输出会一个字节一个字节输出,就可能会乱码.但是将文件里的内容写入另一个文件的话,底层操作会自动将这三个字节组成一个汉字(因为汉字在存储的时候,无论选择哪种编码存储,每一个字节都是负数),这样写入文件中的内容就不会是乱码.
- FileInputStream类是InputStream类的子类,实例方法都是从InputStream类继承来的.InputStream类是虚类不能直接使用.
- FileInputStream类用来读取文件,且是以字节为单位读取文件
- FileInputStream类的两个构造方法:
FileInputStream(String name)//参数是文件名eg:"a.txt"
FileInputStream(File file)//参数是文件类的对象,就是上面讲File初始化时构造的file,f,file2.
(下面这两种初始化方法也可以)
FileInputStream fileInputStream = new FileInputStream(new File("new.txt")); FileInputStream fis = new FileInputStream("file2.txt");
- FileInputStream会顺序的读取文件,每次调用read方法都会顺序地读取剩下的内容,直至文件末尾,或者流关闭
使用FileInputStream读取文件的方法
这是API里规定的read方法:
read()方法返回的是读取到的字节内容,read(byte[]b)是将读取到的内容存储到b数组里.i它返回的实际上是读取到的字节数,而不是读取到的内容.
下面这段代码演示了如何用File和FileInputStream读取文件
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class InputStream_ {
public static void main(String[] args) {
int n = -1;//默认n是文件结尾,这样读出来的任何字节都可以保证是从文件里读取出来的
byte []a = new byte[50];//将从文件中读取的一百个字节放入a数组中
File file = new File("new.txt");
try {
FileInputStream fileInputStream = new FileInputStream(file);//创建文件fIle的输入流
if((n=fileInputStream.read(a,0,50))!=-1){
String s = new String(a,0,n);//将读取到的字符数组转换成字符串
//String(byte[] bytes, int offset, int length)
//通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String 。
System.out.println(s);
}
} catch (IOException e) {
System.out.println("出错");
}
}
}
总结下来,如果想要用字节流读取一个文件,首先要实例化一个FileInputStream类对象,和一个用来存储读取出的内容的字节数组.读取后将该字节数组中的内容转化成字符串.
FileOutputStream
如果只是简单的向文件中写入内容,可以用FileOutputStream.
- FileOutputStream类是OutputStream类的子类,实例方法都是从OutputStream类继承来的
- FileOutputStream类用来向文件里写内容,以字节为单位
- FileOutputStream类的两个构造方法:
FileOutputStream(String name)//参数是文件名eg:"a.txt"
FileOutputStream(File file)//参数是文件类的对象
(看到这儿是不是感觉和FileInputStream大差不差?那么下面就是和FileInputStream不一样的地方了)
- 在使用FileOutputStream的上述两个构造方法时,如果输出流指向的文件不存在,Java就会自动创建该文件,如果指向的是已存在的文件,输出流就会将文件清空,也就是说文件的长度会变为零.(是不是听起来很离谱?难道就不能将一个文件不清空,同时还能向文件里写东西吗?当然可以!因为还有两种构造方法)
- FileOutputStream的另外两个构造方法
FileOutputStream(String name,Boolean append);
FileOutputStream(File file,Boolean append);
如果append取值为true,输出流不会刷新所指向的文件,将从文件结尾接着写入.FileInputStream会顺序的向文件中写入内容,每次调用write方法都会顺序地在文件尾写入内容,直至流关闭
如果append取值为false,输出流会刷新所指向的文件.
下面这个例子演示了如何用FileOutputStream基本的向一个文件写入内容
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputStream {
public static void main(String[] args) {
File file = new File("new.txt");
byte []a = "helloworld".getBytes();//将字符串转换成字节数组
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);//创建file的输出流
System.out.println(file.getName()+"的大小: "+file.length());
fileOutputStream.write(a);//将a写入文件,且无论之前的文件中有什么内容都将被刷新
fileOutputStream.close();//关闭输出流,主动使用close方法可以保证操作系统把缓冲区的内容放到磁盘上
System.out.println(file.getName()+"的大小: "+file.length());
fileOutputStream = new FileOutputStream(file,true);//向文件尾添加内容
fileOutputStream.write(a);//将a写入到文件尾
fileOutputStream.close();
System.out.println(file.getName()+"的大小: "+file.length());//查看是否写入成功
} catch (IOException e) {
System.out.println("错误");
}
}
}
附上运行结果
FileInputStream+FileOutputStream
用FileInputStream+FileOutputStream将一个文件中的内容写入到另一个文件中
可以当作练习,看看自己有没有掌握FileInputStreamh和FileOutputStream
import java.io.*;
public class Test {
public static void main(String[] args) {
File in = new File("new.txt");
File out = new File("writed.txt");
byte [] a = new byte[20];
int n = -1;
try {
FileInputStream fileInputStream = new FileInputStream(in);
FileOutputStream fileOutputStream = new FileOutputStream(out,true);
System.out.println(in.getName()+in.length());//查看原始in所指文件长度
System.out.println(out.getName()+out.length());//查看原始out所指文件长度
if((n = fileInputStream.read())!=-1){
fileInputStream.read(a,0,20);
}
fileOutputStream.write(a);
System.out.println(out.getName()+out.length());//查看写入内容后的out所指文件长度
} catch (IOException e) {
System.out.println("错误");
}
}
}
附上运行结果,从运行结果上可以看出,代码是对的
(学不会揍你是我之前的CSDN名)
字节流注意事项:
(1)字节流在读取内容的时候会读入每行最后的换行符"rn"(以windows系统举例),比如说,如果想要读取的文件的内容是12345,然后用一个七个字节的数组取读取的话,读取到的内容就是"12345rn"
(2)使用字节流写入内容时,如果需要换行,要自行添加.不同系统中的换行方式不同:
windows:"rn" mac:"r" Linux:"n"
(3)就着(1)来看,因为我的系统是windows的,所以换行符是"rn",有没有注意到有一行只输出了8,而不是8or?这是因为在读取完第一行末尾的low后,下一次读取的内容正好是"rn8",又因为用的是println输出,所以在输出完8之后就自动换行了.由这个例子可以看出,在用字节流读取文件的时候会将换行符读入,所以如果想要输出的话,println会破坏原有的文档格式,那么如果我们输出时想要保留文档的格式的话,就用print输出就行.
下面这个运行结果就是用print输出的,保留了原来文档的格式
字节缓冲流
先提出两个我之前在学习缓冲流的时候不理解的两个问题
(1)为什么要使用字节缓冲流?
使用字节缓冲流可以提高程序运行效率.因为字节缓冲流的源是字节流,而频繁调用字节流会导致程序运行起来很慢,所以可以使用缓冲区,将读取的数据暂时放进缓冲区,然后再从缓冲区将数据读取出来.
(2)为什么字节缓冲流的源是字节流?/为什么构造方法需要的是字节流而不是具体的文件?
因为字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作.
字节缓冲流:
- BufferOutputStream:该类实现缓冲输出流,通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为每次写入的每个字节导致底层系统的调用
- BufferInputStream:创建BufferInputStream将创建一个内部缓冲区数组.当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
构造方法:
- BufferOutputStream(OutputStream out);
- BufferInputStream(InputStream in);
码字不易,看到这儿不点个赞不合适吧?(给可怜还容易emo的我一点鼓励和支持吧~)
字符输入输出流
正如前面字节流里提到的,在含有中文的文件中,使用字节流读取不是很方便,所以我们需要学习如何使用字符流.字符流=字节流+编码表(ps:字符流也是有限制的,它只能赋值文本数据)
文件字符输入输出流
- FileReader(String filename); FileReader(File file);
- FileWriter(String filename); FileWriter(File file);
FileWriter(String filename,boolean append);
FileWriter(File file,boolean append);
字符缓冲流
BufferedReader(Reader in);
BufferedWriter(Writer out);
字符缓冲流的特有功能
BufferedWriter:
void newline():写一行行分隔符,行分隔符字符串由系统属性定义
BufferedReader:
public String readLine():读一行文字,结果包含行的内容的字符串,不包括任何终止字符,如果到达了流的结尾,会返回null.
下面这个例子是用字符缓冲流将new.txt里的内容读取到file2.txt中
import java.io.*;
public class Test {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("new.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("file2.txt"));
int ch;
while ((ch = br.read())!=-1){
bw.write(ch);
}
bw.close();
br.close();
}
}
总结(学习心得体会)
字节流和字符流都有各自的优缺点
字节流:优点是可以读取文档,图片,视频,音频.缺点是读取速度较慢,而且对于要读取之后立即输出的中文来说不太友好.
字符流:优点是读取速度快,缺点是只能读取文档文件,甚至word都不可以读取.
体会抽象类的好处:读取都是read(),写入都是write().



