概述
- 输入流 :把数据从 其他设备 上读取到 内存 中的流。
- 输出流 :把数据从 内存 中写出到 其他设备 上的流。
字节流
- 一切皆为字节,字节流可以传输任意数据
字节输出流(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)
:将指定的字节输出流。
FileOutputStream类(文件字节输出流)
构造方法
public FileOutputStream(File file)
:创建文件输出流以写入由指定的 File对象表示的文件。public FileOutputStream(String name)
: 创建文件输出流以指定的名称写入文件。- 当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果有这个文 件,会清空这个文件的数据。
使用
- 写入数据原理:
java程序—>JVM虚拟机—>OS操作系统—>OS调用写数据的方法—>把数据写入到文件中
- 使用步骤
- 创建FileOutputStream对象,构造方法中传递写入数据的目的地
- 调用write方法写入数据
- 关闭流
//使用 write(int b)一次写一个字节
public class FosWrite{
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 写出数据
fos.write(97); // 写出第1个字节
fos.write(98); // 写出第2个字节
fos.write(99); // 写出第3个字节
// 关闭资源
fos.close();
}
}
输出结果: abc
- 注意:虽然参数为int类型四个字节,但是只会保留一个字节的信息写出。
//使用 write(byte[] b) 一次写多个字节
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 字符串转换为字节数组
byte[] b = {65,66,67,68,69} //输出结果: ABCDE
byte[] b = {-65,-66,-67,68,69} //输出结果:烤炴E
byte[] b = "你好".getBytes(); //输出结果:你好
// 写出字节数组数据
fos.write(b);
// 关闭资源
fos.close();
}
}
- 注意:一次写多个字节
- 如果写的第一个字节是正数(0~127),那么显示的时候会查询ASCII表
- 如果写的第一个字节是负数,那么第一个字节会和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)
文件存储原理和记事本打开原理
- 硬盘中存储的都是字节,1字节=8个二进制位
- 在任意的文本编辑器中打开文件时,都会查询编码表,将字节转化为字符表示
0~127:查询ASCII码表
其它值:查询系统默认码表(中文系统GBK)
数据的追加续写和换行写
追加续写
- 每次程序运行,创建输出流对象,都会清空目标文件中的数据(删除该文件,创建新的空文件)。如何保留目标文件中数据,还能继续添加新数据呢?
public FileOutputStream(File file, boolean append)
: 创建文件输出流以写入由指定的 File对象表示的 文件。public FileOutputStream(String name, boolean append)
: 创建文件输出流以指定的名称写入文件。- true 表示追加数据, false 表示清空原有数据。
换行
- windows:
\r\n
回车符
\r
和换行符\n
:
回车符:回到一行的开头(return)。
换行符:下一行(newline)。 - linux:
/n
- mac:
/r
public class FOSWrite {
public static void main(String[] args) throws IOException {
// 使用文件名称创建流对象
FileOutputStream fos = new FileOutputStream("fos.txt");
// 定义字节数组
byte[] words = {97,98,99,100,101};
// 遍历数组
for (int i = 0; i < words.length; i++) {
// 写出一个字节
fos.write(words[i]);
// 写出一个换行, 换行符号转成数组写出
fos.write("\r\n".getBytes());
}
// 关闭资源
fos.close();
}
}
字节输入流(InputStream)(硬盘->内存)
java.io.InputStream
抽象类是表示字节输入流的所有类的超类- 字节输入 流的基本共性功能方法:
public void close()
:关闭此输入流并释放与此流相关联的任何系统资源。
public abstract int read()
: 从输入流读取数据的下一个字节。
public int read(byte[] b)
: 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
FileInputStream类
java.io.FileInputStream
类是文件输入流,从文件中读取字节。- 读取数据原理
java程序—>JVM虚拟机—>OS操作系统—>OS调用读取数据的方法—>读取文件
构造方法
FileInputStream(File file)
: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。FileInputStream(String name)
: 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。- 当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出
FileNotFoundException
。
使用
- 使用步骤:
- 创建FileInputStream对象,构造方法中传递写入数据的目的地
- 调用read方法读取文件
- 关闭流
- 读取字节: read 方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回 -1 ;
一次读取一个字节
public class FISRead {
public static void main(String[] args) throws IOException{
// 使用文件名称创建流对象
FileInputStream fis = new FileInputStream("read.txt"); //abc
// 读取数据,返回一个字节
/*int read = fis.read();
System.out.println((char) read); //a
read = fis.read();
System.out.println((char) read); //b r
read = fis.read();
System.out.println((char) read); //c
// 读取到末尾,返回‐1
read = fis.read();
System.out.println( read); */
int len=0;
while((len=fis.read())!=-1){
System.out.println((char) len);
}
// 关闭资源
fis.close();
}
}
字节流一次读取一个字节的原理
一次读取多个字节原理
- 从图中可以看出,第一次(AB)和第二次(CD)输出结果正确,第三次(ED)和第四次(ED)输出错误,第三次应该只输出E,第四次无输出,这是因为在bytes数组中,上次读取的数据没有被完全替换;
public class FISRead {
public static void main(String[] args) throws IOException{
// 使用文件名称创建流对象.
FileInputStream fis = new FileInputStream("read.txt"); // 文件中为abcde
// 定义变量,作为有效个数
int len ;
// 定义字节数组,作为装字节数据的容器
byte[] b = new byte[2];
// 循环读取
while (( len= fis.read(b))!=‐1) {
// 每次读取后,把数组的有效字节部分,变成字符串打印
System.out.println(new String(b,0,len));// len 每次读取的有效字节个数
}
// 关闭资源
fis.close();
}
}
输出结果:
ab
cd
e
字节流读取中文问题
- 使用字节流读取中文文件
1个中文
GBK:占用两个字节
UTF-8:占用三个字节
- 当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,
那是因为 一个中文字符可能占用多个字节存储,而一次只能读取一个字节,从而产生乱码问题
。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文 件。