Java IO操作详解

article/2025/10/5 14:15:11

在Java编程中,IO(输入输出)是重要的组成部分,Java应用常常需要从外界输入数据或者把数据输出到外界。

Java IO的核心用一句话概括:抽象类或接口之中的抽象方法会根据实例化子类的不同,会完成不同的功能。所有的IO操作都在java.io包之中进行定义,而且整个java.io包实际上就是五个类和一个接口:
(1)五个类:File、InputStream、OutputStream、Reader、Wirter;
(2)一个接口:Serializable。

一、文件操作类File

在整个java.io包之中,File类是唯一的一个与文件本身操作有关的类,所谓的文件本身指的是:文件的创建、删除、重命名、取得文件大小、修改日期。

1、文件类对象实例化

如果要想使用File类操作文件的话,那么肯定要通过构造方法实例化File类对象,而实例化File类对象的过程之中主要使用以下两种构造方法:

(1)public File(String pathname);//主要在Java EE的开发之中

(2)public File(File parent, String child);//主要在Android开发之中

2、文件的基本操作

文件的基本操作,主要有两种功能:创建和删除
(1)创建文件:

public boolean createNewFile() throws IOException;

(2)删除文件:

public boolean delete();

范例:

import java.io.File;public class TestDemo {public static void main(String[] args) throws Exception {File file = new File("D:\\demo.txt"); // 文件的路径if (file.exists()) { // 文件存在file.delete(); // 删除文件} else { // 文件不存在file.createNewFile(); // 创建新文件}}
}

本程序操作就表示文件如果存在则删除,如果不存在,则创建一个新的文件,此时基本功能是实现了,不过这个程序此时却存在问题:

(1)关于路径分隔符

在windows操作系统之中,使用“\”作为路径分隔符,而在linux系统下使用“/”作为路径的分隔符,而从实际的开发而言,大部分情况下都会在windows中做开发,而后将项目部署到linux下,那么此时,路径的分隔符都需要进行修改,这样实在是过于麻烦,为此在File类之中提供了一个常量:

public static final String separator

(按照Java的命名规范来讲,对于全局常量应该使用大写字母的方式定义,而此处使用的是小写,是由Java的发展历史所带来的问题)。

所以以上程序实例化File类对象修改为:

 File file = new File("D:" + File.separator + "demo.txt"); // 文件的路径

(2)之前进行文件创建的时候都是在根路径下创建完成的,如果说现在要创建的文件有目录呢?
例如,现在要创建一个d:\hellodemo\my\test\demo.txt文件,而此时在执行程序的时候hellodemo目录不存在,这个时候执行的话就会出现错误提示:

Exception in thread "main" java.io.IOException: 系统找不到指定的路径。

因为现在目录不存在,所以不能创建,那么这个时候必须要首先判断要创建文件的父路径是否存在,如果不存在应该创建一个目录,之后再进行文件的创建,而要想完成这样的操作,需要以下几个方法的支持:
①找到一个指定文件的父路径:

public File getParentFile();

②创建目录:

public boolean mkdirs();

范例:

import java.io.File;
public class TestDemo {public static void main(String[] args) throws Exception {File file = new File("D:" + File.separator + "hellodemo"+ File.separator + "my" + File.separator + "test"+ File.separator + "demo.txt"); // 文件的路径if (!file.getParentFile().exists()) { // 父路径不存在file.getParentFile().mkdirs(); // 创建目录}if (file.exists()) { // 文件存在file.delete(); // 删除文件} else { // 文件不存在file.createNewFile(); // 创建新文件}}
}

以后在任何的java.io.File类开发的过程之中,都一定要考虑文件目录的问题。

3、获取文件的基本信息

除了以上的常用的方法之外,在File类之中还可以通过以下的方法取得一些文件的基本信息:

(1)取得文件的名称:

public String getName();

(2)给定的路径是否是文件夹:

public boolean isDirectory();

(3)给定的路径是否是文件:

public boolean isFile();

(4)是否是隐藏文件:

public boolean isHidden();

(5)文件的最后一次修改日期:

public long lastModified();

(6)取得文件大小:

public long length();

是以字节为单位返回的。

二、字节流与字符流

使用File类执行的所有操作都是针对于文件本身,但是却没有针对于文件的内容,而要进行文件内容操作就需要通过Java之中提供的两组类完成:

(1)字节操作流:OutputStream、InputStream;
(2)字符操作流:Writer、Reader。

但是不管是字节流还是字符流的操作,本身都表示资源操作,而执行所有的资源操作都会按照如下的几个步骤进行,下面以文件操作为例(对文件进行读、写操作):

(1)如果要操作的是文件,那么首先要通过File类对象找到一个要操作的文件路径(路径有可能存在,有可能不存在,如果不存在,则要创建路径);
(2)通过字节流或字符流的子类为字节流或字符流的对象实例化(向上转型);
(3)执行读 / 写操作;
(4) 最后一定要关闭操作的资源(数据流属于资源操作,资源操作必须关闭)

1、字节流

OutputStream和InputStream是字节流的两个顶层父类。让他们提供了输出流类和输入流类通用API,字节流一般用于读写二进制数据,如图像和声音数据。

[1]输出流:OutputStream

java.io.OutputStream主要的功能是进行字节数据的输出的,这个类的定义如下:

public abstract class OutputStream
extends Object
implements Closeable, Flushable

发现OutputStream类定义的时候实现了两个接口:Closeable、Flushable,这两个接口的定义如下:

(1)Closeable (JDK 1.5推出):

public interface Closeable extends AutoCloseable {public void close() throws IOException;
}

(2)Flushable(JDK 1.5推出):

public interface Flushable {public void flush() throws IOException;
}

对于OutputStream类而言发现其本身定义的是一个抽象类(abstract class),按照抽象类的使用原则来讲,需要定义抽象类的子类,而现在如果要执行的是文件操作,则可以使用FileOutputStream子类完成,如果按照面向对象的开发原则,子类要为抽象类进行对象的实例化,而后调用的方法以父类中定义的方法为主,而具体的实现找实例化这个父类的子类完成,也就是说在整个的操作之中,用户最关心的只有子类的构造方法:

(1)实例化FileOutputStream(新建数据):

public FileOutputStream(File file) throws FileNotFoundException;

(2)实例化FileOutputStream(追加数据):

public FileOutputStream(File file, boolean append)
throws FileNotFoundException

当取得了OutputStream类的实例化对象之后,下面肯定要进行输出操作,在OutputStream类之中定义了三个方法:

(1)输出单个字节数据:

public abstract void write(int b) throws IOException;

(2)输出一组字节数据:

public void write(byte[] b) throws IOException;

(3)输出部分字节数据:

public void write(byte[] b, int off, int len) throws IOException;

范例:使用OutputStream向文件之中输出数据,输出路径:d:\demo\test.txt

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;public class TestDemo {public static void main(String[] args) throws Exception {//第一步:定义文件路径File file = new File("D:"+File.separator + "demo"+ File.separator + "test.txt");if(!file.getParentFile().exists()){file.getParentFile().mkdirs();}//第二步:实例化输出流OutputStream output = new FileOutputStream(file);String data = "hello world !\r\nhello world !\r\nhello world !\r\nhello world !";// 第三步:输出数据,要将数据变为字节数组输出output.write(data.getBytes());//第四步:关闭资源output.close();}
}

运行结果:

1

在整个的文件输出过程之中可以发现,如果现在要输出的文件不存在,那么会出现自动创建文件的情况,并且如果重复执行以上的代码,会出现新的内容覆盖掉旧内容的操作,所以下面可以使用FileOutputStream类的另外一个构造方法进行数据的追加:

OutputStream output = new FileOutputStream(file, true);

如果说现在不想全部内容输出,也可以使用另外一个write()方法部分内容输出:

output.write(data.getBytes(), 0, 5);

运行结果:

w

在OutputStream类之中所有的数据都是以字节数据为主的。

[2]输入流:InputStream

如果现在要从指定的数据源之中读取数据,使用InputStream,这个类的定义如下:

public abstract class InputStream
extends Object
implements Closeable

既然InputStream为抽象类,那么这个抽象类要使用就必须有子类,现在是通过文件读取内容,肯定使用FileInputStream子类进行操作,与OutputStream类的使用一样,对于FileInputStream也只关心构造方法:

public FileInputStream(File file) throws FileNotFoundException;

在InputStream类之中,定义了三个读取数据的操作方法:
(1)读取单个字节:

public abstract int read() throws IOException;

注意:每次执行read()方法都会读取一个数据源的指定数据,如果现在发现已经读取到了结尾返回-1;

(2)将读取的数据保存到字节数组中:

public int read(byte[] b) throws IOException;

注意:如果现在要读取的数据小于byte的数据,这个时候read()方法的返回值int返回的是数据个数,如果数据已经读完了,则这个时候的int返回的是-1

(3)将读取的数据保存在部分字节数组中:

public int read(byte[] b, int off, int len) throws IOException;

范例:一次性全部读取数据进来

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;public class TestDemo {public static void main(String[] args) throws Exception {//第一步:定义文件路径File file = new File("D:" + File.separator + "demo" + File.separator + "test.txt"); // 定义文件路径if (file.exists()) { // 文件存在则可以读取//第二步:实例化输入流InputStream input = new FileInputStream(file);//第三步:读取数据到字节数组byte data[] = new byte[1024]; // 假设要读的长度是1024int len = input.read(data); // 读取数据,返回读取个数//第四步:关闭资源input.close(); System.out.println("读取的数据是:【" + new String(data, 0, len) + "】");}}
}

范例:单个字节读取

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;public class TestDemo {public static void main(String[] args) throws Exception {File file = new File("D:" + File.separator + "demo" + File.separator + "test.txt"); // 定义文件路径if (file.exists()) { // 文件存在则可以读取InputStream input = new FileInputStream(file);byte data[] = new byte[1024]; // 假设要读的长度是1024int foot = 0; // 操作data数组的脚标int temp = 0;// 第一步:temp = input.read(),读取一个单个字节,并且将内容给temp变量// 第二步:temp != -1,将接收到的temp的数值判断是否为-1,如果为-1则表示退出循环,如果不是,则保存数据while ((temp = input.read()) != -1) {data[foot++] = (byte) temp; // 保存读取进来的单个字节}input.close(); // 关闭System.out.println("读取的数据是:【" + new String(data, 0, foot) + "】");}}
}

在今后开发中,都会使用以上的while循环方式进行数据的读取。

2、字符流

[1]字符输出流:Writer

Writer类也是一个专门用于数据输出的操作类,这个类定义:

public abstract class Writer
extends Object
implements Appendable, Closeable, Flushable

在Wirter类之中比OutputStream类最为方便的一点就是其可以直接使用String型数据输出,并且不再需要将其变为字节数组了。而Writer类本身也是一个抽象类,那么如果要使用依然要依靠它的子类,尤其是现在操作的是文件,使用FileWriter子类。
在Wirter类之中定义的write()方法都是以字符数据为主,但是在这些方法之中,只关心一个:输出一个字符串:

public void write(String str) throws IOException;

范例:使用Wirter类进行内容的输出

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;public class TestDemo {public static void main(String[] args) throws Exception {File file = new File("D:" + File.separator + "demo" + File.separator + "test.txt"); // 定义文件路径if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();// 创建父目录}Writer out = new FileWriter(file);String data = "Hello World .";out.write(data); // 直接输出字符串out.close(); // 关闭输出}
}

运行结果:

w

从输出来讲,Wirter类的输出要比OutputStream类更加的方便。

[2]字符输入流:Reader

Reader是进行字符数据读取的操作类,其定义:

public abstract class Reader
extends Object
implements Readable, Closeable

在Writer类之中存在了直接输出一个字符串数据的方法,可是在Reader类之中并没有定义这样的方法,只是定义了三个按照字符读取的方法,为什么会这样?
因为在使用OutputStream输出数据的时候,其程序可以输出的大小一定是程序可以承受的数据大小,那么如果说使用InputStream读取的时候,可能被读取的数据非常的大,那么如果一次性全读进来了,就会出现问题,所以只能一个一个的进行读取。

在Reader类里也提供了一系列的read方法,其中一个:
读取内容到字符数组:

public int read (char[] cbuf) throws IOException;

注意:返回值表示读取的数据长度,如果已经读取到结尾。返回-1。

Reader依然是抽象类,那么如果从文件读取,依然使用FileReader类。

import java.io.File;
import java.io.FileReader;
import java.io.Reader;public class TestDemo {public static void main(String[] args) throws Exception {File file = new File("D:" + File.separator + "demo" + File.separator + "test.txt"); // 定义文件路径if (file.exists()) {Reader in = new FileReader(file); // 字符输入流char data[] = new char[1024]; // 开辟数组int len = in.read(data); // 读取数据in.close();System.out.println("读取数据内容:【" + new String(data, 0, len) + "】");}}
}

三、字节流与字符流的区别

通过以上的代码演示,现在可以发现,对于字节流和字符流可以完成类似的功能,那么在开发之中使用那一种呢?两者的区别:

字节流在进行IO操作的时候,直接针对的是操作的数据终端(例如:文件),而字符流操作的时候不是直接针对于终端,而是针对于缓存区(理解为内存)操作,而后由缓存取操作终端(例如:文件),属于间接操作,按照这样的方式,如果说在使用字节流的时候不关闭最后的输出流操作,也可以将所有的内容进行输出,而字符输出流的时候如果不关闭,则意味着缓冲区之中的内容不会被输出,当然,这个时候可以由用户自己去调用flush()方法进行强制性的手工清空:

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
public class TestDemo {public static void main(String[] args) throws Exception {File file = new File("D:" + File.separator + "demo"+ File.separator + "test.txt"); // 定义文件路径if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();// 创建父目录}Writer out = new FileWriter(file);String data = "Hello World .";out.write(data) ;   // 直接输出字符串out.flush() ;   // 清空缓冲区}
}

对于电脑磁盘或者是网络数据传输上,使用最多的数据类型都是字节数据,包括图片、音乐、各种可执行程序也都是字节数据,很明显,字节数据要比字符数据更加的广泛,但是在进行中文处理的过程之中,字符流又要比字节流方便许多,所以如果要使用的话,首先考虑的是字节流(还有一个原因是因为字节流和字符流的代码形式类似),如果有中文处理的问题,才会考虑使用字符流。

四、综合实例:文件拷贝

1、实现思路:
如果要想实现文件的复制那么肯定要使用的是字节流,因为文件有可能是图片,而对于这样的操作有两种实现方式:
(1)方式一:将要复制的文件内容全部读取到内存之中,而后将所有内容一次输出到目标文件之中;
(2)方式二:采用边读边写的方式一块一块的进行文件的拷贝。
很明显,使用方式二会更加的方便,因为如果要复制的文件很大,那么方式一是不可能在内存之中装如此只大的数据量,所以全部读取是不太可能的。

需要拷贝的文件如下,约47M:

这里写图片描述

2、拷贝程序:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;public class TestDemo {public static void main(String[] args) throws Exception {File inFile = new File("D:" + File.separator + "demo"+ File.separator + "test.zip"); // 定义文件路径File outFile = new File("D:" + File.separator + "demo"+ File.separator + "test2.zip"); // 定义文件路径long start = System.currentTimeMillis();if (!inFile.exists()) { // 源文件不存在System.out.println("源文件不存在!");System.exit(1); // 程序退出}if(!outFile.getParentFile().exists()){outFile.getParentFile().mkdirs();}InputStream input = new FileInputStream(inFile);OutputStream output = new FileOutputStream(outFile);int temp = 0;//保存每次读取的个数byte data[] = new byte[4096]; // 每次读取4096字节while ((temp = input.read(data)) != -1) { // 将每次读取进来的数据保存在字节数组里,并返回读取的个数output.write(data, 0, temp); // 输出数组}long end = System.currentTimeMillis();System.out.println("拷贝完成,所花费的时间:" + (end - start) + "毫秒");input.close();output.close();}
}

运行结果:

拷贝完成,所花费的时间:125毫秒

查看文件:

3


http://chatgpt.dhexx.cn/article/wpVkehf7.shtml

相关文章

C++中的IO操作

IO操作 了解C中的IO操作C中的二进制读写&#xff0c;文本读写C中的stringstream类与I/O操作中对<<与>>运算符的重载 了解C中的IO操作 我们学习IO操作&#xff0c;就要先了解什么是IO操作&#xff0c;从名字中就可以看出来&#xff0c;I,O就代表着输入输出的操作&a…

处理器的IO操作

文章目录 1 IO空间的分类1.1 内存映射IO空间1.2 独立IO空间 2 处理器操作外设的基本方式3 内存映射IO空间的硬件设计3.1 硬件设计的关键3.2 设备地址映射示例 1 IO空间的分类 处理器与外设之间的数据通信通过IO操作完成。 1.1 内存映射IO空间 对于内存映射IO空间&#xff1a…

文件IO操作

目录 一.文件的操作 1.构造方法 2.常用方法 3.文件的绝对路径和相对路径 1.绝对路径 2.相对路径 4.注意事项 5.File类的方法使用例子&#xff08;递归遍历指定目录下的所有文件&#xff09; 二. 输入流 1.InputStream&#xff08;输入流&#xff09; &#xff08;1&a…

Linux 文件IO操作

概述 本片文章将会主要介绍四个IO函数&#xff1a;开关读写 open函数 open 函数的输入参数是 open(char* ,flag ,[mode])第一个参数表示的是打开文件的路径文件名第二个参数表示的是打开的方式&#xff0c;见下表 打开方式描述O_RDONLY只读O_WRONLY只写O_RDWR读写O_CREAT创建…

简述IO操作

IO java.io中最主要的五个类就是InputStream、OutputStream、Reader、Writer、File。 从传输方式角度来说&#xff0c;可以将IO分类为&#xff1a; 一&#xff1a;File File类的对象主要用来获取文件本身的一些信息&#xff0c;例如文件所在的目录、文件的长度或文件读写权…

Java文件IO操作及案例

文章目录 一. 文件概述1. 狭义和广义上的文件2. 文件的分类3. 文件的路径 二. 针对文件系统的操作1. File类的属性和构造2. File类的获取操作3. File类的判断操作4. 文件的创建和删除5. 其他的常用方法 三. 对文件内容进行读写1. IO流对象2. 文件的读操作3. 文件的写操作4. Sca…

java IO操作

系列文章目录 第一章 万事万物皆对象 第二章 java构造器 第三章 java访问权限 第四章 java初始化 第五章 java继承 第六章 java重载与重写 第七章 java接口和抽象类 第八章 java数组 第九章 java内部类 第十章 java时间操作 第十一章 final关键字 第十二章 java字符串 第十三章…

Linux基础 IO操作

一、IO接口的基本认识与使用 在c语言中&#xff0c;我们对文件用fopen&#xff0c;fread&#xff0c;fwrite&#xff0c;fclose等等c语言标准库函数来进行操作&#xff0c;实际上这些库函数是对系统调用接口的一个封装&#xff0c;目的是操作简单&#xff0c;方便编程。 以下…

Java中的IO操作

IO 操作是我以前不太理解的操作。总是觉得很神奇&#xff0c;然后一脸懵逼。今天终于鼓起勇气&#xff0c;认真的学习IO方面的知识。有理解不妥当或者不正确的地方&#xff0c;还请各位大佬指正。 一、java的io发生在哪&#xff1f; 这个问题&#xff0c;我们必须首先明确下。…

基础IO-文件IO操作

目录 1.C语言文件IO相关操作&#xff08;库函数IO接口&#xff09; 2. 系统调用IO接口 1.C语言文件IO相关操作&#xff08;库函数IO接口&#xff09; fopen--打开文件&#xff0c;返回一个文件的操作句柄&#xff0c;有了句柄才能对指定的文件进行操作。 FILE *fopen(char *p…

Java文件IO操作

目录 一、了解什么是文件 狭义的文件&#xff1a; 广义的文件&#xff1a; 二、文件的路径 ①文件的绝对路径 ②文件的相对路径 三、Java对于文件的操作 File类的构造方法 File类的普通方法 四、对于文件的内容操作 ①FileInputStream&#xff08;文件输入流&#xf…

IO操作

一、简介 IO流是用来处理设备之间的数据传输的&#xff0c;数据一般储存在设备上 设备&#xff1a;硬盘&#xff0c;光盘&#xff0c;内存等等&#xff0c;内存是临时储存的 Java对数据的操作是采用流的方式 按照操作的数据分为&#xff1a;字节流和字符流 暗照流向&#x…

Java基础--IO操作

一、IO原理及分类 一、IO原理 1、I/O是Input/Output的缩写&#xff0c;I/O技术是非常实用的技术&#xff0c;用于处理设备之间的数据传输&#xff0c;如读写文件&#xff0c;网络通信等。 2、java程序中对于数据的输入/输出操作一般都是以流的方式进行 3、java.io包下提供各…

关于I/O操作

https://blog.csdn.net/deram_boy/article/details/51191425 提及这个&#xff0c;就想到了各种文件操作&#xff0c;这种流&#xff0c;什么reader 啊&#xff0c; writer啊&#xff0c;buffer啊&#xff0c;file啊。但是综合的东西与总结&#xff0c;只是曾经了解。因为工作…

IO操作概念

IO&#xff1a;输入输出&#xff0c;对程序的输入与输出 文件&#xff1a;一组有关数据的集合 文件名&#xff1a;这组数据的名字 linux系统中所有文件均属于文件&#xff08;通过文件系统进行管理&#xff09; 按类型分类&#xff1a; 1、普通文件 &#xff08;…

I/O操作

前言 I/O操作即操作存储器&#xff0c;所以想了解I/O操作&#xff0c;需要了解一点存储器相关知识点。 计算机存储器 存储器是计算机的核心部件之一&#xff0c;在完全理想的状态下&#xff0c;存储器应该要同时具备以下三种特性&#xff1a; &#xff08;1&#xff09;速度…

操作系统_04_IO相关(个人总结)

声明: 1. 本文为我的个人复习总结, 并非那种从零基础开始普及知识 内容详细全面, 言辞官方的文章 2. 由于是个人总结, 所以用最精简的话语来写文章 3. 若有错误不当之处, 请指出 软硬链接 软链接(快捷方式): 删除原文件时, 软链接则失效 硬链接…

gcc 命令

gcc 命令 GCC 编译器 gcc 命令格式 gcc 选项 文件名字主要选项 -c&#xff1a; 只编译不链接为可执行文件&#xff0c;编译器将输入的.c 文件编译为.o 的目标文件。-o&#xff1a; <输出文件名>用来指定编译结束以后的输出文件名&#xff0c;如果不使用这个选项的话 G…

Ubuntu Linux gcc的常用命令

目录 一、gcc简介 二、简单的gcc编译 1 预处理 2 编译为汇编语言代码 3 汇编 4 连接 三、多个程序文件的编译 四、检查错误 五、连接库文件 1 编译成可执行文件 2 链接 3 强制链接时使用静态链接库 六、总结 一、gcc简介 Linux系统下的Gcc&#xff08;GNU C Compi…

Linux GCC 编译详解

文章目录 一、GCC 编译器简介二、GCC 工作流编程语言的发展GCC 工作流程gcc 和 g 的区别 三、使用 GCC 编译GCC 编译格式GCC 编译流程多个源文件编译 一、GCC 编译器简介 首先&#xff0c;什么是编译器呢&#xff1f; 我们可以使用编辑器&#xff08;如 linux 下的 vi、window…