Java IO

Java IO 教程

Java IO 是一套 Java 用来读写数据(输入和输出)的 API 。大部分程序都要处理输入,并由输入产生一些输出。Java 对此提供了 Java IO 包。
下面我们将主要介绍这些类是如何组织的,以及怎样使用他们。因此你就不会迷惑需要时怎样选择类,或者是否有一个满足你需求的类存在。

Java.IO 包的范围

Java.IO包并没有涵盖所有输入输出类型。例如,并不包含 GUI 或者网页的输入输出,这些输入输出在其他地方涉及,比如 Swing 工程中的 JFC 类,或者 J2EE 里的 Servlet 和 HTTP 包。


Java IO 概述

在这一小节我会对 Java IO 包下所有的类概述,更加具体说,会根据类的用途对类进行分组。这个分组会使你在未来工作中,进行类的用途判定时,或者某个特定用途选择类时变得更加容易。

输入和输出——数据源和目标媒介

术语输入输出往往会让人有一点疑惑,一个应用程序的输入往往是另一个应用程序的输出。
为了消除这个疑惑,我试着给输入输出起一些不一样的别名,让他们从概念上与数据的来源和数据的流向相关。
Java IO 包主要关注的是从原始数据源的读取以及输出原始数据到目标媒介。一下是最典型的数据源和目标媒介。

  • 文件
  • 管道
  • 网络连接
  • 内存缓存
  • System.in ; System.out ; Systemn.error ;

下图描述一个程序从数据源读取数据,然后将数据输出到其他媒介的原理
这里写图片描述

Java IO 中,流从概念上来说是一个连续的数据流。你可以从流中读取数据,也可以往流中写入数据。流与数据源或者数据流向的媒介相关。在 Java IO 中流既可以是字节流(以字节为单位的进行读写),也可以是字符流(以字符为单位进行读写)。

InputStream、OutputStream、Reader、Writer

一个程序需要 InputStream 或者 Reader 从数据源读取数据,需要 OutputStream 或者 Writer 将数据写入到目标媒介中。
这里写图片描述
InputStrem 和 Reader 与数据源相关,OutputStream 和 Writer 与目标媒介相关。

Java IO 用途和特征

Java IO 中包含了许多 InputStream、OutputStream、Reader、Writer 的子类。这样设计的原因是让每一个类负责不同的功能。各个类用途汇总如下。

  • 文件访问
  • 网络访问
  • 内部缓存访问
  • 线程内部通信
  • 缓冲
  • 过滤
  • 解析
  • 读写文本
  • 读写基本数据类型
  • 读写对象

Java IO 类概述表

Byte Based InputByte Based OutputCharacter Based InputCharacter BasedOutput
BasicInputStreamOutputStreamReader / InputStreamReaderWriter / InputStreamWriter
ArraysByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
FilesFileInputStream / RandomAccessFileFileOutputStream / RandomAccessFileFileReaderFileWriter
PipesPipedInputStreamPipedOutputStreamPipedReaderPipedWriter
BufferingBufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
FilteringFilterInputStreamFilterOutputStreamFilterReaderFilterWriter
ParsingPushbackInputStreamPushbackReader
StringsStringReaderStringWriter
DataDateInputStreamDateOutputStream
Data-FormarttedPrintStreamPrintWriter
ObjectsObjectInputStreamObjectOutputStream
UtilitiesSequenceInputStream

Java IO 文件

在 Java 应用程序中,文件是一种常用的数据源或者存储数据的媒介。所以这一小节将会对 Java 文件的使用做一个简短的概述。

通过 Java IO 读文件

如果你需要在不同端读文件,你可以根据文件是二进制还是文本文件选择 FileInputStream 或者 FileReader。这两个类允许你从文件开始到文件末尾一次读取一个字节过着字符。或者将读取到的一个字节写入到字节数组。你不必一次性的读取整个文件,相反你可以按照顺序读取文件中的字节或者字符。

通过 Java IO 写文件

如果你需要在不同端写入,你可以根据自己写入的数据是二进制型数据还是字符 型数据选用 FileOutputStream 或者 FileWriter 。你可以一次写入一个字节或者字符到文件中,也可以直接写入字节数组或者字符数据,数据按照写入顺序存在文档中。

通过 Java IO 随机存取文件

正如上面表格所看到的,RandoAccessFile 堆文件进行随机存取。
随机存取并不意味着你可以在真正随机位置进行读写,它只是意味着你可以跳过文件中某些部分进行操作。这使得 RandomAccessFile 可以覆盖一个文件的某些部分、或者追加内容到它的末尾、或者删除它的某些内容,当然它也可以从文件中的任何位置开始读文件。


Java IO : 管道

Java IO 的管道为运行在同一个 JVM 的两个线程提供了通信能力。所以管道也可以看做数据源以及目标媒介。

通过 Java IO 创建管道

可以通过 Java IO 中 PipedOutputStream 和 PipedInputStream 创建管道。一个 PipedInputStream 流应该和一个 PipedInputStream 流相关联。一个线程通过 PipedOutputSteam 写入的数据可以被另一个线程通过相关联的 PipedInputStream读取出来。

Java IO 管道实例

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class Piped {
    public static void main(String[] args) throws IOException {
        final PipedOutputStream out = new PipedOutputStream();
        final PipedInputStream in = new PipedInputStream(out);

        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    out.write("hello world".getBytes());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    int data = in.read();
                    while (data != -1) {
                        System.out.println((char) data);
                        data = in.read();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}

你也可以使用connect()方法使之相联,PipedInputStream 和 PipedOutputStream 都拥有一个 connect() 方法。

管道和线程

当时用两个相关联的管道流时,务必将他们分配给不同线程。read() 和 write() 同时调用会导致流阻塞。这意味着如果尝试在一个线程中同时进行读和写,可能会导致死锁。

管道的替代

除了管道,一个 JVM 中不同线程之间还有许多通信方式。实际上,线程大多数情况下会传递完整的对象而非原始字节数据,但是,如果你需要在线程之间传递字节数据,Java IO 管道是一个不错的选择。


Java IO:网络

当两个进程之间建立了网络连接之后,他们的通信方式就如同操作文件一样。利用 InputStream 读取数据,利用 OutputStream 写入数据。换句话说,Java 网络 API 用来在不同进程之间建立网络连接,而 Java IO 则用来建立连接之后进行进程之间的数据交换。
基本上意味着如果你有一份能够对文件写入某些数据的代码,那么数据也可以很容易的写入到网络中去,你所需要做的就是在代码中利用 OutputStream 代替 FileOutputStream 进行数据的写入


Java IO: 字节和字符数组

03-21
<think>好的,我现在需要处理用户关于Java IO的问题。用户希望了解Java IO的概念或者解决相关问题,特别是询问教程和故障排除的方法。首先,我得回顾一下Java IO基础知识,确保自己理解正确,然后组织回答的结构。 首先,Java IO主要涉及输入输出流,用于处理数据的读写。核心包是java.io,里面有很多类,比如File、InputStream、OutputStream、Reader、Writer等。用户可能需要知道这些类的层次结构和使用方法。 接下来,常见的IO操作包括文件读写、网络通信、序列化等。比如,FileInputStream和FileOutputStream用于字节流,而FileReader和FileWriter用于字符流。缓冲流(BufferedInputStream等)可以提高效率,这部分应该提到。 然后,异常处理是Java IO中很重要的一部分,比如IOException,需要正确处理try-with-resources来自动关闭流,避免资源泄漏。这部分用户可能在故障排除时会遇到问题,比如未正确关闭流导致文件锁定或资源耗尽。 关于教程,Oracle的官方文档是权威资源,应该引用。比如引用[3]提到了JSP的信息,但用户需要的是IO的教程,可能需要检查是否有其他引用相关。不过用户给出的引用中,引用[1]是关于JDK 7的故障排除工具,可能和调试IO问题相关,比如使用jdb进行调试。引用[5]提到字节码信息,可能和IO关系不大,但故障排除时可能需要查看异常堆栈,这可能涉及字节码或类加载的问题。 对于故障排除,常见问题包括文件路径错误、权限问题、字符编码不一致导致的乱码,或者流未正确关闭。比如,文件找不到可能是因为相对路径的当前工作目录与预期不符,或者文件被其他进程占用。这时候需要检查路径是否正确,是否有读取权限,使用绝对路径测试,或者使用工具如Process Explorer查看文件句柄。 此外,NIO(New IO)在Java 1.4引入,提供了非阻塞IO和通道等高效处理方式,用户可能也需要了解NIO和传统IO的区别,比如使用Channel和Buffer的方式,或者使用Files类简化操作。 在组织回答时,需要分步骤讲解,比如先介绍核心概念,然后常见操作,接着是故障排除技巧,最后提供学习资源和相关工具。同时,生成的问题要围绕Java IO的进一步学习,比如NIO、性能优化、常见异常处理等。 需要确保回答中的LaTeX格式正确,比如类名和方法名可能需要用代码块,而数学表达式则用$...$。例如,文件路径的转义可能需要讨论,比如在字符串中使用反斜杠需要转义,写成`"C:\\\\path\\\\to\\\\file"`,但这里可能不需要数学表达式,所以可能不需要用到LaTeX的公式部分。 检查用户提供的引用,是否有与IO相关的资源。引用[4]是关于安卓USB驱动的,可能不相关。引用[2]关于反射,可能也不直接相关,但故障排除时可能会用到反射来检查类路径或资源加载,这可能间接相关,但可能不需要特别提到。 总结回答结构: 1. Java IO核心概念:流、字节流与字符流、缓冲流、NIO。 2. 常见操作:文件读写示例代码。 3. 故障排除:常见问题及解决方法,如路径、权限、编码、资源泄漏。 4. 学习资源:官方教程、工具(如jdb)。 5. 相关问题:如何选择IO和NIO,处理大文件,字符编码问题,关闭资源方法,常见异常处理。 需要确保回答中的引用正确,比如引用[1]关于JDK工具,可能在故障排除时使用jdb或者jstack等工具分析问题,可以提到。引用[3]的链接虽然是JSP,但Oracle的Java EE教程可能包含IO相关内容,需要检查链接是否有效,但用户提供的链接可能已失效,需要注意。不过用户给出的引用可能有误,比如引用[3]的网址是javaee.github.io,可能是正确的,但需要确认是否有IO相关部分。 最后,代码示例需要正确,比如使用try-with-resources来读取文件,展示正确的异常处理方式。同时,确保所有技术术语准确,例如InputStreamReader处理字符编码,BufferedReader提高读取效率。 可能的问题点:用户提供的引用中是否有直接关于Java IO的内容?引用[1]提到JDK工具,可以用于调试IO问题,比如使用jdb调试应用程序,或者在出现IO异常时分析线程状态。引用[5]关于字节码信息,可能与IO问题关系不大,但类加载时找不到资源文件可能会涉及,需要看具体情况。 因此,在故障排除部分,可以建议使用JDK工具如jstack检查是否有线程阻塞在IO操作,或者使用jdb进行调试,引用[1]。同时,处理资源泄漏时,可以使用try-with-resources来自动关闭流,这是Java 7的特性,可能需要提到。 综上所述,回答的结构应该是先介绍核心概念,然后示例代码,接着故障排除步骤,引用相关资源,最后生成相关问题。</think>### Java IO 概念与问题排查指南 #### 一、核心概念 Java IO(输入输出)用于处理数据读写,核心包为 `java.io`,主要分为两类: 1. **字节流**:处理二进制数据,基类为 `InputStream` 和 `OutputStream`,例如 `FileInputStream` 和 `BufferedOutputStream`。 2. **字符流**:处理文本数据,基类为 `Reader` 和 `Writer`,例如 `FileReader` 和 `BufferedWriter`。 3. **NIO(New IO)**:Java 1.4 引入,通过 `Channel` 和 `Buffer` 实现高效非阻塞操作,例如 `Files.readAllLines()`[^1]。 #### 二、常见操作示例 1. **文件读取(字符流)**: ```java try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } ``` 2. **文件写入(字节流)**: ```java try (OutputStream out = new BufferedOutputStream(new FileOutputStream("output.dat"))) { out.write("Hello".getBytes()); } catch (IOException e) { e.printStackTrace(); } ``` #### 三、故障排查技巧 1. **文件路径问题** - 使用绝对路径或检查工作目录:`System.getProperty("user.dir")`。 - 路径分隔符兼容性:使用 `File.separator` 替代硬编码的 `/` 或 `\`。 2. **权限与资源占用** - 确认文件可读/写:`file.canRead()` 和 `file.canWrite()`。 - 确保流正确关闭:使用 **try-with-resources**(Java 7+)避免资源泄漏。 3. **字符编码问题** - 指定编码格式:例如 `new InputStreamReader(new FileInputStream("file.txt"), StandardCharsets.UTF_8)`。 4. **调试工具** - 使用 `jdb`(Java Debugger)追踪 IO 异常堆栈[^1]。 - 通过 `jstack` 分析线程阻塞(如网络 IO 超时)。 #### 四、学习资源 1. **官方教程** - [Oracle Java IO 教程](https://docs.oracle.com/javase/tutorial/essential/io/)(涵盖基础与 NIO)。 2. **进阶内容** - Java NIO.2(Java 7+)的 `Path` 和 `Files` 类[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值