Java笔记--08

来源:互联网 发布:validateform js 编辑:程序博客网 时间:2024/06/05 18:40

IO需要掌握的16个流
FileInputStream
FileOutputStream
FileReader
FileWriter

BufferedReader
BufferedWriter
BufferedInputStream
BufferedOutputStream

DataInputStream
DataOutputStream

ObjectInputStream
ObjectOutputStream

转换流(字节流转换成字符流)
InputStreamReader
OutputStreamWriter

PrintWriter
PrintStream(标准的输出流:默认输出到控制台)


FileInputStream

java.io.InputStream;     java.io.FileInputStream;文件字节数入流,按照字节方式读取文件     1.要读取某文件,先给这个文件创建一个"输入流"     //文件路径    String filePath = "txt";//相对路径,相对当前而言,在当前路径找下去;也可以是绝对路径,F:\\workspace\\08\\txt或者F:/workspace/08/txt    FileInputStream fis = new FileInputStream(filePath);    2.开始读(如果已经读取到文件的末尾,就会返回-1)    int temp=0;    while((temp=fis.read()) != -1){    System.out.println(temp);    }    3.释放资源,为了保证流一定会释放,所以在finally语句块中执行    finally{    fis.close();    }

注意:在读取文件时可能出现FileNotFountException,而该异常是编译期异常,因此要进行try…catch…处理
用上面这样的程序存在缺点:频繁访问磁盘,伤害磁盘,并且效率低,因此系统提供了int read(byte [] bytes);方法
该方法在读取之前在内存中准备一个byte数组,每次读取多个字节存储到bytes数组中一次读取多个字节,不是单个字节读取了,效率高

1.创建输入流FileInputStream fis = new FileInputStream("txt");//txt.txt文件中存储的是abcd2.开始读//准备一个数组并声明一次最多可以读取几个字节byte [] bytes = new byte[3];每一次最多读取3个字节int i1 = fis.read(bytes);//3//注意:int read(byte [] bytes);该方法返回的int类型的值代表的是:这次读取了多少个字节//将byte数组转换成字符串System.out.println(new String(bytes));//abcint i2 = fis.read(bytes);//1System.out.println(new String(bytes));//dbc如果要想正确显示最后一次读取的数据,应该用String(byte [] bytes,int offset,int length);方法;其中offset是从几开始读,length是读取的长度System.out.println(new String(bytes,0,i2));//dbc3.关闭流资源fis.close();用数组的方式循环读取FileInputStream fis = new FileInputStream("Test");byte [] bytes = new byte[1024];//每次读取1KBint temp = 0;while((temp=fis.read(bytes)) != -1){//将byte数组有效的数据转换成字符串      System.out.print(new String(bytes,0,temp));       }fis.close();注意:因为Test文件中本身自带换行,因此在输出时不能再用println()方法了,而要用print()方法int available();返回流中剩余的估计字节数skip(long n);从输入流中跳过并丢弃n个字节的数据

FileOutputStream

java.io.OutputStream;    java.io.FileOutputStream;文件字节输出流,将计算机内存中的数据写入硬盘文件中FileOutputStream fos = null;    try{    //1.创建文件字节输出流    //fos = new FileOutputStream("temp01");//谨慎使用,会将源文件覆盖    //以追加的方式写入    fos = new FileOutputStream("temp01",true);    //2.开始写    String msg = "HelloWorld!";    //将String转换成byte数组    byte[] bytes = msg.getBytes();    fos.write(bytes);    //write(byte [] bytes,int offset, int length);该方法可以将数组中指定长度写入   //推荐最后的时候为了保证数据完全写入硬盘,所以要刷新   fos.flush();    }catch(Exception e){    e.printStream();    }finally{    //3.关闭流资源    if(fos != null){    try{        fos.close();       }catch(Exception e){        e.printStream();    }    }}

关于文件复制粘贴
以下为了书写的简便不采用try…catch…进行处理,而是用throws语句进行声明,正常编程中要用try…catch…处理

//创建输入流FileInputStream fis = new FileInputStream("FileOutputStream.java");//创建输出流FileOutputStream fos = new FileOutputStream("F:/FileOutputStream.java");//一边读一边写byte [] bytes = new byte[1024];int temp = 0;while(temp=fis.read(bytes) != -1){//将byte数组中的内容直接写入     fos.write(bytes,0,temp);}//刷新fos.flush();//关闭流资源fis.close();fos.close();

FileReader

java.io.Reader;     java.io.InputStreamReader;//转换流(字节输入流-->字符输入流)      java.io.FileReader;文件字符输入流//创建字符输入流FileReader fr = null;fr = new FileReader("Test");//开始读char [] chars = new char[512];//1KB,一个字符占两个字节int temp = 0;while((temp=fr.read(chars))!=-1){//将char数组有效部分转换成字符串    System.out.print(new String(chars,0,temp));    }//关闭fr.close();

FileWriter

java.io.Writer;    java.io.OutputStreamWriter;//转换流(字节输出流-->字符输出流)     java.io.FileWriter;文件字符输出流//创建字符输出流//FileWriter fw = new FileWriter("temp02");//覆盖FileWriter fw = new FileWriter("temp02",true);//追加//开始写fw.write("海波东--冰皇");//将char数组的一部分写入char [] chars = {'我','看','过','好','多','小','说','了','!'};fw.write(chars,0,3);//我看过//刷新fw.flush();fw.close();

用FileReader和FileWriter实现文件复制
只能复制纯文本

FileReader fr = new FileReader("Test02.java");FileWriter fw = new FileWriter("F:/Test02.java");char [] chars = new char[512];//1KBint temp = 0;while((temp=fr.read(chars))!=-1){    //写    fw.write(chars,0,temp);    }fw.flush();fr.close();fw.close();

BufferedReader;带有缓冲区的字符输入流
BufferedWriter;带有缓冲区的字符输出流
BufferedInputStream;带有缓冲区的字节输入流
BufferedOutputStream;带有缓冲区的字节输出流

java.io.Reader;    java.io.BufferedReader;//创建一个带有缓冲区的字符输入流FileReader fr = new FileReader("BufferedReaderTest.java");//创建一个文件字符输入流BufferedReader br = new BufferedReader(fr);//将文件字符输入流包装成带有缓冲区的字符输入流//根据流出现的位置,流又可以分为:包装流和节点流,FileReader fr是一个节点流,BufferedReader br是一个包装流//上面两句可以合为一句BufferedReader br = new BufferedReader(new FileReader("BufferedReaderTest.java"));//开始读String temp = null;while((temp=br.readLine())!=null){//br.readLine()方法读取一行,但是行尾不带换行符    System.out.println(temp);    }//关闭流资源//注意:关闭的时候只需要关闭最外层的包装流(这里有一个装饰者模式)br.close();

如何将FileInputStream包装成BufferedReader?

//创建一个文件字符输入流FileInputStream fis = new FileInputStream("BufferedReaderTest.java");//转换流(将字节流转换成字符流)InputStreamReader isr = new InputStreamReader(fis);//isr是字符流//将字符流包装成带有缓冲区的字符流BufferedReader br = new BufferedReader(isr);//可以将上面的三句话合成一句BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("BufferedReaderTest.java")));后面的代码和上面的一样,此处省略

接收用户键盘输入
以前的方式:采用Scanner 类;

Scanner s = new Scanner(System.in);//System.in是一个标准的输入流,默认接收键盘的输入//程序执行到此处停下来,等待用户的输入String str =s.next();

注意:该方式默认以空格作为分割,因此不能从键盘接收hello world!只能接收到hello
使用BufferedReader用来接收用户的输入

BufferedReader br = new BufferedReader(InputStreamReader(System.in));//接受输入(每一次接收一行)String str = br.readLine();

BufferedWriter

java.io.Writer;    java.io.BufferedWriter;//创建带有缓冲区的字符输出流BufferedWriter bw = new BufferedWriter(new FileWriter("temp03"));//开始写bw.write("我现在不怎么看小说了,");//写入一个行分隔符bw.newLine();bw.write("时间反而多了!");//刷新bw.flush();//关闭bw.close();

使用BufferedReader和BufferedWriter完成复制

//创建带有缓冲的字符输入流BufferedReader br = new BufferedReader(new FileReader("Copy.java"));//创建带有缓冲区的字符输出流BufferedWriter bw = new BufferedWriter(new FileWriter(F:/Copy.java));//边读边写String temp = null;while((temp=br.readLine())!=null){    bw.write(temp);    bw.readLine();//添加一个换行符,拷贝出来的文件会比源文件大2字节,一个换行符占2字节    }//刷新bw.flush();//关闭br.close();bw.close();

DataOutputStream;数据字节输出流
可以将内存中的”int i=10;”写入到硬盘文件中,写进去的不是字符串,写进去的是二进制数据,带类型

java.io.OutputStream;    java.io.FileterOutputStream;        java.io.DataOutputStream;//创建数据字节输出流DataOutputStream dos = new DataOutputStream(new FileOutputStream("temp04"));//准备数据byte b = 10;short s = 11;int i = 12;long l = 1000L;float f = 3.2f;double d = 3.2;boolean flag = true;char c = 'a';//写dos.writeByte(b);dos.writeShort(s);dos.writeInt(i);dos.writeLong(l);dos.writeFloat(f);dos.writeDouble(d);dos.writeBoolean(flag);dos.writeChar(c);//刷新dos.flush();//关闭dos.close();

注意:使用DataOutputStream写入的数据,只能用DataInputStream读取

DataInputStream

java.io.InputStream;    java.io.FilterInputStream;        java.io.DataInputStream;//创建输入流DataInputStream dis = new DataInputStream(new FileInputStream("temp04"));//读//注意:要使用该流读取数据,必须提前知道该文件中数据的存储格式、顺序且读的顺序必须和写入的顺序相同byte b = dis.readByte();short s = dis.readShort();int i = dis.readInt();long l = dis.readLong();float f = dis.readFloat();double d = dis.readDouble();boolean flag = dis.readBoolean();char c = dis.readChar();//下面接输出语句,不一一写了System.out.print(b);dis.close();

PrintStream;标准的输出流,默认打印到控制台,以字节方式
PrintWriter;以字符方式
PrintStream;

java.io.OutputStream;    java.io.FilterOutputStream;        java.io.PrintStream; //默认是输出到控制台的System.out.println("HelloWorld!");//还可以写成下面这种形式PrintStream ps = System.out;ps.println("HelloWorle!");//可以改变输出方向System.setOut(new PrintStream(new FileOutputStream("log")));//再次输出则打印到log,通常使用这种方式记录日志System.out.println("hiahiahia...");

ObjectOutputStream;序列化JAVA对象到硬盘(Serial)
ObjectInputStream将硬盘中的数据”反序列化”到JVM内存中(DeSerial)
序列化

java.io.OutputStream;    java.io.ObjectOutputStream;//创建java对象User u = new User("张三","男","21");//创建输出流(序列化流)(JVM中的java对象状态保存到硬盘中)ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("temp05"));//写oos.writeObject(u);//刷新oos.flush();//关闭oos.close();

注意:User对象要想序列化,必须实现Serializable接口,而Serializable接口中有没有方法,像这样的接口,我们称为标识接口,标识接口的作用:起到标识作用,JVM如果看到该标识,会对它特殊待遇
反序列化

java.io.InputStream;    java.io.ObjectOnputStream;//创建反序列化流ObjectInputStream ois = new ObjectInputStream(new FileInputStream("temp05"));//反序列化Object o = ois.readObject();//输出到控制台System.out.println(o);//会调用User里重写的toString方法,结果为:[User:姓名:张三,性别:男,年龄:21]//关闭ois.close();

关于序列化版本号和transient关键字
因为User实现了Serializable接口,JVM会特殊待遇:会给该类添加一个属性
static final long serialVersionUID = 124941495L;
每次该类改动之后再次编译,系统都会给该类一个serialVersionUID,如果让系统自动生成,就会出现以前序列化的对象在反序列化的时候会报异常,那是因为系统每次为该类添加属性并赋值是不同的,因此在实际编程中,通常都是我们自己在需要序列化的类中写一个序列化版本号,另外,如果不想让该类中的某属性序列化,则在该属性的前面用关键字transient关键字修饰
java.io.File;
1.File类和流无关,不能通过该类完成文件的读写
2.File是文件和目录路径名的抽象表示形式
File代表的是硬盘上的Directory和file

File f1 = new File("Test01.java");//代表的是文件File f2 = new File(D:/A/B/C);//代表的是目录File f3 = new File(D:/TT);System.out.println(f1.exists());//判断该文件是否存在//如果不存在,创建该目录或文件if(!f3.exists()){f2.mkdir();//创建目录f2.createNewFile();//创建文件}if(!f2.exists()){f2.mkdirs();//创建多重目录}

File中常用的方法

   String getAbsolutePath();获取绝对路径    String getName();获取文件名    String getParent();获取父路径    boolean isDirectory();判断该文件是否是目录    boolean isFile();判断该文件是否是文件    long lastModified();获取文件最后一次修改的时间    long length();获取文件的长度(字节数)    File [] listFiles();//列出子文件并保存在数组里

如果要遍历数组里所有的以.java结尾的子文件,可以用增强for循环加判断条件

File f = new File(D:/workspace);File [] fs = f.listFiles();for(File f:fs){    if(f.getAbsolutePath().endsWith(.java)){            System.out.println(f.getAbsolutePath());        }    }

使用递归,找出某目录下的所有子目录以及子文件

import java.io.*;public class Test{    public static void main(String [] args){        File f = new File("F:/workspace")        //调用方法完成查找        method(f);        }    public static void method(File f){        if(f.isFile()){        return;        }    File [] fs = f.listFiles();    for(File subF:fs){            System.out.println(subF.getAbsolutePath());            method(subF);            }        }}