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编程示例,并可能需要根据具体的应用程序和网络环境做适当的调整。

相关文章
|
20小时前
|
设计模式 算法 Java
Java的前景如何,好不好自学?,万字Java技术类校招面试题汇总
Java的前景如何,好不好自学?,万字Java技术类校招面试题汇总
|
20小时前
|
存储 网络协议 前端开发
es集群安装,邮储银行java面试
es集群安装,邮储银行java面试
|
20小时前
|
消息中间件 JSON Java
十五,java高级程序员面试宝典
十五,java高级程序员面试宝典
|
20小时前
|
NoSQL 算法 Java
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
【redis源码学习】持久化机制,java程序员面试算法宝典pdf
|
20小时前
|
消息中间件 Java Kafka
Java大文件排序(有手就能学会),kafka面试题2024
Java大文件排序(有手就能学会),kafka面试题2024
|
22小时前
SpringJDK动态代理实现,2024Java面试真题精选干货整理
SpringJDK动态代理实现,2024Java面试真题精选干货整理
|
22小时前
|
安全 前端开发 Java
Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day15
Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day15
|
1天前
|
Java
阅读《代码整洁之道》总结(1),java多线程面试
阅读《代码整洁之道》总结(1),java多线程面试
|
1天前
|
NoSQL Java 关系型数据库
爱了!阿里高工纯手打金三银四Java架构面试大全,涵盖近年来1000余道大厂面试真题
爱了!阿里高工纯手打金三银四Java架构面试大全,涵盖近年来1000余道大厂面试真题
|
1天前
|
Java 程序员
Java this关键字详解(3种用法),Java程序员面试必备的知识点
Java this关键字详解(3种用法),Java程序员面试必备的知识点