3.字符输出流Writer
成员方法:
abstract void close() 关闭流,先刷新。
abstract void flush() 刷新流。
void write(char[] cbuf) 写入一个字符数组。
abstract void write(char[] cbuf, int off, int len) 写入字符数组的一部分。
void write(int c) 写一个字符。
void write(String str) 写一个字符串。
void write(String str, int off, int len) 写一个字符串的一部分。
4.FileWriter
- FileWriter 继承 OutputStreamWriter 继承 Writer
构造方法:
FileWriter(File file) 给一个File对象构造一个FileWriter对象。
FileWriter(File file, boolean append) 给一个File对象构造一个FileWriter对象。
FileWriter(String fileName) 构造一个给定文件名的FileWriter对象。
FileWriter(String fileName, boolean append)构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。
文件写入步骤
- 创建此类对象,构造方法写文件路径,调用write方法把数据写入到内存缓存区中(此间会将字符转换为字节),然后使用flush方法把内存缓冲区中的数据刷新到文件中,之后释放资源(释放资源也会把缓冲区数据刷新到文件中)
import java.io.FileWriter; import java.io.IOException; public class J04 { public static void main(String[] args) throws IOException { FileWriter fw=new FileWriter("字符测试文件.txt"); fw.write("知识点"); fw.flush();//刷新缓冲区数据到文件中 fw.close(); } } // 结果: // 文件中显示:知识点
续写和换行
- 续写:用有追加写开关的构造方法,即可,和字节续写相同,换行也相同。
四、缓冲流(增强流对象)
1.字节输出缓冲流(BufferedOutputStream)
BufferedOutputStream(OutputStream out) 继承 OutputStream
相当于将要输入的全部字节存储到某个地方,一次性发送到指定的地方,使虚拟机和操作系统间交互尽可能少,以提高效率。
构造方法:
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流
BufferedOutputStream(OutputStream out,int size) 创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流
当传递一个输出流对象后缓冲流会给这个对象增加一个缓冲区,提高FileOutputStream的写入效率,size可以指定也能默认。
使用:
创建FileOutputStream对象,构造方法中绑定输出地址,然后将创建的对象作为参数创建BufferedOutputStream类的对象,使用缓冲流的对象对文件进行写入操作,然后刷新缓冲区(flush),然后释放资源()
import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class Io_06 { public static void main(String[] args) throws IOException { FileOutputStream fos=new FileOutputStream("缓冲流测试.txt"); BufferedOutputStream bos=new BufferedOutputStream(fos); bos.write("测试缓冲流".getBytes()); bos.flush(); bos.close(); } }
2.字节输入缓冲流(BufferedInputStream)
- 继承自InputStream
构造方法:
BufferedInputStream(InputStream in) 创建一个BufferedInputStream并保存其参数,输入流 in ,供以后使用。
BufferedInputStream(InputStream in, int size) 创建BufferedInputStream具有指定缓冲区大小,并保存其参数,输入流 in ,供以后使用。
代码示例:
import java.io.*; public class Io_06 { public static void main(String[] args) throws IOException { FileInputStream fis=new FileInputStream("缓冲流测试.txt"); BufferedInputStream bis=new BufferedInputStream(fis); //是显示字符串,所以先创建字节数组,将输入的字节存储到字节数组中,然后通过Sting的构造方法将字节数组转换为字符串输出 int len; byte[] bytes=new byte[1024]; while ((len=bis.read(bytes))!=-1){ System.out.println(new String(bytes)); } bis.close(); } }
3.字符缓冲输出流(BufferedWriter)
继承自Writer
构造方法:
BufferedWriter(Writer out) 创建使用默认大小的输出缓冲区的缓冲字符输出流。
BufferedWriter(Writer out, int sz) 创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。
成员方法(特有):
void newLine() 写一行行分隔符。
实现代码:
import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; public class Io_07 { public static void main(String[] args) throws IOException { FileWriter fw=new FileWriter("缓冲流测试文件.txt"); BufferedWriter bw=new BufferedWriter(fw); bw.write("zdhd"); bw.newLine(); bw.write("shd"); bw.flush(); bw.close(); } } // 结果: // zdhd // shd
4.字符缓冲输入流(BufferedReader)
继承自Reader
构造方法:
BufferedReader(Reader in) 创建使用默认大小的输入缓冲区的缓冲字符输入流。
BufferedReader(Reader in, int sz) 创建使用指定大小的输入缓冲区的缓冲字符输入流
特有的成员方法
String readLine() 读一行文字。
以换行符(‘\n’),回传(‘\r’)或者回车后直接跟着换行(\r\n)作为结束行的标志
如果读取到的这一行无数据了,会返回null值,其他时候返回的是读取的数据(但是不会读取行的终止符合,即如果本来有换行,读取后是不会读取换行符)
代码示例:
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class Io_08 { public static void main(String[] args) throws IOException { BufferedReader br=new BufferedReader(new FileReader("缓冲流测试文件.txt")); //读的是一行,所以只有一字符串为类型接收数据 String str; while ((str=br.readLine())!=null){ System.out.println(str); } } } // 结果: // zdhd // shd
五、对文件内容进行排序
文件内容:
1.测试缓冲流10 9.测试缓冲流2 2.测试缓冲流9 3.测试缓冲流8 6.测试缓冲流5 4.测试缓冲流7 5.测试缓冲流6 8.测试缓冲流3 10.测试缓冲流1 7.测试缓冲流4
排序代码:
import java.io.*; import java.util.HashMap; public class IO_00 { public static void main(String[] args) throws IOException { /* 目的:将无序的10段话有序的录入进其他文件中 1.使用字符缓冲输入流,获取文件中的数据。 2.对数据进行切割,分离序号和文本内容 3.对文件数据用HashMap集合进行存储,K为序号,V为文本内容 4.遍历集合,将K,V值存储到指定文件 */ HashMap<String,String> hashMap=new HashMap<>(); BufferedReader br=new BufferedReader(new FileReader("缓冲流测试.txt")); BufferedWriter bw=new BufferedWriter(new FileWriter("缓冲流测试排序.txt")); String str; //每次获取一行数据,返回值为null表示获取完成 while ((str=br.readLine())!=null){ //'.'是转义字符,前面必须加\\来表示后面的 . 是普通字符 String[] strings=str.split("\\."); //将分割后的数据存储到集合中,K存储序号,V存储内容(HashMap会对数据按照K的数字大小进行排序) hashMap.put(strings[0],strings[1]); } //利用keySet方法将所有k值转换成set数组,并用增强for循环获取每个k值,然后利用get方法和k值获取每个v值 for (String k:hashMap.keySet()) { //分割后,分割符会取消,所以需要手动添加 bw.write(k+"."+hashMap.get(k)); //换行,同样换行符也会取消,也需要手动添加 bw.newLine(); } br.close(); bw.flush(); bw.close(); } }
结果:
1.测试缓冲流10 2.测试缓冲流9 3.测试缓冲流8 4.测试缓冲流7 5.测试缓冲流6 6.测试缓冲流5 7.测试缓冲流4 8.测试缓冲流3 9.测试缓冲流2 10.测试缓冲流1
六、转换流
作用:在文件进行写入或者读取操作时,文件是以字节形式存储在文件中,然后通过编码表对字节进行解码以呈现看得懂的文字,而就在在编码中,一般情况默认使用UTF-8编码,但是有的会使用GBK编码,如果编码录入,与解码读取所用的编码表不同,则会出现乱码情况,此时就可以使用转换流指定使用什么编码表进行读取或者写入操作。
OutputStreamWriter继承自Writer
InputStreamReader继承自Reader
构造方法:
输出的: OutputStreamWriter(OutputStream out)创建一个使用默认字符编码的OutputStreamWriter。 OutputStreamWriter(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter。
输入的: InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader 。InputStreamReader(InputStream in, String charsetName)创建一个使用命名字符集的InputStreamReader。
参数:OutputStream,InputStream:分别是字节输出流和字节输入流; charsetName:编码名称,不区分大小写,默认为UTF-8
使用步骤:
1.创建OutputStreamWriter对象,构造方法中new一个字节输出流,和指定编码。
2.用OutputStreamWriter对象,调用方法写入数据,然后刷新缓冲区,释放资源
3.创建InputStreamReader对象,构造方法new一个字节输入流,和指定编码。
4.调用方法读取文件,释放资源。
实现代码:
import java.io.*; public class Io_11 { public static void main(String[] args) throws IOException { OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("转换流测试.txt"),"gbk"); osw.write("转换流"); osw.flush(); osw.close(); InputStreamReader isr=new InputStreamReader(new FileInputStream("转换流测试.txt"),"gbk"); int i; while ((i=isr.read())!=-1){ System.out.print((char) i); } isr.close(); } }
七、序列化与反序列化
- 定义:用来将对象进行存储,将对象利用字节方式存储进文件为序列化,将对象从文件中读取叫反序列化。
1.ObjectInputStream和ObjectOutputStream
构造方法:
输出的:ObjectOutputStream(OutputStream out) 创建一个写入指定的OutputStream的ObjectOutputStream。参数是字节输出流
输入的:ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream。
特有方法:
输出的:void writeObject(Object obj) 将指定的对象写入ObjectOutputStream。
输入的:Object readObject() 从ObjectInputStream读取一个对象。
使用步骤:
1.先创建一个类及其对象a,并实现接口Serializable(不实现是会抛出异常的)
2.再创建ObjectOutputStream对象,调用writeObject方法,参数是a(即第一步创建的对象),把对象写入文件中
3.释放资源
4.创建ObjectInputStream对象,调用readObject方法,将对象读取出来,除了io异常外还有一个关于class文件的异常,即需要有这个文件,读取的对象用类型为Object的变量接收。
5.释放资源,打印对象。
实现代码:
import java.io.*; public class Io_12 { public static void main(String[] args) throws IOException, ClassNotFoundException { A a=new A("邹飞鸣"); ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("序列化测试.txt")); oos.writeObject(a); oos.close(); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("序列化测试.txt")); Object obj=ois.readObject(); ois.close(); System.out.println(obj); } } //实现接口 class A implements Serializable{ private String str; //定义有参构造方法一定还要定义一个无参的 public A(){} public A(String str){ this.str=str; } public String getStr() { return str; } public void setStr(String str) { this.str = str; } //为了输出具体的数值 @Override public String toString() { return "A{" + "str='" + str + '\'' + '}'; } } // 结果: // A{str='邹飞鸣'}
2.反序列化序列号异常问题
当类实现Serializable后类会有一个序列号,这个序列号会随着对象进行序列化存储进文件中,当进行反序列化时会比较文件中的和类中的是否一致,如果一致才会读取,否则会抛出异常,而当类中代码发生改变后(如变量修饰符)序列号也是会改变的,而此时再读取已经被序列化的文件时,就会产生异常,所以可以将序列号固定不变,可防止此类问题:需在类中添加代码:
static final long serialVersionUID = 42L;
3.transient(瞬态关键字)
- 作用,使修饰的变量不能够被序列化,即不能将赋好值的这个变量将值随着对象一起被存储进去。
- static修饰后也不能被序列化。
后记
Java全栈学习路线可参考:【Java全栈学习路线】最全的Java学习路线及知识清单,Java自学方向指引,内含最全Java全栈学习技术清单~