能懂系列之 Java.IO 字节流读写文件
序
工作开发中,对文件的操作肯定是少不了的,所以搞懂文件操作的基础 IO 流是相当有必要的,所以今天阿淼就给大家普及一下。
一、Java文件读写操作的分类
首先,阿淼给大家绘制了一张 IO 流的关系图:
看完过后有没有一目了然的感觉?有的话就对了,赶紧保存下来吧。
从图中么我们可以清晰的看到:java 将文件的读写分成了字节流和字符流,字节流主要是对非文本文件的操作,读和写操作的单位都是字节;字符流主要是对文本文件的操作,读和写操作的基本单位都是一个字符而不仅仅是单个字节。
在每种流种都有写操作和读操作,即输出流,输入流。
二、编码表的简单介绍
计算机都只记录‘0’和‘1’,要形成我们所见到的万千气象,则需要将数据中的‘0’、‘1’与编码表对照。
正所谓 “道生一,一生二,二生三,三生万物”
对于中文的读写,单纯用字节流将会出现乱码的现象,因为在编码表中,一个中文字符不仅仅是占一个字节大小。造成这个现象主要是因为编码表不同而造成的。
常用的英文编码表为ASCII,这个编码表每个符号都只占用一个字节总共有256个内容,但是因为这个编码表的表示很有局限性,并不能表示其他文字。
对于中文而言,使用最多的就是GBK和UTF-8两种编码表。
在互联网中,最的普遍使用的还是UTF-8编码表。
这两种编码表为了和ASCII表保持兼容性,都将前面256个保持和ASCII表相同,使用2字节(GBK),3字节(UTF-8)表示一个字符。
三、字节流操作。
1.字节输出流OutputStream
OutputStream是一个抽象类,表示输出字节流的所有类的父类。输出流接受输出字节并将这些字节发送到某个接收器。
需要定义 OutputStream 子类的应用程序必须始终提供至少一种可写入一个输出字节的方法。
而在此抽象方法中,定义了输出字节流的基本方法。
void close()
//关闭此输出流并释放与此流有关的所有系统资源。
void flush()
//刷新此输出流并强制写出所有缓冲的输出字节。
void write(byte[] b)
//将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len)
//将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
void write(int b)
//将指定的字节写入此输出流。
在OutputStream类中,有一个已经实现的类,FileOutputStream类,用于数据写入到文件中。
①FileOutputStream
FileOutputStream,文件输出流,功能是将数据输出到FileOutputStream所指定的对象中。
FileOutputStream构造方法摘要:
/*文件覆盖写入构造*/
FileOutputStream(File file)
//创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(String pathname)
//创建一个向具有指定名称的文件中写入数据的输出文件流。
/*文件续写构造*/
FileOutputStream(File file, boolean append)
//创建一个向指定 File 对象表示的文件中写入数据的文件输出流。
FileOutputStream(String pathname, boolean append)
//创建一个向具有指定 name 的文件中写入数据的输出文件流。
既然FileOutputStream是OutputStream的一个继承类,那么就可以直接使用OutputStream中定义好的方法来写入数据了。
FileOutputStream覆盖写入数据代码演示:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException{
//在D:\JavaStudyCode中创建存储数据的文件OutputStream.txt
File f = new File("D:\\JavaStudyCode\\OutputStreamDemo.txt");
//单参数构造方法,创建一个文件输出流对象,指定数据输出存储的位置
FileOutputStream fos = new FileOutputStream(f);
//通过FileOutputStream指定的文件不存在会被创建,如果存在则会被覆盖
//调用FileOutputStream父类OutputStream的方法进行数据写入
fos.write(65); //write(int b)方法写入一个字节数据
/*
*fos.write(65)会将65这个字节数据对照编码表进行写入,
*所以文件出现的内容是一个字母‘A’
*/
byte[] bytes = {65,66,67};
fos.write(bytes); //write(byte[] b)方法写入一个字节数组数据
/*
*fos.write(bytes)会将字节数组中的三个数据,65,66,67
*对照编码表进行写入
*被写入的内容为‘A’‘B’‘C’三个字母
*加上上一句写入的‘A’
*此时文件内容为AABC
*/
//write(bytes,1,1)方法写入从bytes数组索引1开始的2个字节数据
fos.write(bytes,1,2);
/*
*fos.write(bytes,1,2)会将bytes数组索引1开始的2个字节数据
*对照编码表进行写入
*所以写入的内容为‘B’‘C’
*加上前面的内容,文件中的内容为AABCBC
*/
//关闭流并且释放占用资源
fos.close();
}
}
FileOutputStream续写数据代码演示:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class WritennAndNewLine {
public static void main(String[] args) throws IOException{
//在D:\JavaStudyCode中创建存储数据的文件OutputStream.txt
File f = new File("D:\\JavaStudyCode\\OutputStreamDemo.txt");
//创建一个文件输出流对象,指定数据输出存储的位置
FileOutputStream fos = new FileOutputStream(f,true);
//双参数构造方法,第二个参数为true时不会覆盖原来的文件,而是进行续写
fos.write(68);//在前面的操作写在文件中的内容之后写入一个D
/*
* 文件中的内容为AABCBC加上这个方法写入的D为AABCBCD
*/
//写入数据的换行操作
String str = "\r\n"+"换行后的字符";
//调用String的getBytes()方法,将String转成byte数组写入
fos.write(str.getBytes());
fos.close();
}
}
此时文件中的内容为:
AABCBCD
换行后的字符
\r \n为转移字符; \后面跟着字符将字母转成了特定用途的标识符
\r回车符 \n换行符; 在文本写入时有相同的换行作用
2.字节输入流InputStream
InputStream也是一个抽象类,与OutputStream为一个同等的相对作用的类,将文件中的内容读入到内存中,表示字节输入流的所有类的父类。
需要定义 OutputStream 子类的应用程序必须始终提供至少一种可写入一个输出字节的方法。
而在此抽象方法中,定义了输入字节流的基本方法。
void close()
关闭此输入流并释放与该流关联的所有系统资源。
int read()
从输入流中读取数据的下一个字节,如果没有字节返回-1
int read(byte[] b)
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中,返回读取到的字节数
int read(byte[] b, int off, int len)
将输入流中最多 len 个数据字节读入 byte 数组。
在InputStream类中,有一个已经实现的类,FileInputStream类,用于将文件中的数组读入内存中程序使用。
①FileInputStream
FileInputStream,文件输入流,功能是将FileInputStream所指定的对象文件中的数据读入到内存中。
FileInputStream构造方法摘要:
FileInputStream(String name)
//通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。
FileInputStream(File file)
//通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
同样的,FileInputStream是InputStream的一个继承类,那么就可以直接使用InputStream中定义好的方法d读取数据了。
FileInputStream读取文件数据到内存:
代码演示:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class InputStreamDemo {
public static void main(String[] args) throws IOException {
//使用原先写入好的并删除掉中文字符后的数据文件OutputStream.txt,
//创建File对象
File f = new File("D:\\JavaStudyCode\\OutputStreamDemo.txt");
//创建一个文件输入流对象,指定数据读取的文件的位置
FileInputStream fis = new FileInputStream(f);
//一次读取一个字节
int data = 0; // 记录read方法的返回值,不是-1则循环读取
while((data = fis.read()) != -1) {
System.out.println("initial is "+data);
System.out.println("changed is "+(char)data);
}
fis.close();
}
}
结果输出:
initial is 65
changed is A
initial is 65
changed is A
initial is 66
changed is B
initial is 67
changed is C
initial is 66
changed is B
initial is 67
changed is C
initial is 68
changed is D
initial is 68
changed is D
initial is 13
changed is
initial is 10
changed is
对于这种一次读取一个字节的方法是极度低效的,如果一个文件稍微大一点的话,就能够明显感觉到读取很慢,所以可以采用read()的一个重载方法,先将内容读取到一个中间容器byte数组中。
FileInputStream读取多字节数据到内存:
代码演示:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class InputStreamDemo {
public static void main(String[] args) throws IOException {
//在D:\JavaStudyCode中创建存储数据的文件OutputStream.txt
//创建File对象
File f = new File("D:\\JavaStudyCode\\OutputStreamDemo.txt");
//创建一个文件输入流对象,指定数据读取的文件的位置
FileInputStream fis = new FileInputStream(f);
//一次读取一个bytes数组大小的字节,长度可以是1024的整数倍
byte[] bytes= new byte[1024];
int length = 0; // 记录read方法的返回值,不是-1则循环读取
while((length = fis.read(bytes)) != -1) {
System.out.println(new String(bytes,0,length));
}
fis.close();
}
}
输出结果是:
AABCBCDD
标题:能懂系列之 Java.IO 字节流读写文件
作者:spirit223
地址:https://www.mmzsblog.cn/articles/2020/08/01/1596253370864.html
如未加特殊说明,文章均为原创,转载必须注明出处。均采用CC BY-SA 4.0 协议!
本网站发布的内容(图片、视频和文字)以原创、转载和分享网络内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。若本站转载文章遗漏了原文链接,请及时告知,我们将做删除处理!文章观点不代表本网站立场,如需处理请联系首页客服。• 网站转载须在文章起始位置标注作者及原文连接,否则保留追究法律责任的权利。
• 公众号转载请联系网站首页的微信号申请白名单!
