java IO

本文详细介绍了Java中的IO流概念,包括输入输出流、字符流和字节流的区别,并通过实例演示了如何使用这些流来读写文件。此外,还介绍了如何使用RandomAccessFile实现文件的随机读写。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java流

Java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流.

输入流和输出流

根据数据的输入、输出方向的不同对而将流分为输入流和输出流。

  1. 输入流:InputStream和Reader
  2. 输出流:OutputStream和Writer

字符流和字节流

流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:

  1. 字节流:InputStream和OutputStream(数据流中最小的数据单元是字节)
  2. 字符流:Reader和Writer(数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。)

Java 字节流与字符流的区别 

字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件;

以写文件的操作为主进行比较,在操作时字节流和字符流的操作完成之后都不关闭输出流。 

使用字节流不关闭执行:文件中也依然存在了输出的内容,证明字节流是直接操作文件本身的;

使用字符流不关闭执行:程序运行后会发现文件中没有任何内容,这是因为字符流操作时使用了缓冲区,而   在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭,则缓冲区中的内容是无法输出的,所以得出结论:字符流使用了缓冲区,而字节流没有使用缓冲区。

什么叫缓冲区?

可以简单地把缓冲区理解为一段特殊的内存。

某些情况下,如果一个程序频繁地操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。

在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区暂存数据。 

Java流类的类结构图 

 

Java IO的基本用法 

 Java IO :字节流

字节流对应的类应该是InputStreamOutputStream,而在我们实际开发中,我们根据不同的媒介类型选用相应的子类来处理

例1,用字节流写文件

public static void writeByteToFile(){
            String hello= new String( "hello word!");
             byte[] byteArray= hello.getBytes();
            File file= new File( "E://tmp//writeByteToFile.txt");
             //因为是用字节流来写媒介,所以对应的是OutputStream
             //又因为媒介对象是文件,所以用到子类是FileOutputStream
            OutputStream os;
            try {
                os = new FileOutputStream( file);
                os.write( byteArray);
                 os.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
             
      }

例2,用字节流读文件

 public static void readByteFromFile(){
            File file= new File( "E://tmp//writeByteToFile.txt");
             byte[] byteArray= new byte[( int) file.length()];
             //因为是用字节流来读媒介,所以对应的是InputStream
             //又因为媒介对象是文件,所以用到子类是FileInputStream
            InputStream is;
            try {
                is = new FileInputStream( file);
                 int size= is.read( byteArray);
                    System. out.println( "大小:"+size +";内容:" +new String(byteArray));
                     is.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
      }

Java IO :字符流

例3,用字符流读文件

 public static void readCharFromFile() {
            File file= new File( "E://tmp//writeByteToFile.txt");
             //因为是用字符流来读媒介,所以对应的是Reader
             //又因为媒介对象是文件,所以用到子类是FileReader
            Reader reader;
            try {
                reader = new FileReader( file);
                 char [] byteArray= new char[( int) file.length()];
                 int size= reader.read( byteArray);
                System. out.println( "大小:"+size +";内容:" +new String(byteArray));
                 reader.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
      }

例4,用字符流写文件

     public static void writeCharToFile(){
            String hello= new String( "wahahahahahahaha");
            File file= new File( "E://tmp//writeByteToFile.txt");
             //因为是用字符流来读媒介,所以对应的是Writer,又因为媒介对象是文件,所以用到子类是FileWriter
            Writer os;
            try {
                os = new FileWriter( file);
                 os.write( hello);
                 os.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
      }

随机读取File文件

通过上面的例子我们已经知道,我们可以用FileInputStream(文件字符流)或FileReader(文件字节流)来读文件,这两个类可以让我们分别以字符和字节的方式来读取文件内容,但是它们都有一个不足之处,就是只能从文件头开始读,然后读到文件结束。

但是有时候我们只希望读取文件的一部分,或者是说随机的读取文件,那么我们就可以利用RandomAccessFile。RandomAccessFile提供了seek()方法,用来定位将要读写文件的指针位置,我们也可以通过调用getFilePointer()方法来获取当前指针的位置,具体看下面的例子:

例5,随机写入文件

 public static void randomAccessFileWrite() {
         // 创建一个RandomAccessFile对象
        RandomAccessFile file;
        try {
            file = new RandomAccessFile( "E://tmp//writeByteToFile.txt", "rw");
             // 通过seek方法来移动读写位置的指针
             file.seek(10);
             // 获取当前指针
             long pointerBegin = file.getFilePointer();
             // 从当前指针位置开始写
             file.write( "HELLO WORD!HHHHHHH".getBytes());
             long pointerEnd = file.getFilePointer();
            System. out.println( "pointerBegin:" + pointerBegin + "\n" + "pointerEnd:" + pointerEnd + "\n" );
             file.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
  }

例6,随机读取文件

 public static void randomAccessFileRead() {
         // 创建一个RandomAccessFile对象
        RandomAccessFile file;
        try {
            file = new RandomAccessFile( "E://tmp//writeByteToFile.txt", "rw");
             // 通过seek方法来移动读写位置的指针
             file.seek(10);
             // 获取当前指针
             long pointerBegin = file.getFilePointer();
             // 从当前指针开始读
             byte[] contents = new byte[1024];
             file.read( contents);
             long pointerEnd = file.getFilePointer();
            System. out.println( "pointerBegin:" + pointerBegin + "\n" + "pointerEnd:" + pointerEnd + "\n" + new String(contents));
             file.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
  }

参考文献链接: http://blog.csdn.net/suifeng3051/article/details/48344587

 

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、付费专栏及课程。

余额充值