Java——I/O

1.流的分类

按照方向分类
输入流:从外部设备流向程序的流成为
输出流:程序流向外部设备的流
按照数据单元分类
字节流:以字节为单位,可以读写任意资源 InputStream,OutputStream
字符流:方便处理以unicode形式存储的信息,读写操作是基于两字节的unicode码元。Reader,Writer
按照功能分
节点流
FileInputStream 文件流
ByteArrayInputStream 字节数组流
PipedInputStream 管道流

处理流
InputStreamReader 桥梁流
BufferedReader 缓冲流
DataInputStream 数据流
ObjectInputStream 对象流
SequenceInputStream 合并流
2java中的流类型
这里写图片描述

操作文件

1.File类
1.构造file对象

 /**
     * File 文件/文件夹的操作
     * 构造File  四种方式
     *
     */

    static void file() throws URISyntaxException {

        File f = new File("D:\\");//传入路径

        File f2 = new File(f, "test");//以f为父级路径构建,相当于D:\\test

        File f3 = new File("D:\\","test");//与f2类似,只是将路径换成String型

        URI uri = new URI("http://docs.oracle.com/javase/9/docs/api/java/io/File.html");
        File f4 = new File(uri);//通过uri构建,通常用于网络操作
    }

常用的方法

创建方法

(1)boolean createNewFile()  //用来创建标准文件的方法
使用File file = new File(path)只是指定了文件创建的路径,但是文件还没有生成,另外如果路径不存在,那么文件将不会创建成功
(2)boolean mkdir()  //创建目录:根据File对象的名字(路径)创建一个目录(文件夹),如果是相对目录,则新建的目录在当前目录下
(3)boolean mkdirs()  //创建多级目录:如果File对象名字有多级目录,则可以调用该方法一次性创建多级目录
mkdirs()可以建立多级文件夹(目录), mkdir()只能创建一层目录
如:
Filefile = new File("c:/aa");
file.mkdir(); //这样可以在c:/下创建aa目录
假如有多层目录,则不能用mkdir创建,如:
Filefile = new File("c:/aa/bb");
file.mkdir() //这样创建不了.
这样不会建立任何目录, 因为找不到/tmp/one/two目录, 结果返回false
应该改为:mkdirs()

删除方法

(1)boolean delete()
(2)boolean deleteOnExit()  //文件使用完成后删除

判断方法

(1)boolean canExecute()  //判断文件是否可执行
(2)boolean canRead()  //判断文件是否可读
(3)boolean canWrite()  //判断文件是否可写
(4)boolean exists()  //判断文件是否存在
(5)boolean isDirectory() //判断File对象指向的文件是否为目录,返回一个boolean类型的值,true或者false
(6)boolean isFile() //判断File对象指向的文件是否是标准文件,返回一个boolean类型的值,true或者false
(7)boolean isHidden()
(8)boolean isAbsolute()  //判断是否是绝对路径 文件不存在也能判断

获取方法


(1)StringgetName()  //获取文件的名字(不带文件的路径),返回的是String类型的值
(2)String getPath()
(3)String getAbsolutePath()
(4)String getParent()  //如果没有父目录返回null
(5)long lastModified()  //获取最后一次修改的时间
(6)long length()  //得到File对象指向文件的长度,以字节计算,返回一个长整形的值(long)
   注意:在系统中,文件夹(目录)的大小为零,也就是不占用空间,使用length()时返回的是0
(7)boolean renameTo(File f)  //重新命名此抽象名称指定的文件
f-- 新抽象路径名的抽象路径名,如果重命名成功此方法返回true,否则返回false
(8)File[] listRoots()  //返回抽象路径名数组,表示在目录中此抽象路径名表示,满足指定过滤器的文件和目录。
(9)String[] list() 
(10)String[] list(FilenameFilter filter)

示例

  /**
     * 需求1:遍历D:\\test下所有文件包括子文件夹
     * 方法1----使用递归
     *   如果是文件夹就递归调用
     */
    static void traverseFolder1(String path) {
        File file = new File(path);
        if (file.exists()) {//判断file是否存在
            File[] files = file.listFiles();//获取file下文件和文件夹,存储到file数组中
            if (files.length == 0) {
                System.out.println("文件夹是空的!");
                return;
            } else {
                for (File f : files) {   //遍历file数组
                    if (f.isDirectory()) { //判断是否为文件夹
                        System.out.println("文件夹:" + f.getAbsolutePath());//获取file的绝对路径
                        traverseFolder1(f.getAbsolutePath());
                    } else {
                        System.out.println("文件:" + f.getAbsolutePath());
                    }
                }
            }
        } else {
            System.out.println("文件不存在!");
        }
    }

    /**
     * 方法二----不使用递归
     * 定义一个linkendlist,保存遍历结果是文件夹的file,到空为止
     */
    static void traverseFolder2(String path) {
        int fileNum = 0, folderNum = 0;
        File file = new File(path);
        if (file.exists()) {
            LinkedList<File> list = new LinkedList<File>();
            File[] files = file.listFiles();
            for (File file2 : files) {
                if (file2.isDirectory()) {
                    System.out.println("文件夹 :" + file2.getAbsolutePath());
                    list.add(file2);
                    fileNum++;
                } else {
                    System.out.println("文件:" + file2.getAbsolutePath());
                    folderNum++;
                }
            }
            File temp_file;
            while (!list.isEmpty()) {
                temp_file = list.removeFirst();
                files = temp_file.listFiles();
                for (File file2 : files) {
                    if (file2.isDirectory()) {
                        System.out.println("文件夹:" + file2.getAbsolutePath());
                        list.add(file2);
                        fileNum++;
                    } else {
                        System.out.println("文件:" + file2.getAbsolutePath());
                        folderNum++;
                    }
                }
            }
        } else {
            System.out.println("文件不存在!");
        }
        System.out.println("文件夹共有:" + folderNum + ",文件共有:" + fileNum);
    }

2.文件的简单读写
流是一种资源,我们操作完之后需要自行关闭

public static void main(String[] args) {
        try {
            //  read("D:\\a.txt");
            write("D:\\b.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读文件--从文件读到程序
     * 1.构造输入流
     * 2.定义暂存数组
     * 3.读取
     * 读取文本类的可用FileReader,二进制文件可用FileInputStream
     */
    static void read(String src) throws IOException {

        //方法1----------------

        FileReader fr = new FileReader(src);
        char[] buf = new char[1024];
        int c;//用来判断是否可读
        String s = "";
        while ((c = fr.read(buf)) != -1) {
            //做一些处理如复制操作,这里只是打印
            s = s + new String(buf);
        }
        fr.close();
        System.out.println("通过字符流:" + s);

        //方法2----------------------

        FileInputStream fis = new FileInputStream(src);
        byte[] b = new byte[1024];
        int len;
        StringBuilder sb = new StringBuilder();
        while ((len = fis.read(b)) != -1) {
            sb.append(new String(b, 0, len));
        }
        fis.close();
        System.out.println("通过字节流:" + sb);
    }


    /**
     * 写文件--从程序写到文件
     * 构造输出流即可
     */
    static void write(String tar) throws IOException {
        String str = "哈哈哈";

        //方法1--------通过字节写出
        FileOutputStream fos = new FileOutputStream(tar);
        fos.write(str.getBytes());//还可以自己指定编码Charset.forName("utf-8")
        fos.close();

        //方法2--------通过字符写出,ture表示在原有内容上添加
        FileWriter fw = new FileWriter(tar, true);
        fw.write(str);
        fw.close();
    }

3.包装流
包装流是为了让某种流的功能更强大,可分成两类
1. 主要以过滤器流为主
如BufferedInputStream,BufferedOuputStream
DataInputStream,DataOutputStream
CheckedOutputStream
CipherOutputStream
DataOutputStream
DeflaterOutputStream
DigestOutputStream
PrintStream

2 对象流、管道流、扫描器等其他流

//流的包装
       FileOutputStream fos=new FileOutputStream("D:\\test.txt");
        BufferedOutputStream bos=new BufferedOutputStream(fos);
        DataOutputStream dos=new DataOutputStream(bos);

4.RandomAccessFile 随机访问文件
创建该类对象时传入模型(mode r表示只读模式,rw表示读写模式,rws表示每次更新都对数据和元数据的写操作进行同步的读/写模式,rwd每次更新时只对数据写操作进行同步的读/写模式)
该类的几个方法
seek(long pos) ———-将文件指针设置到距文件开头的pos字节处,参数是0-文件的字节长度
getFilePointer ———-返回文件指针位置
length()———————-返回文件长度
做个恰当的比喻,文件转换成流后,就像我们很多人排成了一队然后报数,正常情况依次进行。有了seek方法后,就可以指定从谁开始,到谁结束。
这样就可以实现文件的断点续传,暂停时只需要将位置保留下来,再次读取时从该位置开始即可。


    public static void main(String[] args) {
        try {
            random("D:\\a.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * RandomAccessFile 随机访问文件
     *
     */
    static void random(String src) throws IOException {
        RandomAccessFile raf=new RandomAccessFile( src, "rw");
        long l=raf.length();//文件长度
        //读操作------
        raf.seek(3);//从第三个字节开始读
        byte[] b = new byte[1024];
        int len;
        StringBuilder sb = new StringBuilder();
        while((len=raf.read(b))!=-1){
            sb.append(new String(b, 0, len));
            System.out.println("当前指针位置:"+raf.getFilePointer());
        }
        System.out.println(sb.toString());

        //写操作-------
        String str= "123来";
        raf.seek(0);//将内容写在最前面
        raf.write(str.getBytes(Charset.forName("utf-8")));//可以指定编码

        raf.close();

    }

5.zip的操作

 /**
     * ZIP的操作----解压缩
     */
    static void  unZip(String srcpath, String tarsrc) throws IOException {
           byte[] buffer = new byte[1024];

            //create output directory is not exists
            File folder = new File(tarsrc);
            if (!folder.exists()) {
                folder.mkdir();
            }

            //get the zip file content
            ZipInputStream zis =
                    new ZipInputStream(new FileInputStream(srcpath));
            //get the zipped file list entry
            ZipEntry ze = zis.getNextEntry();

            while (ze != null) {
                String fileName = ze.getName();
                File newFile = new File(tarsrc + File.separator + fileName);
                System.out.println("file unzip : " + newFile.getAbsoluteFile());
                //create all non exists folders
                //else you will hit FileNotFoundException for compressed folder
                new File(newFile.getParent()).mkdirs();
                FileOutputStream fos = new FileOutputStream(newFile);
                int len;
                while ((len = zis.read(buffer)) > 0) {
                    fos.write(buffer, 0, len);
                }

                fos.close();
                ze = zis.getNextEntry();
            }
            zis.closeEntry();
            zis.close();
            System.out.println("Done");
    }


    /**
     * ZIP的操作----压缩
     */
    static void zipped(String srcpath, String tarsrc) throws IOException {
            File file = new File(srcpath);// 要被压缩的文件夹
            File zipFile = new File(tarsrc);//压缩后的位置
            InputStream input = null;
            ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
            if(file.isDirectory()){
                File[] files = file.listFiles();
                for(int i = 0; i < files.length; ++i){
                    input = new FileInputStream(files[i]);
                    zipOut.putNextEntry(new ZipEntry(file.getName() + File.separator + files[i].getName()));
                    int temp = 0;
                    while((temp = input.read()) != -1){
                        zipOut.write(temp);
                    }
                    input.close();
                }
            }
            zipOut.close();
        }

6.对象的序列化和反序列化
序列化是以特殊的文件格式存储对象数据,它包含所有对象的类型和数据域,每个对象都赋予一个序列号;当相同对象重复出现将被存储为对这个对象序列号的引用。
例如字符串对象存为:
74 两字节表示的字符串长度 所有字符
hello ————74 00 05 hello


    public static void main(String[] args) {

        Tests t = new Tests();

        //测试序列化
//        Book bk = new Book();
//        bk.setId(3);
//        bk.setName("8");
//        try {
//            t.writeobj("D:\\c.txt", bk);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

          //测试反序列化
        try {
            Book bk1 = (Book) t.readobj("D:\\c.txt", Class.forName("com.xxx.Book"));//或者Book.class
            System.out.println(bk1.getName());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }


    /**
     * 对象流与序列化
     * 可以将一个对象写入流中,然后读回
     * tarpath 保存的路径如 D:\b.txt
     * obj 需要序列化的对象引用 该类需实现Serializable接口
     */
    <T> void writeobj(String tarpath, T t) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(tarpath));
        oos.writeObject(t);
        oos.close();
    }

    /**
     * 反序列化
     * 将文件转换成对象
     * srcpath 序列化文件的路径
     * t 反序列化后的类型
     * 改方法是一个泛型方法
     */
    <T> T readobj(String srcpath, T t) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(srcpath));
        t = (T) ois.readObject();
        ois.close();
        return t;
    }

Book类

import java.io.Serializable;

public class Book implements Serializable{
    private int id;
    private String name;
    //省略get,set...
    }

本文示例源码:http://download.csdn.net/download/qq_29423883/10001011

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值