跟着刚哥梳理java知识点——IO(十五)
凡是与输入、输出相关的类、接口都定义在java.io包下
java.io.File类
1、File是一个类,可以有构造器创建其对象。此对象对应着一个文件或者一个目录。
2、File中的类,仅涉及到如何查找、创建、删除、重命名文件(.txt .jpg .java)或者目录(io\\io1)。如果涉及到文件里的内容的,File是无能为力的,只能用io流。
3、File类的对象常作为io流的具体类的构造器的形参。
4、mkdir和mkdirs:都是创建文件目录,但是mkdirs在没有上层目录的时候把上层所有缺失的目录都创建了,而mkdir则不行。
1 //绝对路径(文件) 2 File file1 = new File("d:\\io\\hello.txt"); 3 //相对路径(文件) 4 File file2 = new File("hello.txt"); 5 //绝对路径(目录) 6 File file3 = new File("d:\\io\\io1");
FileInputStream和FileOutputStream(字节流)
1、FileInputStream:从硬盘中读取一个文件到程序的内存中。
1 //①先声明一个file类,如果"hello.txt"文件不存在,则会抛出FileNotFoundException异常 2 File file = new File("hello.txt"); 3 //②创建一个FileInputStream类的对象 4 FileInputStream fis = new FileInputStream(file); 5 //③调用FileInputStream的方法,实现file文件的读取 6 int b = fis.read(); //read():读取下一个字节,执行到结尾返回-1 7 while(b!=-1){ 8 System.out.print((char)b); 9 fis.read(); 10 } 11 //④关系相应的类,需要显示的关闭资源 12 fis.close();
上面再读取文件时候是一个字节一个字节的读取,这是不现实的,现实中我们肯定要一批一批的读取。
这时我们就要用到read的重载方法read(byte[])
刚才的b的就变成了每次读入到byte中字节的长度,刚才③中的代码改成如下代码:
1 byte[] b = new byte[5]; //读取到的数据要写入的数据 2 int len; // 每次读入到byte中的字节的长度 3 while((len = fis.read(b)) = -1){ 4 for(int i = 0;i < len ;i++){ 5 system.out.print((char)b[i]); 6 } 7 }
输出结果:abcdefg
如果把上面代码len修改成b.length,结果呢 :
输出结果:abcdefgcde
为什么呢?当第一次调用fis.read(b)的时候,b数组的5个元素就变成了b[0]= a, b[1] = b,b[2] = c, b[3] = d,b[4] = e,当第二次调用read的时候,b[0] = f,b[1] = g,但是后面没值了所以没变化了。
2、FileOutputStream:从内存中读取一个文件存储到磁盘中。
1 // ①先声明一个file类,表明要写入的文件位置,输出的文件可以不存在,如果不存在则会自动创建 2 File file = new File("hello1.txt"); 3 //②创建一个FileOutputStream类的对象 4 FileOutputStream fos = new FileOutputStream(file); 5 //③写入的操作 6 fos.write(new String("i love my family").getBytes()); 7 //④关闭输出流 8 fos.close();
FileReader 和 FileWriter(字符流)
FileInputStream和FileOutputStream上面两个会了,这两个基本都一样的写法
把byte[]的b换成char[]就行了(字节换字符),其他的什么都不变
优点:可以读取到中文
缺点:只能处理文本文件,不能处理图片、视频等文件
BufferedInputStream和BufferedOutputStream
两个字节缓冲流(默认缓冲区大小是8M),可以提升读取文件速度
BUfferedOutputStream write完之后记着要flush 刷新一下
复制文件代码:
1 public static void main(String[] args) { 2 3 long time = System.currentTimeMillis(); 4 5 File source=new File("E:\\test\\a.txt"); 6 File target=new File("E:\\copy"); 7 FileInputStream fis=null; 8 FileOutputStream fos=null; 9 BufferedInputStream bis=null; 10 BufferedOutputStream bos=null; 11 12 byte[] ch=new byte[1024]; 13 int len=0; 14 15 try { 16 //创建流对象 17 fis=new FileInputStream(source); 18 //创建缓冲流 19 bis=new BufferedInputStream(fis); 20 if(!target.exists()){ 21 target.mkdirs(); 22 } 23 fos=new FileOutputStream(new File(target,source.getName())); 24 bos=new BufferedOutputStream(fos); 25 while((len=bis.read(ch))!=-1){ 26 bos.write(ch,0,len); 27 } 28 //刷新缓冲区 29 bos.flush(); 30 31 } catch (IOException e) { 32 e.printStackTrace(); 33 }finally{ 34 StreamUtils.closeInput(fis); 35 StreamUtils.closeInput(bis); 36 37 StreamUtils.closeOutput(fos); 38 StreamUtils.closeOutput(bos); 39 } 40 41 int costTime = (int) (System.currentTimeMillis() - time); 42 System.out.println("使用BIS和BOS的时间为:" + costTime + "ms"); 43 44 }
BufferedReader和BufferedWriter
两个字符缓冲流,可以提升文件读取速度(纯文本文件)
BufferedReader和BufferedWriter类各拥有8192字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。
word文件只能用字节流打开
例子:使用字符处理流实现文件复制
import java.io.*; class IODemo { public static void main(String[] args) { try { //使用BufferedReader和BufferedWriter进行文件复制(操作的是字符,以行为单位读入字符) FileReader fr=new FileReader("a.txt"); BufferedReader br=new BufferedReader(fr); FileWriter fw=new FileWriter("d.txt"); BufferedWriter bw=new BufferedWriter(fw); String s=br.readLine(); while(null!=s) { bw.write(s); //由于BufferedReader的rendLIne()是不读入换行符的,所以写入换行时须用newLine()方法 bw.newLine(); //read=fis.read(b); s=br.readLine(); } br.close(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } }
InputStreamReader和OutputStreamWriter 转换流
编码:字符串---》字节数组
解码:字节数组----》字符串
1 public static void main(String[] args) throws IOException { 2 BufferedReader br = null; 3 BufferedWriter bw = null; 4 try{ 5 //解码 6 File file = new File("dbcp.txt"); 7 FileInputStream fis = new FileInputStream(file); 8 InputStreamReader isr = new InputStreamReader(fis,"GBK"); 9 br = new BufferedReader(isr); 10 //编码 11 File file1 = new File("dbcp1.txt"); 12 FileOutputStream fos = new FileOutputStream(file1); 13 OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK"); 14 bw = new BufferedWriter(osw); 15 String str; 16 while ((str=br.readLine())!=null){ 17 bw.write(str); 18 bw.newLine(); 19 bw.flush(); 20 } 21 } 22 catch (IOException e){ 23 e.printStackTrace(); 24 } 25 finally { 26 bw.close(); 27 br.close(); 28 } 29 }
DataInputStream和DataOutputSteam 数据流
为了方便的操作java语言的基本数据类、String型、字节数组的数据,可以使用数据流
ObjectInputStream和ObjectOutputstream 对象流
用于存储和读取对象的处理流,它可以把对象写入到数据源中,也能把对象从数据源中还原回来。其实就是序列化和反序列化。
序列化:将内存中的java对象转换成二进制流,把这种二进制流永久的保存在磁盘上或者通过网络将这种二级制流传输到另一个网络节点。
反序列化:当其他程序获取了这种二进制流,恢复成原来的java对象。
① ObjectInputStream与ObjectOutputStream类所读写的对象必须实现Serializable接口,对象中transient和static类型成员变量不会被序列化
②
1 import java.io.*; 2 public class serializtion { 3 4 public static void main(String[] args)throws IOException{ 5 Student s1=new Student("张三", 1, 15, "化学"); 6 Student s2=new Student("李四", 2, 19, "生物"); 7 8 FileOutputStream fout=new FileOutputStream("student.txt"); 9 ObjectOutputStream out=new ObjectOutputStream(fout); 10 out.writeObject(s1); 11 out.writeObject(s2); 12 out.close(); 13 FileInputStream fin=new FileInputStream("student.txt"); 14 ObjectInputStream in=new ObjectInputStream(fin); 15 try { 16 s1=(Student) in.readObject(); 17 s2=(Student) in.readObject(); 18 } catch (ClassNotFoundException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 in.close(); 23 System.out.print("name:"+s1.name); 24 System.out.print(" id:"+s1.id); 25 System.out.print(" age:"+s1.age); 26 System.out.println(" department:"+s1.department); 27 System.out.print("name:"+s2.name); 28 System.out.print(" id:"+s2.id); 29 System.out.print(" age:"+s2.age); 30 System.out.println(" department:"+s2.department); 31 } 32 } 33 import java.io.*; 34 public class Student implements Serializable { 35 String name; 36 int id ; 37 int age; 38 String department; 39 public Student(String name, int id, int age, String department) { 40 this.age = age; 41 this.department = department; 42 this.id = id; 43 this.name = name; 44 } 45 }
RandomAccessFile 随机存取文件流
√ 既可以充当一个输入流,又充当一个输出流
√ 支持从文件的开头读取、写入。若文件不存在则创建,否则覆盖
√ 支持任意的位置的“插入”