目录
一、IO概述
1.什么是IO
Java中I/O操作主要是指使用java.io
包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。
我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为输入input
和输出output
,即流向内存是输入流,流出内存的输出流。
2.IO的分类
根据数据的流向分为:输入流和输出流。
- 输入流 :把数据从
其他设备
上读取到内存
中的流。 - 输出流 :把数据从
内存
中写出到其他设备
上的流。
格局数据的类型分为:字节流和字符流。
- 字节流 :以字节为单位,读写数据的流。
- 字符流 :以字符为单位,读写数据的流。
3.父类
4.操作 IO流的步骤
核心步骤如下:
- 建立联系
- 选择流
- 操作:写出读取
- 释放资源(程序中打开的文件 IO 资源不属于内存中的资源,垃圾回收无法回收,需要显示关闭。)
二、字节流
1.一切皆为字节
一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。
2.字节输入流【InputStream】
java.io.InputStream
抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入流的基本共性功能方法。
public void close()
:关闭此输入流并释放与此流相关联的任何系统资源。public abstract int read()
: 从输入流读取数据的下一个字节。public int read(byte[] b)
: 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
close方法,当完成流的操作时,必须调用此方法,释放系统资源。
1)FileInputStream类
java.io.FileInputStream
类是文件输入流,从文件中读取字节。
构造方法:
FileInputStream(File file)
: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。FileInputStream(String name)
: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。
当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出FileNotFoundException
。
读操作:
/**
* 读取字节
*/
public class InputStream001 {
public static void main(String[] args) throws IOException {
//建立连接
File file = new File("F:\\输入输出流\\a.txt");
// 选择流 流一定要和某个资源(文件)对接
FileInputStream fis = new FileInputStream(file);
// 读取(操作)每次读一个,当读到最后一个时,会返回-1
//int i = fis.read();
int data;
while((data = fis.read())!= -1){
System.out.println((char)data);
}
//关闭资源
fis.close();
}
}
/**
* 使用字节数组读取
*/
public class InputStream002 {
public static void main(String[] args) throws IOException {
//建立连接
File file = new File("F:\\输入输出流\\a.txt");
//选择流
FileInputStream fis = new FileInputStream(file);
//读取 一些
byte[] bytes = new byte[1024];
// 读取多个数据放入 byte[] 返回实际读取的数据个数,当返回的实际个数是-1表示文件读取结束
int realLen = fis.read(bytes);
while(realLen!=-1){
String s = new String(bytes, 0, realLen, "GBK");
System.out.println(s);
//realLen是变化的,每次放一个,读一个
realLen = fis.read();
}
//释放资源
fis.close();
}
}
3.字节输出流【OutputStream】
java.io.OutputStream
抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法
public void close()
:关闭此输出流并释放与此流相关联的任何系统资源。public void flush()
:刷新此输出流并强制任何缓冲的输出字节被写出。public void write(byte[] b)
:将 b.length字节从指定的字节数组写入此输出流。public void write(byte[] b, int off, int len)
:从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。public abstract void write(int b)
:将指定的字节输出流。
close方法,当完成流的操作时,必须调用此方法,释放系统资源。
1)FileOutputStream类
java.io.FileOutputStream
类是文件输出流,用于将数据写出到文件。
构造方法:
public FileOutputStream(File file)
:创建文件输出流以写入由指定的 File对象表示的文件。public FileOutputStream(String name)
: 创建文件输出流以指定的名称写入文件。
写操作:
public class OutputStream001 {
public static void main(String[] args) throws IOException {
//建立连接
File file = new File("F:\\输入输出流\\w1.txt");
//选择流
OutputStream os = new FileOutputStream(file);
//写操作
os.write(97);//a 写出字节
os.write(new byte[]{98,99,100});//写出字节数组
String str = "\n锄禾日当午,码农真辛苦,一段小程序,一写一上午";//写出字符串
byte[] bytes = str.getBytes();
os.write(bytes);
byte[] b = "abcde".getBytes();
// 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。
os.write(b,2,2);//写出指定长度的字符串 cd
//刷新
os.flush();
//释放资源
os.close();
}
}
2)数据追加续写
这两个构造方法,参数中都需要传入一个boolean类型的值,true
表示追加数据,false
表示清空原有数据。这样创建的输出流对象,就可以指定是否追加续写了。
public FileOutputStream(File file, boolean append)
: 创建文件输出流以写入由指定的 File对象表示的文件。public FileOutputStream(String name, boolean append)
: 创建文件输出流以指定的名称写入文件。
/**
* 数据追加
*/
public class OutputStream002 {
public static void main(String[] args) throws IOException {
//建立连接
File file = new File("F:\\输入输出流\\w1.txt");
//选择流
FileOutputStream fos = new FileOutputStream(file,true);
// 字符串转换为字节数组
byte[] b = "abcde".getBytes();
fos.write(b);
//刷新
fos.flush();
// 关闭资源
fos.close();
}
}
三、字符流
当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
1.字符输入流【Reader】
java.io.Reader
抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。
public void close()
:关闭此流并释放与此流相关联的任何系统资源。public int read()
: 从输入流读取一个字符。public int read(char[] cbuf)
: 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中
1)FileReader类
java.io.FileReader
类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
字符编码:字节与字符的对应规则。Windows系统的中文编码默认是GBK编码表。
idea中UTF-8
字节缓冲区:一个字节数组,用来临时存储字节数据。
构造方法:
FileReader(File file)
: 创建一个新的 FileReader ,给定要读取的File对象。FileReader(String fileName)
: 创建一个新的 FileReader ,给定要读取的文件的名称。
读取字符:read
方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1
,循环读取
public class Reader001 {
public static void main(String[] args) throws IOException {
//建立连接
File file = new File("F:\\输入输出流\\aa.txt");
//选择流
Reader r = new FileReader(file);
//读取
int i;
while((i=r.read())!=-1){
System.out.print((char) i);
}
//释放资源
r.close();
}
}
使用字符数组读取:read(char[] cbuf)
,每次读取b的长度个字符到数组中,返回读取到的有效字符个数,读取到末尾时,返回-1
public class Reader002 {
public static void main(String[] args) throws IOException {
//建立连接
File file = new File("F:\\输入输出流\\aa.txt");
//选择流
Reader reader = new FileReader(file);
char[] bytes = new char[1024];
int len ;
while ((len=reader.read(bytes))!=-1){
String s = new String(bytes, 0, len);
System.out.println(s);
}
reader.close();
}
}
2.字符输出流【Writer】
java.io.Writer
抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。
void write(int c)
写入单个字符。void write(char[] cbuf)
写入字符数组。abstract void write(char[] cbuf, int off, int len)
写入字符数组的某一部分,off数组的开始索引,len写的字符个数。void write(String str)
写入字符串。void write(String str, int off, int len)
写入字符串的某一部分,off字符串的开始索引,len写的字符个数。void flush()
刷新该流的缓冲。void close()
关闭此流,但要先刷新它。
1)FileWriter类
构造方法:
FileWriter(File file)
: 创建一个新的 FileWriter,给定要读取的File对象。FileWriter(String fileName)
: 创建一个新的 FileWriter,给定要读取的文件的名称。
**
* 写文件
* 1、建立连接
* 2、选取流
* 3、操作,写
* 4、刷新
* 5、释放资源
*/
public class Writer001 {
public static void main(String[] args) throws IOException {
//建立连接
File file = new File("F:\\输入输出流\\w.txt");
//选择流
Writer w = new FileWriter(file);
//操作 写
w.write(97); // 字符的Unicode码
w.write("bcd"); //String
w.write(new char[]{'f','g'}); //字符数组
w.write('h'); //单个字符
//刷新
w.flush();
//关闭
w.close();
}
}
2)续写和换行
public class Writer002 {
public static void main(String[] args) throws IOException {
//建立连接
File file = new File("F:\\输入输出流\\w.txt");
//选择流
FileWriter fw = new FileWriter(file,true);
// 写出字符串
fw.write("你好");
// 写出换行
fw.write("\r\n");
// 写出字符串
fw.write("程序员");
//刷新
fw.flush();
// 关闭资源
fw.close();
}
}
四、文件复制
文件复制就是先从一个文件读取数据到内存, 再从内存写出数据到文件。
字符流拷贝文件(不能复制图片、音频、视频等):
/**
* 先从一个文件读取数据到内存, 从内存写出数据到文件
*/
public class Demo013IO {
public static void main(String[] args) throws Exception{
//读 输入流
FileReader fr = new FileReader("aaa.txt");
// 写 输出流
FileWriter fw = new FileWriter("acopy.txt");
char[] cs = new char[1024];
int len;
// 循环读取
while((len=fr.read(cs))!=-1){
fw.write(cs,0,len);
}
// 刷新和释放资源
fw.flush();
fr.close();
fw.close();
}
}
字节流拷贝文件:
public class Demo014IO {
public static void main(String[] args)throws Exception {
// 创建流 输入流 并且同时和文件建立联系
FileInputStream fis = new FileInputStream("A.png");
// 创建流 输出流 并且同时和文件建立联系
FileOutputStream fos = new FileOutputStream("bbbb.png");
byte[] bs = new byte[1024];
int len;
while((len=fis.read(bs))!=-1){
fos.write(bs,0,len);
}
// 刷新和释放资源
fos.flush();
fos.close();
fis.close();
}
}
五、Commons-io
commons-IO是apache的一个开源的工具包,封装了IO操作的相关类,使用Commons IO可以很方便的读写文件,url源代码等。commons-IO 需要加入classpath 的第三方 jar 包内的 class 文件才能在项目中使用
1.导入 commons-io
- 获取commons-io架包,选中idea的项目,右击,新建一个Dircetory,命名为lib。
- 把commons-io复制粘贴到lib文件夹中,选中commons-io右击,再选中add as Library…
Commons-io架包帮我们封装了以上所有操作
,非常方便。
2.读文件
public class CommonsIORead {
public static void main(String[] args) throws IOException {
//原始的做法
// File file1 = new File("F:\\输入输出流\\a.txt");
//工具类提供的方法,用来和指定文件建立联系
File file = FileUtils.getFile("F:\\输入输出流\\a.txt");
//读文件内容到一个字符串
String s = FileUtils.readFileToString(file, "GBK");
//输出
System.out.println(s);
}
}
3.写文件
public class CommonsIOWrite {
public static void main(String[] args) throws IOException {
//创建file对象,写文件,文件不一定要存在
File file = FileUtils.getFile("F:\\输入输出流\\write.txt");
// 使用工具去写文件 文件,内容,编码集
FileUtils.writeStringToFile(file,"Hello,world!","UTF-8");
}
}
4.文件的复制
/**
* 文件复制 利用FileUtils工具类,可以直接复制
*/
public class CommonsCopy02 {
public static void main(String[] args) throws IOException {
//copyFile 原文件 复制到 其他文件,其他文件可以不存在
FileUtils.copyFile(FileUtils.getFile("F:\\输入输出流\\a.txt"),FileUtils.getFile("F:\\输入输出流\\copy2.txt"));
}
}