Java IO 流基本操作示例——修改中..._swadian2008的博客-程序员资料

技术标签: 文件复制  JavaIO流  输入流和输出流  Java SE  

目录

一、数据流

二、字节流和字符流

三、输入流和输出流

1、使用输入流读取本地文件内容

2、使用输出流把内容写入本地文件

3、文件复制

关闭close和刷新flush

四、缓冲流

1、使用字符缓冲流读写文件内容

2、使用字节缓冲流读写文件内容

五、File文件类

1、常用方法

1)获取功能的方法

2)判断功能的方法

3)创建删除功能的方法

4)目录的遍历

2、递归复制文件夹下文件


一、数据流

数据流:数据流(data stream)是一组有序,有起点和终点的字节的数据序列。包括输入流和输出流。数据流模式中,处理系统无法控制所处理的数据的到达顺序,由于数据量的庞大,数据流中的元素被处理后将被抛弃或存档(archive)。以后再想获取这些数据将会很困难,除非将数据存储在内存中,但由于内存大小通常远远小于数据流数据的数量,因此实际上通常只能在数据第一次到达时获取数据。

缓冲流:为了提高数据的传输效率,通常使用缓冲流(Buffered Stream),即为一个流配有一个缓冲区(buffer),一个缓冲区就是专门用于传输数据的内存块。当向一个缓冲流写入数据时,系统不直接发送到外部设备,而是将数据发送到缓冲区。缓冲区自动记录数据,当缓冲区满时,系统将数据全部发送到相应的设备。

当从一个缓冲流中读取数据时,系统实际是从缓冲区中读取数据。当缓冲区空时,系统就会从相关设备自动读取数据,并读取尽可能多的数据充满缓冲区。

JavaIO流图示:

IO流分类:

按照流向数据流向可以分为输入流输出流

按照处理数据类型的单位不同可以分为字节流字符流

二、字节流和字符流

字节流:InputStreamOutputStream是java中可以按照最小字节单位读取的流,即每次读写一个字节,字节流是直接连接到输入源的流。

字符流:是以字符为单位进行数据处理的IO流。本质其实就是基于字节流读取时,去查找指定的码表

区别:

1.读写单位不同:字节流式以字节(8位2进制)为单位,每次读写一个字节。字符流是以字符为单位,根据码表映射字符,一次可能读多个字节。

2.处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据

结论:只要是纯文本数据优先使用字符流,除此之外都使用字节流。

字符流使用代码演示:

public static void main(String[] args) throws IOException {
        Reader fr = new FileReader("D:\\MyFiles\\poi\\IODemo.txt");
        Writer fw = new FileWriter("D:\\MyFiles\\poi\\IODemo_fw.txt");
        int len;
        // 一次读一个字符数组
        char[] chars = new char[1024];
        while ((len = fr.read(chars)) != -1) {
            fw.write(chars, 0, len);
            fw.flush();
        }
        fw.close();
        fr.close();
    }

三、输入流和输出流

1、使用输入流读取本地文件内容

代码示例:

public static void main(String[] args) throws IOException {
        // 斜杠为转义字符,在Java中需使用双斜杠或者反斜杠来进行表示
        File file = new File("D:\\MyFiles\\poi\\IODemo.txt");
        // 使用文件流——字节流方式来读取文件里边的内容
        InputStream fis = new FileInputStream(file);
        int len;
        // 创建缓冲区数组大小为1024个字节
        byte[] bytes = new byte[1024];
        StringBuilder stringBuilder = new StringBuilder();
        // 读取的字节数会作为整数返回,赋值给len,当流读到文件的末尾时,会返回-1
        while ((len = fis.read(bytes)) != -1) {
            String str = new String(bytes, 0, len);
            stringBuilder.append(str);
        }
        // 关闭输入流
        fis.close();
        System.out.println(stringBuilder.toString());
    }

其中

(len = fis.read(bytes)) != -1

表示从输入流中读取一些字节数并将它们存储到缓冲区数组bytes中。读取的字节数会作为整数返回,当流读到文件的末尾时,会返回-1。其中返回值len为从输入流读取到缓冲区的字节总数

注:

1、读取的第一个字节存储在元素bytes[0]中,下一个字节存储在元素bytes[1]中,以此类推。读取的字节数最多等于bytes数组的长度。设k为实际读取的字节数;这些字节将存储在元素bytes[0]到bytes[k-1]中,而元素bytes[k]到bytes[bytes.length-1]不受影响。

2、StringBuilder是线程不安全的,StringBuffer是线程安全的。

String str = new String(bytes, 0, len);

3、通过使用平台的默认字符集解码指定的字节子数组,构造一个新的String。

2、使用输出流把内容写入本地文件

代码示例:

public static void main(String[] args) throws IOException {
        // 写入文件的地址
        File file = new File("D:\\MyFiles\\poi\\fos.txt");
        // 没有文件会创建文件,有文件会进行内容覆盖
        OutputStream fos = new FileOutputStream(file);
        String str = "this is a demo. / 这是一个演示。";
        // 使用默认编码方式转换成字节码
        byte[] bytes = str.getBytes();
        // 从指定字节数组写入bytes.length字节到这个输出流。
        fos.write(bytes);
        fos.close();
    }

3、文件复制

代码示例:

public static void main(String[] args) throws IOException {
        // 读入文件地址
        InputStream fis = new FileInputStream("D:\\MyFiles\\poi\\a.jpg");
        // 写入文件地址
        OutputStream fos = new FileOutputStream("D:\\MyFiles\\poi\\b.jpg");
        int len;
        byte[] bytes = new byte[1024];
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
            fos.flush();
        }
        // 关闭资源
        fos.close();
        fis.close();
    }

关闭close和刷新flush

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要使用flush() 方法。

flush()这个函数是清空的意思,用于清空缓冲区的数据流,进行流的操作时,数据先被读到内存中,然后再用数据写到文件中。有时候,当数据读完时,立刻调用close()方法关闭读写流,可能会造成数据丢失。因为,读入数据完成时不代表写入数据完成,一部分数据可能会留在缓存区中,并没有写入到文件中去。

四、缓冲流

缓冲流,也叫高效流、是对4个FileXxx 流的“增强流”。

缓冲流的基本原理

1、使用了底层流对象从具体设备上获取数据,并将数据存储到缓冲区的数组内
2、通过缓冲区的read()方法从缓冲区获取具体的字符数据,这样就提高了效率。
3、如果用read方法读取字符数据,并存储到另一个容器中,直到读取到了换行符时,将另一个容器临时存储的数据转成字符串返回,就形成了readLine()功能。

也就是说在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

缓冲书写格式为BufferedXxx,按照数据类型分类:

  • 字节缓冲流BufferedInputStreamBufferedOutputStream
  • 字符缓冲流BufferedReaderBufferedWriter

1、使用字符缓冲流读写文件内容

读取文件内容格式如下:

(1).English:this is a demo ! ! !
(2).中文:这是一个演示!!!

代码示例:

public static void main(String[] args) throws IOException {
        // 读取数据
        BufferedReader br = new BufferedReader(new FileReader("D:\\MyFiles\\poi\\original.txt"));
        // 创建集合,保存数据
        HashMap<String, String> map = new HashMap<String, String>();
        String line = null;
        while ((line = br.readLine()) != null) {
            // 解析文本
            String[] split = line.split("\\.");
            // 保存到集合
            map.put(split[0], split[1]);
        }
        br.close();
        // 写入数据
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\MyFiles\\poi\\copy.txt"));
        for (Map.Entry<String, String> entry : map.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            // 写出拼接文本
            bw.write(key + "." + value);
            // 写出换行
            bw.newLine();
        }
        bw.close();
    }

2、使用字节缓冲流读写文件内容

代码示例:

public static void main(String[] args) throws IOException {
        BufferedInputStream bi = new BufferedInputStream(new FileInputStream("D:\\MyFiles\\poi\\original.txt"));
        BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("D:\\MyFiles\\poi\\original_bo.txt"));
        int len;
        byte[] bytes = new byte[8 * 1024];
        while ((len = bi.read(bytes)) != -1) {
            bo.write(bytes, 0, len);
        }
        bo.close();
        bi.close();
    }

文章参考:史上最骚最全最详细的IO流教程,没有之一! - 宜春 - 博客园

五、File文件类

java.io.File 类是专门对文件进行操作的类,只能对文件本身进行操作,不能对文件内容进行操作
java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作

怎么理解上面两句话?其实很简单!

第一句就是说File跟流无关,File类不能对文件进行读和写也就是输入和输出!
第二句就是说File主要表示类似 D:\\文件目录1D:\\文件目录1\\文件.txt ,前者是文件夹(Directory)后者则是文件(file),而File类就是操作这两者的类。

1、常用方法

1)获取功能的方法

  • public String getAbsolutePath() :返回此File的绝对路径名字符串。
  • public String getPath() :将此File转换为路径名字符串。
  • public String getName() :返回由此File表示的文件或目录的名称。
  • public long length() :返回由此File表示的文件的长度。

绝对路径和相对路径

绝对路径:一个完整的路径,以盘符开头,例如 F://aaa.txt
相对路径:一个简化的路径,不以盘符开头,例如 //aaa.txt//b.txt

2)判断功能的方法

  • public boolean exists() :此File表示的文件或目录是否实际存在。
  • public boolean isDirectory() :此File表示的是否为目录。
  • public boolean isFile() :此File表示的是否为文件。

3)创建删除功能的方法

  • public boolean createNewFile() :文件不存在,创建一个新的空文件并返回true,文件存在,不创建文件并返回 false
  • public boolean delete() :删除由此File表示的文件或目录。
  • public boolean mkdir() :创建由此File表示的目录。
  • public boolean mkdirs() :创建由此File表示的目录,包括任何必需但不存在的父目录。

其中,mkdirs()mkdir()方法类似,但mkdir(),只能创建一级目录,mkdirs()可以创建多级目录比如//a//b//c,所以开发中一般用mkdirs();

4)目录的遍历

  • public String[] list() :返回一个String数组,表示该File目录中的所有子文件或目录。

  • public File[] listFiles() :返回一个File数组,表示该File目录中的所有的子文件或目录。

listFiles在获取指定目录下的文件或者文件夹时必须满足下面两个条件:

  1. 指定的目录必须存在
  2. 指定的必须是目录。否则容易引发返回数组为null,出现NullPointerException异常

2、递归复制文件夹下文件

代码示例:

public class CopyFiles {

    public static void main(String[] args) throws IOException {
        // 将路径srcDir下的文件复制到targetDir下
        String srcDir = "D:\\MyFiles\\poi";
        String targetDir = "D:\\MyFiles\\poi_copy";
        copyDirectiory(srcDir, targetDir);
    }

    /**
     * 复制文件夹的递归方法
     *
     * @param srcDir
     * @param targetDir
     * @throws IOException
     */
    private static void copyDirectiory(String srcDir, String targetDir) throws IOException {
        // 不是文件夹不进行操作
        if (!new File(srcDir).isDirectory()) {
            return;
        }
        // 创建目的文件夹
        new File(targetDir).mkdirs();
        // 列举目录中的文件
        File[] files = new File(srcDir).listFiles();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()) {
                // 更新路径
                String newSrcDir = srcDir + "\\" + files[i].getName();
                String newTargetDir = targetDir + "\\" + files[i].getName();
                // 进行递归
                copyDirectiory(newSrcDir, newTargetDir);
            }
            if (files[i].isFile()) {
                // 更新路径
                String newSrcDir = srcDir + File.separator + files[i].getName();
                String newTargetDir = targetDir + File.separator + files[i].getName();
                copyFile(new File(newSrcDir), new File(newTargetDir));
            }
        }
    }

    /**
     * 文件的读和写
     *
     * @param srcFile
     * @param targetFile
     * @throws IOException
     */
    private static void copyFile(File srcFile, File targetFile) throws IOException {
        BufferedInputStream bi = new BufferedInputStream(new FileInputStream(srcFile));
        BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(targetFile));
        int len;
        byte[] bytes = new byte[8 * 1024];
        while ((len = bi.read(bytes)) != -1) {
            bo.write(bytes, 0, len);
            bo.flush();
        }
        bo.close();
        bi.close();
    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/swadian2008/article/details/101316157

智能推荐

Android9.0无法加载http的url,net::ERR_CLEARTEXT_NOT_PERMITTED_一只小白程序员的博客-程序员资料

从Android 9.0(API级别28)开始,默认情况下禁用明文支持。因此http的url均无法在webview中加载附上我使用的解决办法:&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;&amp;lt;manifest ...&amp;gt; &amp;lt;uses-permission android:name=&quot;android.permission...

使用HTML5+CSS+JS框架有那些好处_js+css的优势_qianduankuangjia的博客-程序员资料

相信很多程序猿朋友都用过框架,不过你是否知道你用的是HTML框架、CSS框架还是JS框架,其实这都不重要,重要的是使用框架的目的是什么?是不是节约了开发项目时间陈本,这事多么伟大的一箱工程,根据几年前的一片文章中写到,使用前端框架的优劣势,从这边文章中整理出一部分分享给大家。

docket常用命令_已运行docket run -d -t强行给容器进程发kill_amdiandds的博客-程序员资料

Docker是什么?开源软件部署方案,轻量级应用容器框架,可以打包发布任何,运行,任何应用。为什么要用Docket?

超强VS Code,8个顶级扩展插件让前端开发如虎添翼!_前端-DK的博客-程序员资料

微软的 VS (Visual Studio) Code 是一个免费的开源代码编辑器,最近越来越受欢迎。它非常轻巧、灵活,同时也提供了很多强大的功能。它支持绝大多数流行的编程语言,包括PHP、JavaScript、C++ 等。VS Code 是跨平台的。它不仅能用于 Windows 平台,同时也提供 Linux 和 Mac 版本。下载地址:https://code.visualstudio.com...

Levenberg-Marquardt(LM算法)_lishuandao的博客-程序员资料

转自: 翠翠的博客什么是最优化,可分为几大类?答:Levenberg-Marquardt算法是最优化算法中的一种。最优化是寻找使得函数值最小的参数向量。它的应用领域非常广泛,如:经济学、管理优化、网络分析、最优设计、机械或电子设计等等。根据求导数的方法,可分为2大类。第一类,若f具有解析函数形式,知道x后求导数速度快。第二类,使用数值差分来求导数。根据 使用模型不同

golang 浮点数保留n位小数_go float计算保留五位小鼠_pudding_zyx的博客-程序员资料

程序员的天敌产品同学,就像UI妹子的甲方爸爸,总会提些你不想写的需求,还不能动手,比如某个数值经过 ÎÒ´òµÄ¾ÍÊÇÂÒÂë ,先保留3位小数,再经过%¥#@%&amp;amp;*%¥#%,再保留2位小数,在经过䅂䌱㈳ꃥꖽ�,取整。。。。。₍₍ ◝(≖ ◡ ≖)◟⁾⁾不送故,有了下面的n位取整 ✧(≖ ◡ ≖✿)func ChangeNumber(f float64, m int) str...

随便推点

【评测】一种组织蛋白快速提取方法_“泽平科技”公众号24h在线答疑的博客-程序员资料

以往认为脂肪组织是单纯能量储存器官,但随着脂肪组织在能量控制、炎症反应和免疫应答方面重要作用的验证,其已被确认也是一个内分泌器官。脂肪组织不仅响应来自传统内分泌系统和中枢神经系统的传入信号,还表达和分泌具有重要功能的细胞因子,包括瘦素(Leptin)、炎性细胞因子、脂联素(adiponectin)、补体成分、纤溶酶原激活物抑制剂-1(PAI-1)、肾素-血管紧张素系统蛋白和抵抗素(Resistin)等。脂肪组织中除了脂肪细胞外,还有干细胞、前脂肪细胞、巨噬细胞、嗜中性粒细胞、淋巴细胞和内皮细胞等。这些不

Spring Boot 动态定时任务---quartz(不需要重启服务)_quartz的任务 修改类用不用重新启动_qianhuan_的博客-程序员资料

一、配置文件quartz.properties#ID设置为自动获取 每一个必须不同 (所有调度器实例中是唯一的)org.quartz.scheduler.instanceId=AUTO#指定调度程序的主线程是否应该是守护线程org.quartz.scheduler.makeSchedulerThreadDaemon=true#ThreadPool实现的类名org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool#Thread

项目包红叉,jar包冲突问题_微笑面对疾风的博客-程序员资料

项目包红叉,jar包冲突问题 先去maven库里,删除低版本jar包,然后返回项目重新更新下载jar包。即可解决。

HtmlUnit初步使用心得_XaverSun的博客-程序员资料

HtmlUnit初步使用心得HtmlUnit是一款开源的java 页面分析工具,读取页面后,可以有效的使用HtmlUnit分析页面上的内容。项目可以模拟浏览器运行,被誉为java浏览器的开源实现。

Android JetPack组件之Lifecycle初探_Silencemuyi的博客-程序员资料

前言话说JetPack已经出现了好久了,并且自己的项目中也使用过相关的东西,但是,却没有系统的学习和使用以下,各个部分中的东西。近来刚好有时间,学习了部分东西,想着光说不练嘴把式,特此记录以下方便自己以后理解和学习。首先写这篇文章之前我们先要搞懂什么是JetPack组件,它里面又包含了什么?JetPack组件是什么?Android Jetpack 组件是库的集合,这些库是为协同工作而构建的,不过也可以单独采用,同时利用 Kotlin 语言功能帮助您提高工作效率。可全部使用,也可混合搭

Sleep(0)的妙用----加深对操作系统的理解_qfc8930858的博客-程序员资料

Thread.Sleep(0) 表示挂起0毫秒,你可能觉得没作用,你要写Thread.Sleep(1000) 就有感觉了。似乎毫无意义。MSDN的说明:指定零 (0) 以指示应挂起此线程以使其他等待线程能够执行。Thread.Sleep(0) 并非是真的要线程挂起0毫秒,意义在于这次调用Thread.Sleep(0)的当前线程确实的被冻结了一下,让其他线程有机会优先执行。Thread.S...

推荐文章

热门文章

相关标签