Java IO 流基本操作示例——修改中..._java修改文件部分内容-程序员宅基地

技术标签: 文件复制  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

智能推荐

QGC注释消息提示框_qgcpopupdialog-程序员宅基地

文章浏览阅读190次。消息提示框:有时显示时覆盖想要看的界面,可注释!_qgcpopupdialog

【大数据----Ambari】大数据平台的搭建利器_ambri支持的数据库-程序员宅基地

文章浏览阅读273次。https://blog.csdn.net/ningjiebing/article/details/90600652Ambari 是什么Ambari 跟 Hadoop 等开源软件一样,也是 Apache Software Foundation 中的一个项目,并且是顶级项目。目前最新的发布版本是 2.0.1,未来不久将发布 2.1 版本。就 Ambari 的作用来说,就是创建、管理、监视 Hadoop 的集群,但是这里的 Hadoop 是广义,指的是 Hadoop 整个生态圈(例如 Hive,Hbase_ambri支持的数据库

Action向视图传值的6种方式(转)-程序员宅基地

文章浏览阅读74次。在使用ASP.NET MVC进行项目开发时,经常会碰到从Action向视图传值的问题,今天我就把我所知道的方式总结了一下,分成了以下六种:1.使用ViewData进行传值在Action中,有如下代码:ViewData["name"] = "Vibin1";则在视图中可以这样接收:姓名:@ViewData["name"]注意:ViewData是一个简单的字典,它的生命周期和所请求的V...

关于ARC的疑问.求指教啊.-程序员宅基地

文章浏览阅读46次。我是我的项目中使用了ARC,有已个scrollview上面有三个View用来展示内容,每增加已个view就会移除另外一个view,使scrollview上面始终只有三个view.但是我发现一个问题,随着我翻页,内存在不断地增加.后来我写了一段测试代码:UIView *view = nil; while (TRUE) { [view removeFromSupervi

Delphi之MIDAS三层完美解决方案----中间层构建_delphi midas-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏7次。思路:中间层与客户端通过三个关键的接口过程进行交互操作(GetData,SetData,GetspData)GetData:获取数据集。客户端传递数据集名称给中间层,中间层根据请求的数据集名称从数据库的配置文件中获取相关信息,与客户的的条件集合一起给合成SQL语句SetData:提交数据集。客户端传递修改后的数据集Delta与名称给中间层,中间层根据请求的数据集名称从数据库的配置文件中获取相关..._delphi midas

vCenter的安装部署-程序员宅基地

文章浏览阅读3.1k次,点赞3次,收藏6次。vCenter是啥不多说了,看下百度百科https://baike.baidu.com/item/Vcenter/7474684?fr=aladdinvCenter的安装还是要说一下,步骤如下:1、找到vCenter的安装软件。名称VMware-vCenter-Server-Appliance-5.5.0.5100-1312297_OVF10.ova,这里是5.5版本,你可以理解为这个是已

随便推点

GCC基本知识-程序员宅基地

文章浏览阅读110次。掌握下面的对GCC会有一个比较清晰的大致的了解:不经意间,GCC已发展到了4.3的版本,尽管在软件开发社区之外乏人闻问,但因为GCC在几乎所有开源软件和自由软件中都会用到,因此它的编译性能的涨落会直接影响到Linux 、Firefox 乃至于OpenOffice.org和Apache等几千个项目的开发。因此,把GCC摆在开源软件的核心地位是一点也不为过。另一方面,GCC4.3的出现,正在牵引着..._gcc开源协议

JVM-程序员宅基地

文章浏览阅读124次。JVM架构JVM被分为三个主要的子系统:类加载器子系统、运行时数据区和执行引擎。JVM架构图一. 类加载器子系统Java的动态类加载功能是由类加载器子系统处理。当它在运行时(不是编译时)首次引用一个类时,它加载、链接并初始化该类文件。1.1 加载类由此组件加载。启动类加载器 (BootStrap class Loader)、扩展类加载器(Extension cla...

c语言math库正弦余弦函数_输入边及余弦求解代码-程序员宅基地

文章浏览阅读2.6k次,点赞3次,收藏5次。#include<stdio.h>#include<math.h>int main(){ int n; double pi=acos(-1.0); scanf("%d",&n);//度数 printf("%f %f\n",sin(n/180.0*pi),cos(n/180.0*pi));//sin和cos内必须使用弧度制; ..._输入边及余弦求解代码

Android API、版本号、版本名称、NDK对照表_android api 12 s是哪个单词-程序员宅基地

文章浏览阅读1.3w次。API_Level Platform_Version Version_Code NDK_Version 28 Android 9.0 Pie(馅饼) 27 Android 8.1 Oreo(奥利奥) 26 Android 8.0 Oreo(奥利奥) 25 Android 7.1 Noug..._android api 12 s是哪个单词

PHP正则表达式-程序员宅基地

文章浏览阅读40次。正则表达式定义   正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。   列目录时, dir *.txt或ls *.txt中的*.txt就不是一个正则表达式,因为这里*与正则式的*的含义是不同的。   正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组...

IP路由基础、路由器静态路由配置方法、自治系统、缺省路由的配置方法、路由选路规则、缺省路由、备份路由、等价路由、三种查询路由表命令_等价路由和备份路由一样吗?-程序员宅基地

文章浏览阅读4.1k次,点赞23次,收藏26次。路由器特点,网络IP地址规划网络间的特性,基本路由思想,编辑静态路由部分,查询设备整个路由表,查看特定的路由协议时使用,查询目的地址2.2.2.2的路由条目,IP路由表代码写法,IP路由表里的信息,路由表来源,路由表的信息,路由表选路规则,缺点:缺省路由,备份路由,等价路由,做实验的步骤......_等价路由和备份路由一样吗?