JavaIO的基础知识

File类

File类是java.io包下代表与平台无关的文件和目录,换句话说,如果希望在程序中操作文件和目录,都可以通过File类来完成。值得指出的是,不管是文件还是目录都是通过file来操作的,file能新建、删除、重命名文件和目录,File不能访问文件内容本身。如果要访问文件内容本身,则需要使用输入输出流。

常用的方法

     @Test
    public void fileTest() throws IOException {
        // 以当前路径来创建一个File对象
        File file = new File(".");
        // 输出文件名 .
        System.out.println(file.getName());
        // 获取相对路径的父路径 null
        System.out.println(file.getParent());
        // 获取绝对路径 C:\workspace\java-test\test-jdk8\.
        System.out.println(file.getAbsoluteFile());
        // 获取上一级路径 C:\workspace\java-test\test-jdk8
        System.out.println(file.getAbsoluteFile().getParent());
        // 在当前路径下创建一个临时文件
        File tempFile = File.createTempFile("aaa", ".txt", file);
        // 当JVM退出时删除该文件按
        tempFile.deleteOnExit();
        // 以系统当前时间作为新文件名来创建新文件
        File newFile = new File(String.valueOf(System.currentTimeMillis()));
        // 检查文件是否存在 newFile是否存在:false
        System.out.println("newFile是否存在:" + newFile.exists());
        // 以指定newFile对象来创建一个文件 true
        System.out.println(newFile.createNewFile());
        //以newFile对象来创建一个目录,因为neeFile已经存在,所以下面方法返回false,即无法创建目录
        System.out.println(newFile.mkdir());
        /*
            使用list()方法列出当前路径下的所有文件和路径
            1600865736147
            aaa8104162131771530421.txt
            HELP.md
            pom.xml
            src
            target
            test-jdk8.iml
            test-stream.iml
         */
        String[] fileList = file.list();
        if(null != fileList)
            Arrays.stream(fileList).forEach(System.out::println);
        /*
            其中File类的list()方法可以接收一个FilenameFilter参数,通过该参数可以只列出符合条件的文件。
            HELP.md
            src
            target
         */
        String[] fileNames = file.list(((dir, name) -> name.endsWith(".md") || new File(name).isDirectory()));
        if(null != fileNames)
            Arrays.stream(fileNames).forEach(System.out::println);
        // 静态方法列出所有的磁盘根路径 C:\
        File[] roots = File.listRoots();
        Arrays.stream(roots).forEach(System.out::println);
    }

IO流

java中常见的几种流

根据流的流向,可以分为输入流和输出流,这个地方划分输入输出是从程序运行所在内存的角度来考虑的。输入流,只能从中读取数据,基类主要是InputStream和Reader;输出流,只能向其写入数据,基类主要是OutStream和Write。

根据流操作的数据单元,可以分为字节流与字符流,字节流的数据单元是8位的字节,字符流操作的数据单元是16位的字符。字节流主要是InputStream和OutStream作为基类,而字符流主要是Reader和Writer作为基类。

字节流与字符流的用法几乎完全一样,就一起测试了。
/**
     * 测试字节输入流
     * @throws IOException
     */
    @Test
    public void fileInputStreamTest() throws IOException {
        // 创建字节输入流
        FileInputStream fileInputStream = new FileInputStream("C:\\Users\\82409\\Desktop\\error.log");
        /*
            创建一个长度为1024的字节数组来读取文件
            这里创建较小长度的自己数组,程序运行时输出中文注释时就可能出现乱码,这是由于文件保存时采用的时GBK编码,每个中文字符占两个字节,如果read()方法读取时
            只读到半个中文字符就会导致乱码
         */
        byte[] buf = new byte[1024];
        // 用于保存实际读取的字节数
        int hasRaed = 0;
        while ((hasRaed = fileInputStream.read(buf)) > 0) {
            System.out.println(new String(buf, 0, hasRaed));
        }
        fileInputStream.close();
    }

    /**
     * 测试字符输入流
     * @throws IOException
     */
    @Test
    public void fileReaderTest() throws IOException {
        // 创建字符输入流
        FileReader fileReader = new FileReader("C:\\Users\\82409\\Desktop\\error.log");


        // 创建一个长度为32的字符数组来读取文件
        char[] buf = new char[32];
        //用于保存实际读取的字符数
        int hasRead = 0;
        while ((hasRead = fileReader.read(buf)) > 0) {
            System.out.println("FileReader输出:" + new String(buf, 0, hasRead));
        }
        fileReader.close();
        // BufferReader有一个readline()方法,可以很方便地一次读取一行内容。很适合读取输入流的文本内容。
        BufferedReader reader = new BufferedReader(fileReader);
        String line = null;
        while ((line = reader.readLine()) != null) {
            System.out.println("BufferReader输出:" + line);
        }
        reader.close();
    }

    /**
     * 测试字节输出流
     */
    @Test
    public void fileOutputStreamTest() {
        try {
            // 创建字节输出输入流
            FileInputStream fileInputStream = new FileInputStream("C:\\Users\\82409\\Desktop\\error.log");
            //创建字节输出流
            FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\82409\\Desktop\\newError.log");
            byte[] buf = new byte[1024];
            int hasRead = 0;
            while ((hasRead = fileInputStream.read(buf)) > 0) {
                fileOutputStream.write(buf, 0, hasRead);
            }
            fileInputStream.close();
            fileOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * 测试字符输出流
     * @throws IOException
     */
    @Test
    public void FileWriteTest() throws IOException {
        FileWriter fileWriter = new FileWriter("C:\\Users\\82409\\Desktop\\newErro.log");
        fileWriter.write("不管风吹浪打 \n");
        fileWriter.write("胜似闲庭信步 \n");
        // 这里不关闭的,数据依旧在缓冲区,输出文件中是没有数据的。没有必要可以去记忆那些流有缓冲功能,只要正常关闭所有的输出流即可保证程序正常。
        fileWriter.close();
    }

根据流的角色来划分,可以分为节点流和处理流。可以从/向一个特定IO设备(比如磁盘、网络)读/写数据的流,成为节点流,节点流也被称为低级流。处理流则用于对一个已存在的流进行链接或封装,通过封装后的流来实现数据读/写功能。处理流也被称为高级流。

测试处理流
    /**
     * 使用处理流只需要在创建处理流时传入一个节点流作为构造器参数
     *
     * @throws IOException
     */
    @Test
    public void printStreamTest() throws IOException {
        // 定义一个节点输出流
        FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\82409\\Desktop\\newErro.log");
        // 使用PrintStream包装该节点输出流
        PrintStream printStream = new PrintStream(fileOutputStream);
        // 使用PrintStream执行输出
        printStream.println("单纯试一下");
        // 直接使用PrintStream输出对象
        printStream.println(new IOStreamTest());
        fileOutputStream.close();
        printStream.close();
    }

推回输入流:PushbackInputStream和pushBackReader

这两个推回输入流都带有一个推回缓冲区,当程序调用这两个推回输入流的unread()方法时,系统将会把指定数组的内容推回到该缓冲区里,而推回输入流每次调用read()方法时,系统将会把指定数组的内容推回到该缓冲区里,而推回输入流每次调用read()方法总是先从推回缓冲区读取,只有完全读取了推回缓冲区的内容后,但还没有装满read()所需的数组时才会从与那输入流中读取。
    /**
     * 测试推回输入流
     * @throws IOException
     */
    @Test
    public void pushBackTest() throws IOException{
        // 创建一个PushbackReader对象,指定退回缓冲区的长度为64
        PushbackReader pushbackReader = new PushbackReader(new FileReader("C:\\Users\\82409\\Desktop\\newErro.log"),64);
        char[] buf = new char[32];
        // 用来保存上一次读取的字符串内容
        String lastContent = "";
        int hasRead = 0;
        while ((hasRead = pushbackReader.read(buf)) > 0){
            String content = new String(buf,0,hasRead);
            System.out.println(content);
            pushbackReader.unread((lastContent + content).toCharArray());
            System.out.println(new String(buf,0,hasRead));
        }
        pushbackReader.close();
    }

重定向标准输入/输出流

     /**
     * 测试重定向标准输出,将sout重定向到文件输出
     */
    @Test
    public void RedirectOutTest() throws IOException{
        // 创建PrintStream输出流
        PrintStream printStream = new PrintStream(new FileOutputStream("C:\\Users\\82409\\Desktop\\newErro.log"));
        // 将标准输出重定向到printStream输出流
        System.setOut(printStream);
        System.out.println("我就试一下");
        printStream.close();
    }

    /**
     * 测试重定向标注输入
     */
    @Test
    public void RedirectInTest() throws IOException{
        FileInputStream fileInputStream = new FileInputStream("C:\\Users\\82409\\Desktop\\newErro.log");
        System.setIn(fileInputStream);
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            System.out.println(scanner.next());
        }
        fileInputStream.close();
    }

通过runtime的exec()从其他进程读取输出/写入

    @Test
    public void ReadFromProcessTest()throws IOException{
        // 运行javac命令,返回运行该命令的子进程
        Process p = Runtime.getRuntime().exec("javac");
        /*
            以p进程的错误流创建BufferedReader对象,这个错误流对本程序是输入流,对p进程则是输出流
         */
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        String buff = null;
        // 采取循环方式来读取p进程的错误输出
        while ((buff = bufferedReader.readLine()) != null){
            System.out.println(buff);
        }
    }

    /*
        在java程序中启动java虚拟机运行另一个java程序,并向另一个java程序中写入数据。
        使用Runtime的exec执行java ReadStandard命令,该命令将运行ReadStandard类,并返回运行该程序的子进程;程序第二行获取process的输出流,程序将该输出流向process
     */
    @Test
    public void WriteToProcessTest() throws IOException{
        // 运行java ReadStandard命令,并返回运行该命令的子进程
        Process process = Runtime.getRuntime().exec("java ReadStandard");
        // 以process进程的输出流创建PrintStream对象,这个输出流对本程序来说是输出流,对process进程来说是输入流
        PrintStream printStream = new PrintStream(process.getOutputStream());
        printStream.println("我还是要试一下");
        printStream.close();
    }

RandomAccessFile

它可以读取文件内容,也可以向文件输出数据。与普通输入/输出流不同的是,它支持任意访问,程序可以跳转到文件的任意地方来读写数据。如果程序需要向已存在的文件后追加内容,那么应该使用RandomAccessFile,局限是,他只能读写文件,不能读写其他IO节点。RandomAccessFile对象也包含了一个记录指针,用来表示当前读写出的位置,当程序新创建一个RandomAccessFile对象时,该对象的文件记录指针位于文件头(0),当读/写n个字节后,指针向后移动n个字节,RandomAccessFile也可以自由移动指针。

    @Test
    public void RandomAccessFileTest() throws IOException {
        RandomAccessFile randomAccessFile = new RandomAccessFile("C:\\Users\\82409\\Desktop\\newErro.log", "r");
        // 获取randomAccessFile指针位置
        System.out.println("指针位置" + randomAccessFile.getFilePointer());
        randomAccessFile.seek(3);
        byte[] buf = new byte[1024];
        int hasRead = 0;
        while ((hasRead = randomAccessFile.read(buf)) > 0){
            System.out.println(new String(buf,0,hasRead));
        }
        randomAccessFile.close();
    }
    @Test
    public void AppendContentTest() throws IOException{
        RandomAccessFile randomAccessFile = new RandomAccessFile("C:\\Users\\82409\\Desktop\\newErro.log", "rw");
        // 将记录指针移动到文件最后
        randomAccessFile.seek(randomAccessFile.length());
        randomAccessFile.write("新填内容有了吗".getBytes());
        randomAccessFile.close();
    }

    /**
     * 向指定文件、指定位置插入内容
     */
    public void insertContentTest(String fileName,long pos,String content) throws IOException{
        // 新建临时文件
        File temp = File.createTempFile("temp",null);
        RandomAccessFile randomAccessFile = new RandomAccessFile(fileName,"rw");
        FileOutputStream fileOutputStream = new FileOutputStream(temp);
        FileInputStream fileInputStream = new FileInputStream(temp);
        randomAccessFile.seek(pos);
       // 将插入点后的内容加入临时文件保存
        byte[] buf = new byte[1024];
        int hasRead = 0;
        while ((hasRead = randomAccessFile.read(buf)) > 0){
            fileOutputStream.write(buf,0,hasRead);
        }
        // 插入内容
        randomAccessFile.seek(pos);
        randomAccessFile.write(content.getBytes());
        while ((hasRead = fileInputStream.read(buf)) > 0){
            randomAccessFile.write(buf,0,hasRead);
        }
        randomAccessFile.close();
        fileInputStream.close();
        fileOutputStream.close();
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,525评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,203评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,862评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,728评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,743评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,590评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,330评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,244评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,693评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,885评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,001评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,723评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,343评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,919评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,042评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,191评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,955评论 2 355