Java IO

Java中IO是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。

File类


 File类是java.io包中很重要的一个类;


 File类的对象可以表示文件,还可以表示目录,在程序中一个File类对象可以代表一个文件或目录;

一个Flie类的对象可以表示一个具体的文件或目录


 File对象可以对文件或目录的属性进行操作,如:文件名、最后修改日期、文件大小等;


 File对象无法操作文件的具体数据,即不能直接对文件进行读/写操作

 File构造方法

public class FileDemo2 {
    public static void main(String[] args) {
        File file=new File("D:\\浏览器\\Demo.txt");
        File file1=new File("Demo2.txt");
        File file2=new File("D:\\JAVA");
    }
}

 这里便是File的构造方法的三种用法。    

第一行 File file=new File("D:\\浏览器\\Demo.txt");   指定的是相应的文件路径以及文件名。这里的路径指的是绝对路径   即完整的路径。

第二行 File file1=new File("Demo2.txt"); 指在当前目录下创建一个与Demo2.txt文件名相关的文件对象。

第三行File file2=new File("D:\\JAVA"); 指明详细的路径和目录名。

File类常用方法

public static void main(String[] args) {
        File file=new File("D:\\浏览器\\Demo.txt");
        File file1=new File("Demo2.txt");
        File file2=new File("D:\\JAVA");

        System.out.println(file1.getAbsolutePath());//绝对路径  像我们不知道file1的位置的话就可以使用此方法查到绝对路径
        System.out.println(file.getParent());//父级
        System.out.println(file.lastModified());//文件最后修改时间
        System.out.println(file.length());//获取文件内容长度(以字节为单位)
        System.out.println(file.canRead());//判断文件是否可读
        System.out.println(file.canWrite());//判断文件是否可写
        System.out.println(file.exists());//判断文件是否存储
        System.out.println(file.isFile());//判断表示的是否是文件
        System.out.println(file.isDirectory());//判断表示的是否是目录
        System.out.println(file.delete()); //删除文件  删除成功返回ture,反之返回false

        File f=new File("D:\\Demo");
        f.mkdir();  //创建单级目录
        File f1=new File("D:\\Demo1\\Demo2");
        f1.mkdirs(); //创建多级目录

    }

 

public static void main(String[] args) {
        File file=new File("D:\\JAVA");
        String[] s=file.list();
        for(String name: s)
            System.out.println(name);
        
    }

 

list()方法是 获得某个目录中所有的子级目录/文件 返回文件名(String)

我们再使用增强for循环将得到的文件名遍历出来。

File file1=new File("D:\\JAVA");
        File []s1=file1.listFiles();
        for(File f:s1){
            System.out.println(f);
        }

 

listFile()方法是获得某个目录中所有的子级目录/文件 返回文件对象(File)

当然你也可以使用delete()方法区删除文件,不过这可正儿八经的删除的是你的文件,建议留心点。

输入及输出的概念

 输入输出(I/O) 把电脑硬盘上的数据读到程序中,称为输入,即input,进行数据的read 操作从程序往外部设备写数据,称为输出,即output,进行数据的write操作。

输入流与输出流

流即是读写操作的类。

 流按着数据的传输方向分为:
 输入流:往程序中读叫输入流。
 输出流:从程序中往外写叫输出流。

类按照操作不同,单位不同分为:

字节流:每次读取数据时,是以字节为单位,一次读一个字节(可以读取任何文件)

字节输入流 FileInputStream
字节输出流 FileOutputStream

字符流:每次读取数据时,是以字符为单位,一次第一个字符(只适合文本文件)

 字符输入流 FileReader
字符输出流 FileWriter

       InputStream的基本方法:


读取一个字节并以整数的形式返回(0~255),如果返回-1已到输入流的末尾。
int read() throws IOException
读取一系列字节并存储到一个数组buffer, 返回实际读取的字节数,如果读取前已到输入流的末尾返回-1
int read(byte[] buffer) throws IOException
关闭流释放内存资源
void close() throws IOException


       OutputStream的基本方法


向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
将一个字节类型的数组中的从指定位置(off)开始的 len个字节写入到输出流
void write(byte[] b, int off, int len) throws IOException
关闭流释放内存资源
void close() throws IOException

public static void main(String[] args) throws IOException {
        FileInputStream in=new FileInputStream("D:\\game1\\Demo.txt");
        FileOutputStream out=new FileOutputStream("D:\\game1\\Demo2.txt");
        int b=0;
        while ((b=in.read())!=-1){
            out.write(b);

        }
        in.close();
        out.close();
    }

 

 

 这里提几点

1. 要读取的文件必须要存在,而输出的文件会自己创建。

2. 因为当返回为read 返回-1时就代表读取完毕了。所以我们while循环中条件是当读取不为-1时。

int的b值是充当一个承载事物的对象。

3.完事记得close关闭流释放资源。

下面是一个规范的格式写输出输出。因为我们在写代码中会碰到异常,需要try catch语句环绕处理异常。平常演示图个方便所以就直接抛出,规范写法应该如下。

public static void main(String[] args) throws IOException {
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
             in =  new FileInputStream("E:/demo1.txt");
             out = new FileOutputStream("E:/demo2.txt");
             // in.read(); 一次读一个字节,返回字节编码(int), 文件内容读完后返回-1.
                int b = 0;
                while((b = in.read())!=-1){
                    out.write(b);
                    //write(int b); 一次向目标文件写出一个字节
                }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println(e.getMessage());//日志记录
        }finally {
               if(in!=null){
                   in.close();//关闭流通道 释放文件
               }
               if(out!=null){
                   out.close();
               }
        }

    }

 

下面介绍另一种读取方案,因为read读取是一个字节一个字节慢慢读取的,所以我们定义一个数组,使数组被读取装满后再去输出,这样降低了传输次数加大了传输效率。

public static void main(String[] args) throws IOException {
        long l=new Date().getTime();

        FileInputStream in=new FileInputStream("D:\\game1\\Demo.txt");
        FileOutputStream out=new FileOutputStream("D:\\game1\\Demo3.txt");
        int b=0;
        while ((b=in.read())!=-1){
            out.write(b);
        }
        long l2=Calendar.getInstance().getTimeInMillis();
        System.out.println(l2-l);
        in.close();
        out.close();

        System.out.println("----------------------------------------------");

        long l3=new Date().getTime();

        FileInputStream in2=new FileInputStream("D:\\game1\\Demo.txt");
        FileOutputStream out2=new FileOutputStream("D:\\game1\\Demo4.txt");
        byte[] bytes=new byte[100];
        int size=0;
        while ((size=in2.read(bytes))!=-1){
            out2.write(bytes,0,size);
        }
        long l4=Calendar.getInstance().getTimeInMillis();
        System.out.println(l4-l3);
        in2.close();
        out2.close();
    }

分界线上方是普通传输方式,分界线下方是使用数组传输的方式。

我们专门使用了Date类来获取时间差,来计算两种方式的工作效率。

 最后可以看到,使用数组传输效率明显大于普通传输方式。

字符流

字符流的使用方法与字节流大同小异,不过处理原理上不一样。字节流是按照一个字节一个字节读写的。而字符流失按照一个字符一个字符读写的。为什么说字符流适合处理纯文本文件,因为一个文字占有三字节,而一个字母只占有一字节。若使用字节流如果传输过程没有写好,可能会将文本的字节没有写完就结束,这样会使读写出错。

FileReader reader=new FileReader("D:\\game1\\中文.txt");
        FileWriter writer=new FileWriter("D:\\game1\\中文Demo.txt");
        char [] b=new char[10];
        int size=0;
        while ((size=reader.read(b))!=-1){
            writer.write(b,0,size);
        }
        reader.close();
        writer.close();

 

节点流和处理流

根据封装类型不同流又分为:


节点流:
如果流封装的是某种特定的数据源,如文件、字符串、字符串数组等,则称为节点流。亦即上面提到的字节流与字符流。


处理流:
如果流封装的是其它流对象,称为处理流。 处理流提供了缓冲功能,提高读写效率,同时增加了一些新的方法。

缓冲字节输出流 BufferedOutputStream
缓冲字节输入流 BufferedInputStream
缓冲字符输入流 BufferedReader
缓冲字符输出流 BufferedWriter

处理流

  缓冲处理流内置有一个缓冲数组,更有效率的完成读写任务。自己可以定义一个数组大小,在read时,如果自定义的数组不大于底层固定数组时,会把读到的数据缓冲到数组中去,将数组读满之后写出去。write时也并不是每一次都往磁盘中去写,等待内部缓存数组写满时,再向磁盘输出。

FileReader reader=new FileReader("D:\\game1\\中文.txt");
        FileWriter writer=new FileWriter("D:\\game1\\中文Demo22.txt",true);
        BufferedReader bufferedReader=new BufferedReader(reader);
        BufferedWriter bufferedWriter=new BufferedWriter(writer);
        String line="";
        int n=0;
        while ((line=bufferedReader.readLine())!=null){
            bufferedWriter.write(line);
            bufferedWriter.newLine();
        }
        bufferedWriter.flush();
        bufferedReader.close();
        bufferedWriter.close();

 简单来说处理流就是充当了上面我们自己定义的数组的角色。

以上代码还有几点要讲

1.在FileWriter writer=new FileWriter("D:\\game1\\中文Demo22.txt",true);中,文件路径的后面跟了一个ture。这里的作用是写入数据时,保留之前的,向后面追加内容。

2.我们可以看到这串代码是一行一行字符读取的。使用的便是readLine()方法。

3.newLine()就相当于换行

4.最后别忘了flush()刷新缓冲区,以及close()输入输出流。

Print流

Print 打印流:
只做输出没有输入 打印流分为字节打印流和字符打印流
PrintWriter:
字符打印流 print方法可以打印各种类型数据
在javaweb项目中,服务器端向客户端响应数据以打印流的方式响应.

 

public static void main(String[] args) throws FileNotFoundException {
        PrintWriter pw=new PrintWriter("D:\\game1\\Demo.html");
        pw.print("<h1>你好客户端</h1>");
        pw.print("<h1>你好客户端</h1>");
        pw.print("<h1>你好客户端</h1>");
        pw.print("<h1>你好客户端</h1>");
        pw.close();
    }

 

 

对象输入输出流--对象序列化

对象存储在内存中,程序终止运行,内存数据清空,
有时需要保存对象中的数据,需要用流对象,将对象数据输出到文件中,做到对象数据的持久化(长久保存)

因此便有了   ObjectInputStream      ObjectOutputStream     都属于处理流

public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileOutputStream fout= new FileOutputStream("D:/game1/obj.txt");
        ObjectOutputStream out = new ObjectOutputStream(fout);
        Date date = new Date();
        String s = "abc";
        out.writeObject(date);
        out.writeObject(s);
        out.flush();
        out.close();

        //反序列化   会创建对象
        FileInputStream in = new FileInputStream("D:/game1/obj.txt");
        ObjectInputStream oin = new ObjectInputStream(in);
        Date date2 =  (Date)oin.readObject();
        String s2 =   (String)oin.readObject();
        System.out.println(date2);
        System.out.println(s2);
    }

 

 

1. 对象的输出流将指定的对象写入到文件的过程,就是将对象序列化的过程.
2. 对象 的输入流将指定序列化好的文件读出来的过程,就是对象反序列化的过程。
3. 对象的输出流将对象写入到文件中称之为对象的序列化,所以被序列化对象的类必须要实现 Serializable接口。 Serializable接口中没有任何方法。当一个类声明实现Serializable接口后, 表明该类可被序列化。在类中可以生成一个编号
private static final long serialVersionUID = -5974713180104013488L;
4. 随机生成 唯一的 serialVersionUID 用来表明实现序列化类的不同版本间的兼容性。某个类在与之对应的对象已经序列化出去后做了修改,该对象依然可以被正确反序列化.
5. 如果不显示生成序列号,那么将会隐式生产,但是隐式生成后,类一旦发生改变,序列号也会随之改变.

       FileOutputStream fileOutputStream=new FileOutputStream("D:/game1/CarDemo.txt");
        ObjectOutputStream objectOutputStream=new ObjectOutputStream(fileOutputStream);
        Car car=new Car(999,"玛莎拉蒂");
        objectOutputStream.writeObject(car);
        objectOutputStream.flush();
        objectOutputStream.close();

        FileInputStream fileInputStream=new FileInputStream("D:/game1/CarDemo.txt");
        ObjectInputStream objectInputStream=new ObjectInputStream(fileInputStream);
        Car car1=(Car)objectInputStream.readObject();
        System.out.println(car1);
public class Car implements Serializable {
    private static final long serialVersionUID = -9055250986688943401L;
    private int num;
    private String name;

    public Car(int num, String name) {
        this.num = num;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Car{" +
                "num=" + num +
                ", name='" + name + '\'' +
                '}';
    }
}


如果需要将某个类的对象进行序列化,那么此类必须实现Serializable接口。
会为类生成一个版本号,如果不显得定义版本号,会自定默认生成,会有一个问题,每次当类改变了,版本号会重新生成

图中的private static final long serialVersionUID = -9055250986688943401L;正是序列化版本号 显示的定义之后,类信息发生改变不会重新生成。

另外如果某个类属性我们不想存入序列化对象当中,可以使用transient修饰的属性在序列式,不会保存到文件中。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值