第一章:IO流
第二章:字节流
2.1 字节输出流【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)
:从指定的字节数组中从偏移量off开始的len字节写入此输出流;public abstract void write(int b)
:将指定的字节写入此输出流;
2.2 FileOutputStream类
java.io.FileOutputStream extends OutputStream
:文件字节输出流,作用是把内存中的数据写入到硬盘的文件中。
常用构造方法:
FileOutputStream(String path)
:创建一个向具有指定名称的文件中写入数据的输出文件流;FileOutputStream(File file)
:创建一个向指定File对象表示的文件中写入数据的文件输出流;参数:写入数据的目的地
String name:目的地是一个文件的路径
File file:目的地是一个文件
构造方法的作用:
1、先创建一个FileOutputStream对象;
2、会根据构造方法中传递的文件路径/文件创建一个空的文件;
3、会把FileOutputStream对象指向创建好的文件;
写入数据的原理:
Java程序 --> JVM(Java虚拟机)--> OS(操作系统)--> OS调用写数据的方法 --> 把数据写入到文件中
写换行:
直接写换行符号即可,例如 => Windows
:\r\n,Linux
:/n,Mac
:/r;
public class 字节流 {
public static void main(String[] args) throws IOException {
File f = new File("a.txt");
FileOutputStream fos = new FileOutputStream(f,true);
/* 在Windows中,数据带上\r\n即表示换行的意思 */
fos.write("\r\n你好".getBytes());
fos.close();
}
}
数据追加续写:
每次创建输出流对象时,对文件写入都会覆盖原文件的内容,要使得数据每次都是以追加的形式,只需要在FileOutputStream的构造方法的参数中,再加入一个boolean参数,例如:
public FileOutputStream(File file, boolean append)
public FileOutputStream(String name, booloean append)
其中true
表示追加数据,false
表示清空原有数据,默认为false
package file_io;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class 字节流 {
public static void main(String[] args) throws IOException {
File f = new File("D:\\Web学习资料\\first\\1-3-Java语言高级\\06-File类与IO流\\04 IO字节流\\a.txt");
/* FileOutputStream的构造方法中第二个参数即为追加开关,true表示追加,false表示覆盖 */
FileOutputStream fos = new FileOutputStream(f,true);
fos.write("你好,这是我写的一个数据".getBytes());
fos.close();
}
}
2.3 字节输入流【InputStream】
java.io.InputStream
抽象类是表示字节输入流的所有类的超类。它定义了字节输入流的基本共性方法。
常用方法:
int read()
:从输入流读取数据的下一个字节;int read(byte[] b)
:从输入流中读取一定数量的字节,并将其存储在缓冲区数组b中;int read(byte[] b, int off, int len)
:如果读取了有效的字节,则返回读取的有效字节数,反之则返回-1
void close()
:关闭此输入流并释放与该流关联的所有系统资源;
2.4 FileInputStream类
java.io.FileInputStream extends InputStream
:文件字节输入流,作用是将硬盘中的数据读取到内存中。
构造方法:
FileInputStream(String name)
:通过路径打开一个实际的文件FileInputStream(File file)
:通过File对象打开一个实际的文件构造方法的作用:
1、会创建一个FileInputStream对象;
2、会把上述对象指定构造方法中要读取的文件;
举例:
package file_io;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class 读取文件 {
public static void main(String[] args) throws IOException {
File f = new File("D:\\Web学习资料\\first\\1-3-Java语言高级\\06-File类与IO流\\04 IO字节流\\a.txt");
FileInputStream inputStream = new FileInputStream(f);
byte[] b = new byte[100];
int read = inputStream.read(b);
System.out.println(new String(b,0,read));
System.out.println(read);
inputStream.close();
}
}
2.5 拷贝文件示例
这里经过本人测试,发现提示复制成功的一个.avi视频文件打不开,一开始打算将从输入流读取的字节数组转化成了字符串,再将字符串转化成字节数组,放至输出流中,这样的话是有问题的,通过查阅资料,也了解到了字节流和字符流操作的区别具体如下:
- 字符流主要针对一些文本文档(比字节流操作的效率要高),比如.txt、.doc,而pdf就不行。
- 字节流几乎可以对任何文件类型进行操作,主要是对非文件类型的,如媒体文件(音频,视频,图片…)。
注意事项:
当使用字节流读取文本文件时,可能会存在一个问题,就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用来处理文本文件。
package file_io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class 拷贝任意文件 {
public static void main(String[] args) throws IOException {
// 给拷贝文件计时
long begin = System.currentTimeMillis();
// 创建一个读的字节流
FileInputStream inputStream = new FileInputStream("D:\\Web学习资料\\first\\1-3-Java语言高级\\06-File类与IO流\\04 IO字节流\\1_8_4_01_IO概述(概念&分类).avi");
// 创建一个写的字节流
FileOutputStream outputStream = new FileOutputStream("D:\\Web学习资料\\first\\1-3-Java语言高级\\06-File类与IO流\\04 IO字节流\\newFile.avi",true);
// 创建一个字节数组缓冲区,长度定为1024字节
byte[] b = new byte[1024];
// 定义len表示有效字节长度
int len = 0;
// 开始循环读取文件
while ((len = inputStream.read(b)) != -1) {
// 方法一:错误
// 先将有效的部分转化成字符串,然后再转化为字符数组
// 这种思路是有问题的,为什么呢?
// 因为视频格式读取的字节流若是转化成字符串,则会存在错误,导致拷贝的新文件打不开
// outputStream.write(new String(b,0,len).getBytes());
// 方法二:正确
// 将每次从输入流读取的字节数组中有效的部分取出来,然后写入输出流
outputStream.write(b,0,len);
}
// 关闭输出流
outputStream.close();
// 关闭输入流
inputStream.close();
// 计时结束
long end = System.currentTimeMillis();
System.out.println("本次拷贝文件共耗时:" + (end - begin) + "ms");
}
}
第三章:字符流
3.1 字符输入流【Reader】
java.io.Reader
抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。
public void close()
:关闭此流并释放与此流相关联的任何系统资源;public int read()
:从输入流读取一个字符,并将此字符转成int型数据;public int read(char[] cbuf)
:从输入流读取一些字符,并将他们存储到字符数组cbuf中,返回值为读取的有效长度;
3.2 FileReader类
java.io.FileReader
类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
构造方法:
FileReader(File file):
FileReader(String filename):
参数:String filename => 文件路径;File file => 文件对象;
作用:1、创建一个FileReader对象,并把该对象指向要读取的文件;
使用步骤:
- 创建FileReader对象,构造方法中绑定要读取的数据源;
- 使用FileReader对象中的方法read读取文件;
- 释放资源;
举例:
package file_io;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReader读取单个字符 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("D:\\个人资料\\aaa.txt");
// 方法一:
int len = 0;
// read方法读取出来的是字符的int类型字符数据,
// 如果需要还原成真实的数据,只需要强转一下即可
// 未读取到字符则返回-1
while((len = fr.read()) != -1) {
System.out.print((char)len);;
}
// 方法二:
int yxlen = 0;
char[] ch = new char[1024];
while((yxlen = fr.read(ch)) != -1) {
// 使用String类的构造方法,输出字符数组的内容
System.out.print(new String(ch,0,yxlen));
}
}
}
3.3 字符输出流【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():
关闭该输出流,但是先刷新它
3.4 FileWriter类
java.io.FileWriter
类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
构造方法:
FileWriter(File file):
根据给定的File对象构造一个FileWriter对象FileWriter(File file, boolean append):
在上述中,增加可追加的设置FileWriter(String fileName):
根据给定的文件路径构造一个FileWriter对象FileWriter(String fileName, boolean append):
在上述中,增加可追加的设置
使用步骤:
创建
FileWriter
对象,构造方法中绑定要写入数据的目的地;使用
FileWriter
中的方法write,把数据写入到内存缓冲区中(此时内部有字符转化为字节的过程);使用
FileWriter
中的方法flush,把内存缓冲区中的数据,刷新到文件中;释放资源(会先把内存缓冲区中的数据刷新到文件中)
如果不使用 flush或者 close,则数据随代码的执行,在内存缓冲区中停留一段时间后会自动消失,不会被写入文件中!
flush和close方法的区别:
- flush:刷新缓冲区,流对象可以继续使用;
- close:先刷新缓冲区,然后通知系统释放资源,流对象不可以再被使用了;
换行符号:
- Windows: \r\n
- Linux: /n
- Mac: /r
举例一(FileWriter的常规使用):
package file_io;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriter写入数据 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\个人资料\\bbb.txt", true);
// 先写到内存缓冲区中,
// 如果后续没有使用flush或close,则内存缓冲区中的数据压根不会存到文件中去
fw.write("123456789",0,3);
fw.write(new char[]{'中', '国', '加', '油'},0,2);
// 将内存缓冲区中的数据刷新到文件中
fw.flush();
// 会先刷新一次
fw.close();
}
}
举例二(写入的数据进行换行操作):
package file_io;
import java.io.FileWriter;
import java.io.IOException;
public class 使用FileWriter写入换行 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\个人资料\\bbb.txt", true);
for (int i = 0; i < 10; i++) {
fw.write(97 + i);
// 写入换行符号
fw.write("\r\n");
}
fw.close();
}
}