首页 > 其他分享 >IO流

IO流

时间:2023-02-21 21:13:13浏览次数:81  
标签:file String IO File new txt public

File与IO流

Author: Msuenb

Date: 2023-02-21


File类

  • java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关
  • File 能新建、删除、重命名文件和目录,但不能访问文件内容。 访问文件内容,需要使用输入/输出流
  • 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象;但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录
  • File对象可以作为参数传递给流的构造器

File常用构造方法:

序号 方法 描述
1 public File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
2 public File(String parent, String child) 父路径名字符串和子路径名字符串创建新的 File实例。
3 public File(File parent, String child) 父抽象路径名和子路径名字符串创建新的 File实例。
File file1 = new File("D:\\aaa.txt");

FIle file2 = new File("D:\\ddd\bbb.txt");

File parentDir = new File("D:\\ddd");
File file3 = new File(parentDir, "ccc.txt");

File常用方法:

序号 方法 描述
1 public String getAbsolutePath() 获取绝对路径
2 public String getName() 获取名称
3 public String getParent() 获取上层文件目录路径。若无,返回null
4 public long length() 获取文件长度
5 public boolean isDirectory() 判断是否是文件目录
6 public boolean isFile() 判断是否是文件
7 public boolean exists() 判断是否存在
8 public boolean createNewFile() 创建文件
9 public boolean mkdirs() 创建文件目录。如果上层文件目录不存在,一并创建
10 public boolean delete() 删除文件或者文件夹
@Test
public void test01() throws IOException {
    File dir1 = new File("E:\\iotest\\dir1");	// \ 为转义
    if (!dir1.exists()) // 如果 E:\iotest\dir1 不存在 就创建为目录
        dir1.mkdir();

    // 创建dir2目录 以dir1为父目录
    File dir2 = new File(dir1, "dir2");
    if (!dir2.exists()) dir2.mkdirs();

    // 在dir2目录下创建文件 a.txt
    File file = new File(dir2, "a.txt");
    if (!file.exists()) file.createNewFile();
}
@Test
public void test02() {
    File file = new File("E:\\iotest\\dir1\\dir2\\a.txt");
    File absoluteFile = file.getAbsoluteFile(); // 获取绝对路径
    String name = file.getName();
    String parent = file.getParent();
    boolean isDirectory = file.isDirectory();
    boolean isFile = file.isFile();

    if (file.exists()) file.delete();  // 删除文件
}

IO流分类

根据数据的流向分为:输入流和输出流。

  • 输入流:把数据从其他设备上读取到内存中的流。以InputStream,Reader结尾
  • 输出流 :把数据从内存 中写出到其他设备上的流。以OutputStream、Writer结尾

根据数据的类型分为:字节流和字符流。

  • 字节流 :以字节为单位,读写数据的流。以Stream结尾
  • 字符流 :以字符为单位,读写数据的流。以Reader和Writer结尾

根据IO流的角色不同分为:节点流和处理流。

  • 节点流:直接从数据源或目的地读写数据。常用的节点流:

    • 文件IO流: FileInputStream、FileOutputStream、FileReader、FileWriter 。

    • 字符串IO流: StringReader、StringWriter。

    • 数 组IO流: ByteArrayInputStream、ByteArrayOutputStream、CharArrayReader、CharArrayWriter。

  • 处理流:是对一个已存在的流进行连接和封装,通过所封装的流的功能调用实现数据读写。 常用处理流:

    • 缓冲流:BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter。增加缓冲功能,避免频繁读写硬盘。

    • 转换流:InputStreamReader、OutputStreamReader。实现字节流和字符流之间的转换。

    • 数据流:DataInputStream、DataOutputStream。提供读写Java基础数据类型功能

    • 对象流:ObjectInputStream、ObjectOutputStream。提供直接读写Java对象功能

    • 打印流:PrintStream、PrintWriter。提供各种print、println方法输出各种类型的数据

    • 管道IO流:PipedInputStream、PipedOutputStream、PipedReader、PipedWriter。负责两个线程之间的数据交互

    装饰者设计模式:

    IO流的设计使用了装饰模式(Decorator Pattern)也称为包装模式(Wrapper Pattern)。装饰模式是使用一种对客户端透明的方式来动态地扩展对象的功能,它是通过继承扩展功能的替代方案之一。

输入流 输出流
字节流 InputStream OutputStream
字符流 Reader Writer

文件流

  • FIleInputStream和FileOutputStream是字节输入流和字节输出流。
  • FileReader和FileWriter是字符输入流和字符输出流。

FIleInputStream和FileOutputStream

FileOutputStream 用于写出非文本数据之类的原始字节流;FileOutputStream 从文件系统中的某个文件中获得输出字节。

读入字节数据:

@Test
public void input() {
    File file = new File("E:\\iotest\\dir\\test.txt");
    // 1 建立一个字节流对象,将已存在的一个文件加载进流
    FileInputStream fis = null;

    try {
        fis = new FileInputStream(file);
        int len;
        // 2 创建一个临时存放数据的数组
        byte[] buf = new byte[1024];
        // 3 调用字节流对象的读取方法将流中的数据读入到数组
        while ((len = fis.read(buf)) != -1) {
            System.out.println(new String(buf, 0, len));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (fis != null) fis.close();    // 4 关闭资源
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

写出字节数据:

@Test
public void output() {
    File file = new File("E:\\iotest\\dir\\test.txt");
    FileOutputStream fos = null;

    try {
        fos = new FileOutputStream(file, true); // 追加写
        // fos = new FileOutputStream(file);   // 覆盖写
        String str = "hello, world!\r\n";
        fos.write(str.getBytes());	// 写入数据
    } catch (IOException e) {
        throw new RuntimeException(e);
    } finally {
        try {
            if (fos != null) fos.close();	// 关闭资源
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

FileReader和FileWriter

FileReader用于写出非文本数据之类的原始字符流;FileWriter从文件系统中的某个文件中获得输出字符。

读入字符数据:

@Test
public void reader() throws IOException {
    File file = new File("E:\\iotest\\dir\\test.txt");
    FileReader fr = new FileReader(file);

    int len;
    char[] cbuf = new char[1024];
    while ((len = fr.read(cbuf)) != -1) {
        System.out.println(new String(cbuf, 0, len));
    }

    fr.close();
}

写出字符数据:

@Test
public void writer() throws IOException {
    File file = new File("E:\\iotest\\dir\\test.txt");
    FileWriter fw = new FileWriter(file, true);

    String str = "hello, java!";
    fw.write(str);
    fw.flush(); // 刷新缓冲区 fw还可以用

    fw.close(); // 刷新缓冲区 并关闭资源
}

FileWriter与FileOutputStream不同。因为内置缓冲区的原因,需要flush 或 close才能写出字符到文件中

缓冲流

缓冲流,也叫高效流,按照数据类型分类:

  • 字节缓冲流:BufferedInputStream,BufferedOutputStream
  • 字符缓冲流:BufferedReader,BufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组(默认8K字节),通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

使用缓冲流复制文件:

public class BufferStreamTest {
    public static void main(String[] args) {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            bis = new BufferedInputStream(new FileInputStream("E:\\iotest\\dir\\test.txt"));
            bos = new BufferedOutputStream(new FileOutputStream("E:\\iotest\\dest.txt"));
            byte[] buf = new byte[1024];
            int len;
            while ((len = bis.read(buf)) != -1) {
                bos.write(buf, 0, len);
            }
            bos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bis != null) bis.close();
                if (bos != null) bos.close();	// 会自动关闭它包装的底层节点流
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

转换流

转换流提供了在字节流和字符流之间的转换

Java API提供了两个转换流:

  • InputStreamReader:将InputStream转换为Reader,需要和InputStream“套接”。
  • OutputStreamWriter:将Writer转换为OutputStream,需要和OutputStream“套接”

字节流中的数据都是字符时,转成字符流操作更高效。很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。

public static void main(String[] args) throws IOException {
    FileInputStream fis = new FileInputStream("E:\\iotest\\dir\\test.txt");
    FileOutputStream fos = new FileOutputStream("E:\\iotest\\dest2.txt");

    InputStreamReader isr = new InputStreamReader(fis, "GBK");
    OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");

    BufferedReader br = new BufferedReader(isr);
    BufferedWriter bw = new BufferedWriter(osw);
    String str = null;
    while ((str = br.readLine()) != null) {
        bw.write(str);
        bw.newLine();
        bw.flush();
    }
    bw.close();
    br.close();
}

对象流

ObjectInputStream 和 OjbectOutputSteam 用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

  • 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制
  • 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制

ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量

某个类的对象需要序列化输出时,该类必须实现java.io.Serializable 接口。如果对象的某个属性也是引用数据类型,那么如果该属性也要序列化的话,也要实现Serializable接口

class User implements Serializable {
    private String username;
    private String password;
    //  该版本号的目的在于验证序列化的对象和对应类是否版本匹配
    private static final long serialVersionUID = -2991413533082785204L;

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}
@Test
public void serializable() throws IOException {
    User u = new User("zhangsan", "6934y8234");
    FileOutputStream fos = new FileOutputStream("E:\\iotest\\user.dat");
    ObjectOutputStream oos = new ObjectOutputStream(fos);

    oos.writeObject(u);
    oos.close();
}

@Test
public void deserializable() throws IOException, ClassNotFoundException {
    FileInputStream fis = new FileInputStream("E:\\iotest\\user.dat");
    ObjectInputStream ois = new ObjectInputStream(fis);
    Object o = ois.readObject();
    System.out.println(o);

    ois.close();
}

输入输出流和打印流

System.out对象是PrintStream类型的。它也是IO流对象。

PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。它还提供其他两项功能。与其他输出流不同,PrintStream永远不会抛出 IOException;另外,PrintStream可以设置自动刷新。

import java.io.FileNotFoundException;
import java.io.PrintStream;

public class TestPrintStream {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = new PrintStream("io.txt");
        ps.println("hello");
        ps.println(1);
        ps.println(1.5);
        ps.close();
    }
}

实现键盘输入都是通过Scanner类的对象来完成的,Scanner类不只是键盘输入。

import org.junit.Test;
import java.io.*;
import java.util.Scanner;

public class TestScanner {
    @Test
    public void test01() throws IOException {
        Scanner input = new Scanner(System.in);
        PrintStream ps = new PrintStream("1.txt");
        while(true){
            System.out.print("请输入一个单词:");
            String str = input.nextLine();
            if("stop".equals(str)){
                break;
            }
            ps.println(str);
        }
        input.close();
        ps.close();
    }
    
    @Test
    public void test2() throws IOException {
        Scanner input = new Scanner(new FileInputStream("1.txt"));
        while(input.hasNextLine()){
            String str = input.nextLine();
            System.out.println(str);
        }
        input.close();
    }
}

数据流

为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流。

数据流有两个类:DataInputStream 和 DataOutputStream,分别“套接”在 InputStream 和 OutputStream 子类的流上

@Test
public void output() throws IOException {
    DataOutputStream dos = new DataOutputStream(new FileOutputStream("E:\\iotest\\dir\\data.txt"));
    dos.writeUTF("写入UTF字符串");	// 
    dos.writeBoolean(true);
    dos.writeInt(123455);
    System.out.println("写入文件成功");

    dos.close();
}
public void input() throws IOException {
    DataInputStream dis = new DataInputStream(new FileInputStream("E:\\iotest\\dir\\data.txt"));
    String info = dis.readUTF();
    boolean flag = dis.readBoolean();
    int num = dis.readInt();
    System.out.println(info);
    System.out.println(flag);
    System.out.println(num);

    dis.close();
}

try...resource

语法格式:

try(需要关闭的资源对象的声明){
    业务逻辑代码
}catch(异常类型 e){
    处理异常代码
}catch(异常类型 e){
    处理异常代码
}
....

它没有finally,也不需要程序员去关闭资源对象,无论是否发生异常,都会关闭资源对象。

需要指出的是,为了保证try语句可以正常关闭资源,这些资源实现类必须实现AutoCloseable或Closeable接口,实现这两个接口就必须实现close方法。Closeable是AutoCloseable的子接口。Java7几乎把所有的“资源类”(包括文件IO的各种类、JDBC编程的Connection、Statement等接口…)进行了改写,改写后资源类都是实现了AutoCloseable或Closeable接口,并实现了close方法。

写到try()中的资源类的变量默认是final声明的,不能修改。

示例代码:

@Test
public void test03() {
    //从d:/1.txt(GBK)文件中,读取内容,写到项目根目录下1.txt(UTF-8)文件中
    try(
        FileInputStream fis = new FileInputStream("d:/1.txt");
        InputStreamReader isr = new InputStreamReader(fis,"GBK");
        BufferedReader br = new BufferedReader(isr);

        FileOutputStream fos = new FileOutputStream("1.txt");
        OutputStreamWriter osw = new OutputStreamWriter(fos,"UTF-8");
        BufferedWriter bw = new BufferedWriter(osw);
    ){
        String str;
        while((str = br.readLine()) != null){
            bw.write(str);
            bw.newLine();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

标签:file,String,IO,File,new,txt,public
From: https://www.cnblogs.com/msuenb/p/17138424.html

相关文章

  • Android Studio的下载与安装
    一、下载下载官网:DownloadAndroidStudio&AppTools-AndroidDevelopers  点击绿色下载 ......
  • jupyter notebook nbextension常用扩展模块不显示
    jupyternotebooknbextension常用扩展模块不显示nbextension不显示有很多的可能,看了许多博客,试过无数种方法之后发现问题还是解决不了其实这最后的问题就是jupyternote......
  • Solution Luogu6097 子集卷积
    其实是暴力。因为这是模板题,所以模板的前置知识也要讲。前置知识:FWT计算或卷积。这里只需要掌握快速计算或卷积的方法,所以内容较少。如果向了解更多(比如异或卷积)的话......
  • Java IO模型
    什么是IOIO是输入input输出output的首字母缩写形式,直观意思是计算机输入输出,它描述的是计算机的数据流动的过程;应用程序的IO操作分为两种动作:IO调用和IO执行。IO调用是......
  • Redis IO多线程的简要测试结果
    RedisIO多线程的简要测试结果摘要最近想简单确认一下IO多线程的对吞吐量的提升情况.正好手头有鲲鹏的机器,所以想直接进行一下验证顺便用一下4216进行一下对比.......
  • POJ 1001 Exponentiation 字符串乘法+快速求幂
    考虑一下下面的样例应该可以AC:底数整数的情况去掉最后后导零没有小数部分时候不输出小数点思路先不考虑小数点将数存入字符串a,b中答案存入retret的长度是a的长......
  • uni-app:使用uni-transition动画(hbuilderx 3.6.18)
    一,官方文档地址:https://uniapp.dcloud.net.cn/component/uniui/uni-transition.html二,代码:<template><view><viewclass="animation-element-wrapper......
  • 守护安全|AIRIOT城市天然气综合管理解决方案
     城市使用天然气存在安全风险和隐患,天然气管理的复杂性也比较高,依靠传统人工难以发现安全漏洞,特别是在燃气场站、管网的安全监管等方面,场站面临作业管理、区......
  • 嵌入与表示学习 embedding & representation learning, embedding & Encoding
     视频:https://www.bilibili.com/video/BV1Cf4y1e7Ht/?spm_id_from=333.788&vd_source=6292df769fba3b00eb2ff1859b99d79e ========================================......
  • 【论文阅读】SCRFD: Sample and Computation 重分配的高效人脸检测
    原始题目SampleandComputationRedistributionforEfficientFaceDetection中文名称采样和计算重分配的高效人脸检测发表时间2021年5月10日平台IC......