Java IO基础知识点总结

基础概念

Java IO(输入/输出)是 Java 编程中一个核心概念,它涉及到 Java 应用程序与外部环境(如文件系统、网络等)之间的数据交换。Java IO 类库主要在 java.io 包中,提供了丰富的类和接口来处理数据流和文件操作。

1. 基本概念和流(Stream)分类

Java IO 操作主要基于流的概念,流(Stream)是数据传输的抽象。在 Java 中,流分为两大类:字节流(Byte Streams)和字符流(Character Streams)。

字节流:以字节(8位二进制)为单位处理数据,主要用于处理原始二进制数据,如图像、声音等文件。主要类包括 InputStream 和 OutputStream。
字符流:以字符为单位处理数据,适用于处理文本数据。主要类包括 Reader 和 Writer。

2. 字节流和字符流

这两种流在 Java 中的使用方法类似,但它们服务的数据类型和使用场景不同。
字节流

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamTest {
    public static void main(String[] args) {
        try (FileInputStream in = new FileInputStream("input.txt");
             FileOutputStream out = new FileOutputStream("output.txt")) {
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
字符流
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CharacterStreamTest {
    public static void main(String[] args) {
        try (FileReader in = new FileReader("input.txt");
             FileWriter out = new FileWriter("output.txt")) {
            int c;
            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 缓冲流

Java IO 提供了缓冲流(Buffered Streams),它们使用内部缓冲区来读写数据,这样可以减少实际的读写操作次数,从而提高性能。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedStreamTest {
    public static void main(String[] args) {
        try (BufferedReader in = new BufferedReader(new FileReader("input.txt"));
             BufferedWriter out = new BufferedWriter(new FileWriter("output.txt"))) {
            String line;
            while ((line = in.readLine()) != null) {
                out.write(line);
                out.newLine();  // 写入换行符
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

4. 数据流

数据流(Data Streams)允许应用程序以与机器无关的方式从底层输入流中读取基本数据类型和字符串。

import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class DataStreamTest {
    public static void main(String[] args) {
        try (DataOutputStream out = new DataOutputStream(new FileOutputStream("data.bin"));
             DataInputStream in = new DataInputStream(new FileInputStream("data.bin"))) {
            out.writeInt(123);
            out.writeDouble(123.45);
            out.writeUTF("Hello");

            int i = in.readInt();
            double d = in.readDouble();
            String s = in.readUTF();

            System.out.println("Read Int: " + i);
            System.out.println("Read Double: " + d);
            System.out.println("Read String: " + s);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

进阶概念

1. 随机访问文件

Java IO 提供了 RandomAccessFile 类,允许你跳到文件中的任何位置来读写数据。这对于需要访问大文件中特定部分的应用特别有用。

import java.io.RandomAccessFile;
import java.io.IOException;

public class RandomAccessFileExample {
    public static void main(String[] args) {
        try (RandomAccessFile file = new RandomAccessFile("example.dat", "rw")) {
            // 写入一些数据
            file.writeInt(100);
            file.writeDouble(123.456);
            file.writeUTF("Hello World");

            // 跳到文件的起始位置
            file.seek(0);

            // 读取并显示数据
            System.out.println(file.readInt());
            System.out.println(file.readDouble());
            System.out.println(file.readUTF());

            // 跳到文件的开头,写入新的整数
            file.seek(0);
            file.writeInt(200);

            // 再次跳到起始位置,读取新的整数
            file.seek(0);
            System.out.println(file.readInt());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. Java NIO

Java NIO (New IO) 是一个从 Java 1.4 开始引入的API,它提供了非阻塞方式的IO。NIO 支持面向缓冲的IO操作,NIO 的通道(Channel)和缓冲区(Buffer)使得数据的读写更为高效。

Channels and Buffers
Channels:类似于流,但可以进行双向数据传输(读写)。
Buffers:缓冲区实质上是数据的容器,并且可以被读写。

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class NIOExample {
    public static void main(String[] args) {
        try (FileInputStream fin = new FileInputStream("input.txt");
             FileChannel channel = fin.getChannel()) {
            
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int bytesRead = channel.read(buffer);
            
            while (bytesRead != -1) {
                buffer.flip();  // 切换到读模式
                while (buffer.hasRemaining()) {
                    System.out.print((char) buffer.get());
                }
                buffer.clear();  // 清空缓冲区,准备再次读取
                bytesRead = channel.read(buffer);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 选择器(Selectors)

选择器是Java NIO中的高级功能,允许单个线程管理多个Channel。如果你的应用开启了多个连接(例如,一个聊天服务器),使用选择器可以非常高效地管理这些连接。

import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SelectionKey;
import java.net.InetSocketAddress;
import java.util.Iterator;

public class SelectorExample {
    public static void main(String[] args) throws IOException {
        try (Selector selector = Selector.open();
             ServerSocketChannel serverChannel = ServerSocketChannel.open()) {
            
            serverChannel.bind(new InetSocketAddress("localhost", 8080));
            serverChannel.configureBlocking(false);
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);

            while (true) {
                selector.select();  // 阻塞,直到至少有一个通道发生了注册的事件
                Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
                
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();
                    if (key.isAcceptable()) {
                        // 处理接受新连接
                    } else if (key.isReadable()) {
                        // 处理读事件
                    }
                    keyIterator.remove();
                }
            }
        }
    }
}

4. 文件锁定(File Locking)

文件锁定是一种同步访问文件的机制,确保没有两个进程可以同时写入同一个文件。

import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public class FileLockExample {
    public static void main(String[] args) {
        try (RandomAccessFile file = new RandomAccessFile("example.txt", "rw");
             FileChannel channel = file.getChannel()) {

            // 获取对该文件的独占锁定
            FileLock lock = channel.lock();
            try {
                // 在这个区域进行文件操作
                System.out.println("File is locked for exclusive access");
            } finally {
                lock.release(); // 释放锁
                System.out.println("Lock released");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5. 对象序列化

对象序列化是将对象的状态转换为可以存储或传输的格式的过程。在Java中,这通常意味着转换为字节流。

import java.io.*;

public class SerializationExample {
    private static class Student implements Serializable {
        private static final long serialVersionUID = 1L;
        String name;
        transient int age; // 使用 transient 关键字标记非序列化字段

        public Student(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return "Student{name='" + name + "', age=" + age + "}";
        }
    }

    public static void main(String[] args) {
        Student student = new Student("John Doe", 20);

        // 序列化
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("student.ser"))) {
            out.writeObject(student);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 反序列化
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("student.ser"))) {
            Student deserializedStudent = (Student) in.readObject();
            System.out.println(deserializedStudent);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

6. Java NIO 2 (File API)

Java 7 引入了 NIO 2,它在原有 NIO 的基础上增加了对文件处理和文件系统特性的支持。

import java.nio.file.*;

public class NIO2Example {
    public static void main(String[] args) {
        Path path = Paths.get("somefile.txt");

        try {
            // 创建文件
            if (!Files.exists(path)) {
                Files.createFile(path);
            }

            // 写入内容到文件
            Files.write(path, "Hello, World!".getBytes(), StandardOpenOption.APPEND);

            // 读取文件内容
            byte[] bytes = Files.readAllBytes(path);
            System.out.println(new String(bytes));

            // 删除文件
            Files.delete(path);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

面试相关问题

1. 解释Java IO中的流(Stream)是什么。

在Java中,流(Stream)是一种抽象概念,用于在程序和数据源或目标之间顺序读写数据。它们可以来自或去向不同的数据源,如文件、数组、网络连接等。流通常分为输入流和输出流,其中输入流用于从数据源读取数据,输出流用于向目标写数据。Java IO库提供了多种流类型,包括字节流(如InputStream和OutputStream)和字符流(如Reader和Writer)。

2. 字节流和字符流有什么区别?

字节流和字符流是Java IO中处理输入和输出的两种主要方式。字节流(如InputStream和OutputStream)以字节为单位处理数据,适用于处理所有类型的数据,包括二进制数据、图像、视频文件等。字符流(如Reader和Writer)以字符为单位处理数据,专门用于处理文本数据。使用字符流读写时,Java虚拟机会自动处理和转换字符到字节之间的转换。

3. 什么是缓冲流,使用它有什么好处?

缓冲流(Buffered Streams)是Java IO中的一种包装流,用于提高读写数据的效率。它通过设置内部缓冲区来减少实际读写硬盘的次数。例如,BufferedReader和BufferedWriter分别用于包装其他的字符输入和输出流,使得单个字符的读写操作转变为批量读写,大大提高了IO性能。使用缓冲流的好处主要是提高程序的执行效率,减少与磁盘交互的次数。

4. Java中如何实现文件的复制?

在Java中实现文件复制通常使用字节流或字符流,具体取决于文件的类型(二进制或文本)。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileCopy {
    public static void main(String[] args) {
        try (FileInputStream in = new FileInputStream("source.txt");
             FileOutputStream out = new FileOutputStream("destination.txt")) {
            int byteRead;
            while ((byteRead = in.read()) != -1) {
                out.write(byteRead);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5. 解释序列化和反序列化。

序列化是指将对象的状态转换为可以存储或传输的格式(如JSON、XML或二进制格式)的过程,以便可以在文件系统、数据库或网络中保存或发送。反序列化是将已序列化的数据恢复为原始对象的过程。在Java中,可以通过实现Serializable接口,并使用ObjectOutputStream和ObjectInputStream来进行对象的序列化和反序列化。这使得对象可以通过网络发送或持久化存储到磁盘上。

总体知识

1. 高级文件处理

随机访问文件:使用RandomAccessFile类进行文件的随机访问。这允许你跳到文件的任何位置读写数据,非常适合需要频繁查找的大文件。
文件加锁:理解如何对文件片段使用锁定机制,防止并发访问时的数据冲突。这可以通过FileChannel的lock()方法实现。

2. Java NIO

Buffers and Channels:理解缓冲区(Buffers)和通道(Channels)的使用,这是NIO中数据处理的核心。掌握不同类型的Buffer如ByteBuffer、CharBuffer等,以及它们的使用场景。
非阻塞IO:了解如何使用非阻塞IO进行网络通信,这包括设置非阻塞模式的SocketChannel和ServerSocketChannel。
选择器(Selectors):掌握使用选择器管理多个通道的技术。选择器允许单线程处理多个Channel的IO操作,适合实现高性能的网络服务器。

3. 文件系统操作(Java NIO.2)

文件和目录的操作:使用Files和Path类来执行复杂的文件系统操作,如文件属性读取、文件树的遍历、创建符号链接等。
文件变更监听:使用WatchService API 监听文件系统的变化,对于需要实时响应文件修改的应用非常有用。

4. 序列化机制

自定义序列化:了解如何自定义序列化过程,包括使用transient关键字处理不需要序列化的属性,以及实现Externalizable接口进行更精细控制的序列化和反序列化。
序列化的安全性:理解和防范序列化过程中可能的安全风险,如防止序列化数据的篡改和重放攻击。

5. 性能优化

IO性能调优:理解和应用各种IO优化技术,比如合理使用缓冲、选择合适的读写方式和大小、以及利用现代操作系统的高级特性如内存映射(Memory-Mapped Files)。
资源管理:在IO操作中采用正确的资源管理策略,例如使用try-with-resources语句确保及时释放资源。

6. 最佳实践

异常处理:精确地处理IO操作中可能发生的异常,避免因为资源泄露或数据不一致导致的问题。
数据完整性:在进行文件读写操作时,确保数据的完整性和一致性,尤其是在并发场景下。

使用NIO进行文件复制

import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

public class FileCopyNIO {
    public static void copyFile(Path source, Path target) {
        try (FileChannel srcChannel = FileChannel.open(source, StandardOpenOption.READ);
             FileChannel destChannel = FileChannel.open(target, StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
            
            srcChannel.transferTo(0, srcChannel.size(), destChannel);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Path sourcePath = Path.of("source.txt");
        Path targetPath = Path.of("target.txt");
        copyFile(sourcePath, targetPath);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/769579.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为 eNSP 模拟器 配置RIP实例 动态路由协议

1 实验拓扑 2 配置路由器 #R1 Huawei>sys [Huawei]sysname R1 [R1]interface GigabitEthernet 0/0/0 [R1-GigabitEthernet0/0/0]ip address 192.168.1.1 255.255.255.0 [R1-GigabitEthernet0/0/0]qu [R1]rip [R1-rip-1]network 192.168.1.0 [R1-rip-1]version 2 [R1-rip-…

C++:求梯形面积

梯形面积 已知上底15厘米&#xff0c;下底25厘米&#xff0c;问梯形面积值是多少&#xff1f; #include<iostream> using namespace std; int main() {//梯形的面积公式&#xff08;上底下底&#xff09; 高 2//上底变量、下底变量int s,d,h,m;s15;d25;h 2*150 * 2/s ;…

Bootstrap 图片

Bootstrap 图片 Bootstrap 是一个流行的前端框架,它提供了一套丰富的工具和组件,用于快速开发响应式和移动优先的网页。在本文中,我们将探讨如何使用 Bootstrap 来处理和展示图片,包括图片的响应式设计、图片样式和图片布局。 响应式图片 Bootstrap 通过其栅格系统提供了…

接口自动化测试高频面试题

一、json和字典的区别&#xff1f; json就是一个文本、字符串&#xff1b;有固定的格式&#xff0c;格式长的像python字典和列表的组合&#xff1b; 以key-value的键值对形式来保存数据&#xff0c;结构清晰&#xff0c;。可以说是目前互联网项目开发中最常用的一种数据交互格…

k8s record 20240703

1. containerd 它不用于直接和开发人员互动&#xff0c;在这方面不和docker竞争 containerd的用时最短&#xff0c;性能最好。 containerd 是容器的生命周期管理&#xff0c;容器的网络管理等等&#xff0c;真正让容器运行需要runC containerd 是一个独立的容器运行时&am…

PyTorch环境配置及安装

PyTorch环境配置及安装 Step1&#xff1a;安装Anaconda 参考该链接&#xff08;视频01:30--03:00为安装教程&#xff09;&#xff1a; 【PyTorch深度学习快速入门教程&#xff08;绝对通俗易懂&#xff01;&#xff09;【小土堆】】 https://www.bilibili.com/video/BV1hE41…

AIGC在软件开发中的应用

目录 1. AIGC技术概述1.1 定义与背景1.2 发展历程 2. AIGC在软件开发中的应用2.1 代码生成2.2 错误检测与修复2.3 自动化测试 3. AIGC对开发者职业前景的影响3.1 助力与赋能开发者代码示例&#xff1a;自动化测试 3.2 技能需求转变与职业转型压力代码示例&#xff1a;AIGC辅助的…

鸿翼FEX文件安全交换系统,打造安全高效的文件摆渡“绿色通道”

随着数字经济时代的到来&#xff0c;数据已成为最有价值的生产要素&#xff0c;是企业的重要资产之一。随着数据流动性的增强&#xff0c;数据安全问题也随之突显。尤其是政务、金融、医疗和制造业等关键领域组织和中大型企业&#xff0c;面临着如何在保障数据安全的同时&#…

《数字图像处理与机器视觉》案例四 基于分水岭算法的粘连物体的分割与计数

一、引言 分水岭算法&#xff08;Watershed Algorithm&#xff09;&#xff0c;是一种基于拓扑理论的数学形态学的分割方法&#xff0c;其基本思想是把图像看作是测地学上的拓扑地貌&#xff0c;图像中每一点像素的灰度值表示该点的海拔高度&#xff0c;每一个局部极小值及其影…

少儿编程 2024年6月电子学会图形化编程等级考试Scratch一级真题解析(选择题)

2024年6月scratch编程等级考试一级真题 选择题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 1、音乐Video Game1的时长将近8秒&#xff0c;点击一次角色&#xff0c;下列哪个程序不能完整地播放音乐两次 A、 B、 C、 D、 答案&#xff1a;D 考…

Socket编程用到的函数TCP UDP实例

最基本的 Socket 模型 参考这次答应我&#xff0c;一举拿下 I/O 多路复用&#xff01; (qq.com) Socket编程详解-CSDN博客 Socket是一种通信机制&#xff0c;通过它可以在不同主机之间进行数据交换。在Socket编程中&#xff0c;有两种常见的通信模式&#xff1a;客户端-服务…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于目标鲁棒的电动汽车及基站储能联合参与电力市场的决策模型 》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

Go语言--递归函数

递归函数 递归指所数可以直接或问接的调用自身。递归函数通常有相同的结构:一个跳出条件和一个递归体。所谓跳出条件就是根据传入的参数判断是否需要停止递归&#xff0c;而递归体则是函数自身所做的一些处理。 普通函数的调用流程 递归函数调用流程 一定要写终止条件。 实现…

【C++】初步认识C++

1. 初识C1.1 C概念相关1.2 C发展史及其重要性1.2.1 发展史1.2.2 重要性 2. C关键字3. 命名空间4. 输入和输出 个人主页&#xff1a;C_GUIQU 归属专栏&#xff1a;【C学习】 1. 初识C 1.1 C概念相关 C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。 【来源】…

Unity游戏帧率查看软件Fraps

Download Fraps 3.5.99 free version 下载、安装、运行这个软件&#xff0c;左上角就会自动显示帧率

跑腿平台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;基础数据管理&#xff0c;管理员管理&#xff0c;接单详情管理&#xff0c;跑腿员管理&#xff0c;跑腿任务管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;跑腿任务&#xff0c;接单员&…

windows上安装Frida环境

python安装 下载地址 Python Release Python 3.12.4 | Python.org python安装好后&#xff0c;使用如下命令安装frida客户端 pip install frida-tools 使用frida --version 查看frida版本 安装手机模拟器&#xff08;雷电模拟器&#xff09; 我的版本是4.0.61 查看CPU架构 adb …

SpringCloud进阶篇

文章目录 网关快速入门创建模块引入依赖修改启动类配置路由路由过滤(一般不用) 自定义GlobalFilter登录校验登录校验过滤器 微服务获取用户信息保存用户信息到请求头拦截器获取用户信息 OpenFeign传递用户信息配置共享添加共享配置拉取共享配置 配置热更新添加配置到Nacos配置热…

从零开始的python学习生活

第一天 pycharm部分好用快捷键 变量名的定义 与之前学习过的语言有所不同的是&#xff0c;python中变量名的定义更加的简洁 such as 整形。浮点型和字符串的定义 money50 haha13.14 gaga"hello"字符串的定义依然是需要加上引号&#xff0c;也不需要写&#xff1b;…

【docker】运行阶段遇到的问题

目录 1、查询docker 下挂载了哪些工具 2、docker中的简单命令 3、实际场景应用&#xff08;redis&#xff09; 目前工作中仅用到了redis,所以没有太多经验可以交流&#xff0c;暂时仅将我目前遇到的进行发布。还请见谅。 1、查询docker 下挂载了哪些工具 docker ps -a 或者…