Java- IO 及其相关面试题(上)

简介: Java- IO 及其相关面试题(上)

目录

一、前言

    Java IO是Java编程中非常重要的一部分,它提供了丰富的输入和输出功能,可以实现对文件、网络和其他设备的读取和写入操作。在开发中,Java IO广泛应用于文件处理、网络通信、序列化等场景。

Java IO主要涉及两个核心概念:输入流和输出流。输入流用于读取数据,输出流用于写入数据。它们支持字节流和字符流两种类型。字节流以字节为单位进行操作,适用于二进制文件或纯文本文件。字符流以字符为单位进行操作,适用于处理文本文件。


   Java IO还提供了标准IO和NIO两种模式。传统的标准IO模式以流的方式进行操作,适用于较小的数据量和较低的并发处理需求。新IO(NIO)模式则基于通道和缓冲区进行操作,适用于高并发、高吞吐量的场景。


   接下来,我们将详细介绍字节流和字符流的操作方法,并给出相应的代码示例。

二、Java IO 概述

输入和输出流

2.1.1 定义

    输入流(InputStream)和输出流(OutputStream)是Java的I/O类库中的基本概念。输入流用于从外部源(例如文件、网络连接等)读取数据,而输出流用于将数据写入到外部目标(例如文件、网络连接等)。


   输入流提供了一种逐个读取数据的方式,可以使用一些方法来读取不同类型的数据,如readByte、readChar、readInt等。输出流则提供了一些方法来写入不同类型的数据,如writeByte、writeChar、writeInt等。输入流和输出流可以用于处理各种不同的数据源和目标,例如文件、网络套接字、内存缓冲区等。


   在应用中,输入流常用于读取文件内容、读取网络数据等场景,而输出流常用于将数据写入文件、将数据发送到网络等场景。

2.1.2 代码示例

下面是一个示例,演示如何使用输入流和输出流来读写文件:

import java.io.*;
public class FileIOExample {
    public static void main(String[] args) {
        // 读取文件内容
        try (InputStream inputStream = new FileInputStream("input.txt")) {
            int data = inputStream.read();
            while (data != -1) {
                System.out.print((char) data);
                data = inputStream.read();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 写入文件内容
        try (OutputStream outputStream = new FileOutputStream("output.txt")) {
            String message = "Hello, World!";
            outputStream.write(message.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2 字节流和字符流

2.2.1 定义

    字节流和字符流是Java I/O类库中的两种不同类型的流。    

字节流(ByteStream)以字节为单位进行读取和写入操作,可以处理任意类型的数据。字节流类库包括InputStream和OutputStream。


   字符流(CharacterStream)以字符为单位进行读取和写入操作,只能处理文本类型的数据。字符流类库包括Reader和Writer。


   字节流和字符流之间的主要区别在于处理的数据类型不同。字节流可以读取和写入任意类型的数据,适用于处理二进制数据和非文本数据。而字符流则专门用于处理文本数据,可以自动进行字符编码和解码,方便读写文本文件。


   在选择流类型时,需要考虑到处理的数据类型。如果处理的是文本数据,应选择字符流;如果处理的是二进制数据或非文本数据,应选择字节流。

2.2.2 代码示例

下面是一个示例,演示如何使用字符流来读写文本文件:

import java.io.*;
public class FileIOExample {
    public static void main(String[] args) {
        // 读取文本文件内容
        try (Reader reader = new FileReader("input.txt")) {
            int data = reader.read();
            while (data != -1) {
                System.out.print((char) data);
                data = reader.read();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 写入文本文件内容
        try (Writer writer = new FileWriter("output.txt")) {
            String message = "Hello, World!";
            writer.write(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.3 标准IO和NIO

    传统的标准IO(IO是指输入输出)是一种同步阻塞的IO模型,它使用InputStream和OutputStream来进行数据的读取和写入操作。
   标准IO的特点是对数据的读取和写入是以阻塞方式进行的,意味着在IO操作完成之前,当前线程会被阻塞,无法进行其他任务。这种模型在处理大量的并发连接时,性能较差。


   NIO(New IO)是Java提供的一种新的IO模型,它使用通道(Channel)和缓冲区(Buffer)来进行数据的读取和写入操作。


下面将会介绍NIO、BIO和AIO的区别以及NIO使用通道(Channel)和缓冲区(Buffer)。

三、字节流和字符流

3.1. 字节流:InputStream和OutputStream

    字节流是处理字节数据的输入输出流的抽象类。常用的字节流类有FileIn putStream、FileOutputStream、ByteArrayInputStream和ByteArrayOutputStream等。

3.1.1. FileInputStream和FileOutputStream

    FileInputStream和FileOutputStream是用于读取和写入文件的字节流类。

以下是一个读取文件内容并打印的示例代码:

try (FileInputStream fis = new FileInputStream("example.txt")) {
    int data;
    while ((data = fis.read()) != -1) {
        System.out.print((char) data);
    }
} catch (IOException e) {
    e.printStackTrace();
}

以下是一个写入文件内容的示例代码:

try (FileOutputStream fos = new FileOutputStream("example.txt")) {
    fos.write("Hello, World!".getBytes());
} catch (IOException e) {
    e.printStackTrace();
}

3.1.2. ByteArrayInputStream和ByteArrayOutputStream

   ByteArrayInputStream和ByteArrayOutputStream是用于在内存中读取和写入字节数据的字节流类。

以下是一个从字节数组中读取数据并打印的示例代码:

byte[] data = {65, 66, 67, 68, 69};
try (ByteArrayInputStream bais = new ByteArrayInputStream(data)) {
    int byteData;
    while ((byteData = bais.read()) != -1) {
        System.out.print((char) byteData);
    }
} catch (IOException e) {
    e.printStackTrace();
}

以下是一个将数据写入字节数组并打印的示例代码:

try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
    baos.write("Hello, World!".getBytes());
    byte[] data = baos.toByteArray();
    System.out.println(new String(data));
} catch (IOException e) {
    e.printStackTrace();
}

3.1.3. BufferedInputStream和BufferedOutputStream

    BufferedInputStream和BufferedOutputStream是用于提升IO性能的装饰器类,它们通过在内部提供缓冲区来实现。

以下是一个使用BufferedInputStream读取文件的示例代码:

try (FileInputStream fis = new FileInputStream("example.txt");
    BufferedInputStream bis = new BufferedInputStream(fis)) {
    int data;
    while ((data = bis.read()) != -1) {
        System.out.print((char) data);
    }
} catch (IOException e) {
    e.printStackTrace();
}

以下是一个使用BufferedOutputStream写入文件的示例代码:

try (FileOutputStream fos = new FileOutputStream("example.txt");
    BufferedOutputStream bos = new BufferedOutputStream(fos)) {
    bos.write("Hello, World!".getBytes());
} catch (IOException e) {
    e.printStackTrace();
}

  以上是字节流的基本使用方法和示例代码。接下来,我们将介绍字符流的操作方法。

3.2字符流:Reader和Writer

3.2.1. FileReader和FileWriter:

    FileReader是一个用于读取字符文件的类,而FileWriter是一个用于写入字符文件的类。下面是使用FileReader读取字符文件和使用FileWriter写入字符文件的代码示例:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class FileExample {
    public static void main(String[] args) {
        // 使用FileReader读取字符文件
        try (FileReader reader = new FileReader("input.txt")) {
            int data;
            while ((data = reader.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 使用FileWriter写入字符文件
        try (FileWriter writer = new FileWriter("output.txt")) {
            writer.write("Hello, World!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

  在上面的示例中,使用FileReader读取名为"input.txt"的字符文件,并将其内容打印到控制台上。接下来,使用FileWriter将字符串"Hello, World!"写入名为"output.txt"的字符文件。


3.2.2. InputStreamReader和OutputStreamWriter:

   InputStreamReader是一个字符流和字节流之间的桥梁,它将字节流转换为字符流;而OutputStreamWriter是将字符流转换为字节流的类。

   下面是使用InputStreamReader将字节流转换为字符流,并使用OutputStreamWriter将字符流转换为字节流的代码示例:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class StreamExample {
    public static void main(String[] args) {
        // 使用InputStreamReader将字节流转换为字符流
        try (FileInputStream inputStream = new FileInputStream("input.txt");
             InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "UTF-8")) {
            int data;
            while ((data = inputStreamReader.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 使用OutputStreamWriter将字符流转换为字节流
        try (FileOutputStream outputStream = new FileOutputStream("output.txt");
             OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8")) {
            outputStreamWriter.write("Hello, World!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上面的示例中,使用InputStreamReader将名为"input.txt"的字节流转换为字符流,并将其内容打印到控制台上。

   接下来,使用OutputStreamWriter将字符串"Hello, World!"转换为名为"output.txt"的字节流。


3.2.3. BufferedReader和BufferedWriter:

   BufferedReader和BufferedWriter 是具有缓冲区功能的字符流,可以提高读取和写入字符数据的效率。

   下面是使用BufferedReader读取字符文件和使用BufferedWriter写入字符文件的代码示例:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferExample {
    public static void main(String[] args) {
        // 使用BufferedReader读取字符文件
        try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 使用BufferedWriter写入字符文件
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
            writer.write("Hello, World!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上面的示例中,使用BufferedReader逐行读取名为"input.txt"的字符文件,并将每行内容打印到控制台上。

通过使用BufferedReader和BufferedWriter,可以减少对磁盘的读写次数,从而提高读取和写入字符数据的效率。

四、文件操作

4.1. 文件创建、读取和写入

    文件的创建、读取和写入是文件操作中的基本操作。下面是一些常见的文件操作代码示例:

  1. 创建文件:
file = open("filename.txt", "w")  # 打开文件,并指定写入模式
file.close()  # 关闭文件
  1. 写入文件:
file = open("filename.txt", "w")  # 打开文件,并指定写入模式
file.write("Hello, World!")  # 写入内容
file.close()  # 关闭文件

读取文件:

file = open("filename.txt", "r")  # 打开文件,并指定读取模式
content = file.read()  # 读取文件内容
print(content)  # 打印文件内容
file.close()  # 关闭文件

4.2. 文件复制和移动

    文件复制和移动是常见的文件操作需求。可以使用shutil模块中的函数来执行文件复制和移动。

  1. 文件复制:
import shutil
src_file = "path/to/original_file.txt"
dst_file = "path/to/new_file.txt"
shutil.copy(src_file, dst_file)  # 复制文件
  1. 文件移动:
import shutil
src_file = "path/to/original_file.txt"
dst_dir = "path/to/destination_directory/"
shutil.move(src_file, dst_dir)  # 移动文件

4.3. 文件删除和重命名

文件删除和重命名也是常见的文件操作需求。

  1. 文件删除:
import os
file = "path/to/file.txt"
os.remove(file)  # 删除文件

文件重命名

import os
src_file = "path/to/original_file.txt"
dst_file = "path/to/new_file.txt"
os.rename(src_file, dst_file)  # 重命名文件

4.4. 文件属性和权限

文件属性和权限信息可以使用os模块的函数来获取和设置。

  1. 获取文件信息:
import os
file = "path/to/file.txt"
file_info = os.stat(file)  # 获取文件信息
print(file_info.st_size)  # 打印文件大小
print(file_info.st_mtime)  # 打印文件修改时间

设置文件权限:

import os
file = "path/to/file.txt"
os.chmod(file, 0o777)  # 设置文件权限为 777

请注意,这些代码示例仅作为基本的文件操作示例,需要根据具体的应用程序和操作系统做适当的调整。

五、网络通信

5.1. Socket编程基础

    Socket编程是一种在计算机网络中进行通信的基本方式。它允许不同的计算机之间通过网络进行数据传输。

Socket编程的基本概念:

服务器端和客户端:在Socket编程中,通信的一方被称为服务器端,而另一方被称为客户端。服务器端通常绑定到一个特定的IP地址和端口,并在该端口上监听客户端的请求。


IP地址和端口:IP地址是网络中唯一标识一个主机的地址,端口是用于标识一个进程的数字。


套接字(Socket):套接字是通信的端点,它在客户端和服务器端之间建立连接,并通过连接进行数据传输。

   以下是一个简单的Socket编程示例,展示了服务器端和客户端的基本代码:

5.2. 服务器端示例代码

import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.FileNotFoundException;
public class FileOperations {
    public static void main(String[] args) {
        createFile();
        writeFile();
        readFile();
        copyFile();
        moveFile();
        deleteFile();
        renameFile();
    }
    public static void createFile() {
        try {
            File file = new File("filename.txt");
            if (file.createNewFile()) {
                System.out.println("File created: " + file.getName());
            } else {
                System.out.println("File already exists.");
            }
        } catch (IOException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
    }
    public static void writeFile() {
        try {
            FileWriter writer = new FileWriter("filename.txt");
            writer.write("Hello, World!");
            writer.close();
            System.out.println("Successfully wrote to the file.");
        } catch (IOException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
    }
    public static void readFile() {
        try {
            BufferedReader reader = new BufferedReader(new FileReader("filename.txt"));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
        } catch (FileNotFoundException e) {
            System.out.println("File not found.");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
    }
    public static void copyFile() {
        File srcFile = new File("path/to/original_file.txt");
        File destFile = new File("path/to/new_file.txt");
        try {
            Files.copy(srcFile.toPath(), destFile.toPath());
            System.out.println("File copied successfully.");
        } catch (IOException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
    }
    public static void moveFile() {
        File srcFile = new File("path/to/original_file.txt");
        File destDir = new File("path/to/destination_directory/");
        try {
            Files.move(srcFile.toPath(), destDir.toPath().resolve(srcFile.getName()));
            System.out.println("File moved successfully.");
        } catch (IOException e) {
            System.out.println("An error occurred.");
            e.printStackTrace();
        }
    }
    public static void deleteFile() {
        File file = new File("path/to/file.txt");
        if (file.delete()) {
            System.out.println("File deleted: " + file.getName());
        } else {
            System.out.println("Failed to delete the file.");
        }
    }
    public static void renameFile() {
        File srcFile = new File("path/to/original_file.txt");
        File destFile = new File("path/to/new_file.txt");
        if (srcFile.renameTo(destFile)) {
            System.out.println("File renamed successfully.");
        } else {
            System.out.println("Failed to rename the file.");
        }
    }
}

5.3. 客户端示例代码

import java.io.*;
import java.net.*;
public class Client {
    public static void main(String[] args) {
        try {
            // 创建客户端套接字
            Socket clientSocket = new Socket("localhost", 8888); // 服务器的IP地址和端口号
            // 发送数据给服务器
            String message = "Hello, server!";
            OutputStream outputStream = clientSocket.getOutputStream();
            outputStream.write(message.getBytes());
            // 接收服务器发送的数据
            InputStream inputStream = clientSocket.getInputStream();
            byte[] buffer = new byte[1024];
            int length = inputStream.read(buffer);
            String data = new String(buffer, 0, length);
            System.out.println("收到服务器消息:" + data);
            // 关闭连接
            clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

请注意,这些代码示例仅作为基本的Socket编程示例,并可能需要根据具体的应用程序和网络环境做适当的调整。

相关文章
|
3月前
|
Java 测试技术 微服务
最新技术栈下 Java 面试高频技术点实操指南详解
本指南结合最新Java技术趋势,涵盖微服务(Spring Cloud Alibaba)、响应式编程(Spring WebFlux)、容器化部署(Docker+Kubernetes)、函数式编程、性能优化及测试等核心领域。通过具体实现步骤与示例代码,深入讲解服务注册发现、配置中心、熔断限流、响应式数据库访问、JVM调优等内容。适合备战Java面试,提升实操能力,助力技术进阶。资源链接:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)
165 25
|
3月前
|
缓存 Java 关系型数据库
2025 年最新华为 Java 面试题及答案,全方位打造面试宝典
Java面试高频考点与实践指南(150字摘要) 本文系统梳理了Java面试核心考点,包括Java基础(数据类型、面向对象特性、常用类使用)、并发编程(线程机制、锁原理、并发容器)、JVM(内存模型、GC算法、类加载机制)、Spring框架(IoC/AOP、Bean生命周期、事务管理)、数据库(MySQL引擎、事务隔离、索引优化)及分布式(CAP理论、ID生成、Redis缓存)。同时提供华为级实战代码,涵盖Spring Cloud Alibaba微服务、Sentinel限流、Seata分布式事务,以及完整的D
194 1
|
2月前
|
缓存 Java API
Java 面试实操指南与最新技术结合的实战攻略
本指南涵盖Java 17+新特性、Spring Boot 3微服务、响应式编程、容器化部署与数据缓存实操,结合代码案例解析高频面试技术点,助你掌握最新Java技术栈,提升实战能力,轻松应对Java中高级岗位面试。
330 0
|
3月前
|
存储 安全 Java
常见 JAVA 集合面试题整理 自用版持续更新
这是一份详尽的Java集合面试题总结,涵盖ArrayList与LinkedList、HashMap与HashTable、HashSet与TreeSet的区别,以及ConcurrentHashMap的实现原理。内容从底层数据结构、性能特点到应用场景逐一剖析,并提供代码示例便于理解。此外,还介绍了如何遍历HashMap和HashTable。无论是初学者还是进阶开发者,都能从中受益。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
207 3
|
3月前
|
存储 安全 Java
2025 最新史上最全 Java 面试题独家整理带详细答案及解析
本文从Java基础、面向对象、多线程与并发等方面详细解析常见面试题及答案,并结合实际应用帮助理解。内容涵盖基本数据类型、自动装箱拆箱、String类区别,面向对象三大特性(封装、继承、多态),线程创建与安全问题解决方法,以及集合框架如ArrayList与LinkedList的对比和HashMap工作原理。适合准备面试或深入学习Java的开发者参考。附代码获取链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
1344 48
|
3月前
|
算法 架构师 Java
Java 开发岗及 java 架构师百度校招历年经典面试题汇总
以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。
107 5
|
3月前
|
Java API 微服务
2025 年 Java 校招面试全攻略:从面试心得看 Java 岗位求职技巧
《2025年Java校招最新技术要点与实操指南》 本文梳理了2025年Java校招的核心技术栈,并提供了可直接运行的代码实例。重点技术包括: Java 17+新特性(Record类、Sealed类等) Spring Boot 3+WebFlux响应式编程 微服务架构与Spring Cloud组件 Docker容器化部署 Redis缓存集成 OpenAI API调用 通过实际代码演示了如何应用这些技术,如Java 17的Record类简化POJO、WebFlux构建响应式API、Docker容器化部署。
139 5
|
3月前
|
缓存 NoSQL Java
Java Redis 面试题集锦 常见高频面试题目及解析
本文总结了Redis在Java中的核心面试题,包括数据类型操作、单线程高性能原理、键过期策略及分布式锁实现等关键内容。通过Jedis代码示例展示了String、List等数据类型的操作方法,讲解了惰性删除和定期删除相结合的过期策略,并提供了Spring Boot配置Redis过期时间的方案。文章还探讨了缓存穿透、雪崩等问题解决方案,以及基于Redis的分布式锁实现,帮助开发者全面掌握Redis在Java应用中的实践要点。
193 6
|
3月前
|
安全 Java API
2025 年 Java 校招面试常见问题及详细答案汇总
本资料涵盖Java校招常见面试题,包括Java基础、并发编程、JVM、Spring框架、分布式与微服务等核心知识点,并提供详细解析与实操代码,助力2025校招备战。
187 1
|
3月前
|
算法 Java 微服务
2025 年 Java 面试宝典社招春招秋招实操全方位攻略
2025年Java面试宝典涵盖核心技术及最新趋势,分为四大板块:1. Java基础:深入数据类型、多态等特性,结合学生信息管理等实例;2. JVM核心:解析内存模型与GC算法,附多线程转账等场景应用;3. 高并发方案:详解synchronized与线程池配置,提供Web服务器优化案例;4. Spring生态:剖析IoC/AOP原理,演示微服务架构实现。特别新增Java 17+特性实操,包括Record类、密封接口等语法糖,整合Spring Boot 3、响应式编程及云原生技术,通过订单状态机、API网关配置。
252 1

热门文章

最新文章