Java——I/O

来源:互联网 发布:晋中市教育网络平台 编辑:程序博客网 时间:2024/05/16 14:12

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