本节内容在我们开发需求中十分常见,我个人认为理解java IO知识点的重中之重在于理解java.io包下每一种流之间存在的关系。下面我将关系图、基本操作放出(自己敲一遍,且找一下各类存在的关系有助于加深印象)。
package com.example.io;
import org.junit.jupiter.api.Test;
import java.io.*;
/**
* @author lqh
* @date 2020/6/10
*/
public class ByteStreamTest {
/**
* IO(input/output)在计算机用语中时指输入输出,流是一种抽象的数据传输结构,
* 主要用于进行数据的传输,所以IO流就是指用流的形式来进行数据传输。
*
*流的概念:流就像是一个通道,将两个设备之前建立连接,然后数据在通道直接传输
*
* 流的分类
* 一、按操作数据的单位分:字节流和字符流
* 二、按数据流的流向分:输入流和输入流
* 四种常用流
* FileInputStream、FileOutputStream,FileReader,FileWriter
*
*/
@Test
public void testFileInputStream(){
/**
* FileInputStream,字节输入流
* 该流用于从文件读取数据,
* 常用API:
* public int read() throws IOException //到达文件末尾,则返回-1
* public int read(byte[] b) throws IOException
* public int read(byte[] b,int off,int len) throws IOException
*/
File file=new File("E:"+File.separator+"AioDir"+File.separator+"fileInput.txt");
InputStream f=null;
if(!file.getParentFile().exists()) {
file.getParentFile().mkdir();
}
try {
if(!file.exists()){
file.createNewFile();
}
f=new FileInputStream(file);
/* int n=0;
StringBuffer sBuffer=new StringBuffer();
while (n!=-1) //当n不等于-1,则代表未到末尾
{
n= f.read();//读取文件的一个字节(8个二进制位),并将其由二进制转成十进制的整数返回
char by=(char) n; //转成字符
sBuffer.append(by);
}
System.out.println(sBuffer);*/
byte[] b=new byte[2];
int len=0;
while ((len=f.read(b))!=-1) //当n不等于-1,则代表未到末尾
{
System.out.println(new String(b,0,len)); //读取后的字节数组内容
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if(f!=null){
try {
f.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void testFileOutStream(){
/**
* FileOutputStream,字节输出流
* 该流用于向文件中写数据
* 如果该流打开文件进行输出时,目标文件不存在,那么该流就会创建文件
* 常用API:
* public void write(int b) throws IOException
* public void write(byte[] b) throws IOException {}
* public void write(byte[] b,int off,int len) throws IOException{}
* public void close() throws IOException{}
*/
File file=new File("E:"+File.separator+"AioDir"+File.separator+"fileOutput.txt");
OutputStream f=null;
try {
f=new FileOutputStream(file,true);
f.write("\n\rabc".getBytes());
} catch (IOException e) {
e.printStackTrace();
}finally {
if(f!=null){
try {
f.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
1.关系图(注:FileReader和FileWriter的父类)
package com.example.io;
import org.junit.jupiter.api.Test;
import java.io.*;
/**
* @author lqh
* @date 2020/6/11
*/
public class CharacterStreamTest {
@Test
public void testFileReader(){
/**
* int read():每次读取一个字符,读到最后返回 -1
* int read(char[] buffer):将字符读进字符数组,返回结果为读取的字符数
* int read(char[] buffer,int off,int len):将读取的字符存储进字符数组 buffer,返回结果为读取的字符数,从索引 off 开始,长度为 len
*/
File file=new File("E:"+File.separator+"AioDir"+File.separator+"fileReader.txt");//文件编码:UTF-8
Reader fileReader=null;
//此处省略目录检查,假设文件存在
try {
fileReader=new FileReader(file);
int len=0;
/* while ((len=fileReader.read())!=-1){
System.out.println((char)len);
}*/
//int read(char[] buffer,int off,int len)
char[] buffer = new char[10]; //每次读取 10 个字符
while((len=fileReader.read(buffer,0,10))!=-1){
System.out.println(new String(buffer,0,len));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fileReader!=null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void TestFileWriter(){
File file=new File("E:"+File.separator+"AioDir"+File.separator+"fileWriter.txt");
/***
* void write(int c):向外写出一个字符
* void write(char[] buffer):向外写出多个字符 buffer
* void write(char[] buffer,int off,int len):把 buffer 数组中从索引 off 开始到 len个长度的数据写出去
* void write(String str):向外写出一个字符串
*/
Writer fileWriter=null;
try {
fileWriter=new FileWriter(file,true);
fileWriter.write("abc你好123");
fileWriter.write("abc你好".toCharArray());
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fileWriter!=null){
try {
/**
* 此处如果注释flush和close,内容不能够写入
*/
fileWriter.flush();
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* @author lqh
* @date 2020/6/11
*/
public class ConversionFlowTest {
/**
* OutputStreamWriter
* InputStreamReader
*/
@Test
public void testOutputStreamWriter(){
File file=new File("E:"+File.separator+"AioDir"+File.separator+"fileOutput.txt");
try {
OutputStream outputStream=new FileOutputStream(file); //字节流
Writer outputStreamWriter=new OutputStreamWriter(outputStream); //字节流转字符流
outputStreamWriter.write("www.baidu.com");
outputStreamWriter.write("\r\n你好");
outputStreamWriter.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testInputStreamReader(){
File file=new File("E:"+File.separator+"AioDir"+File.separator+"fileInput.txt");
try {
InputStream inputStream=new FileInputStream(file); //字节流
Reader inputStreamReader=new InputStreamReader(inputStream); //字节流转字符流
int len=0;
char[] buffer = new char[10]; //每次读取 10 个字符
while((len= inputStreamReader.read(buffer,0,10))!=-1){
System.out.println(new String(buffer,0,len));
}
inputStreamReader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* @author lqh
* @date 2020/6/11
*/
public class MemoryStreamTest {
@Test
public void testByteArrayOutputStream() throws IOException{
/**
* 内存流:在内存中读写数据 (特点:数据在内存中处理比磁盘(硬盘)要更快一些,有时候可能需要临时在内存中保存并处理数据,内存流效率会更高)
* 好处及应用场景:
* 1.代码中需要交换的数据,读写的数据,仅仅是代码之间需要交换,就没必要内存 ==》 磁盘 磁盘 ==》内存 【仅仅可以在内存读写上提高了效率】
* 2.好处:提高了读写的效率,即数据处理的效率
* 3.安全性:线程安全
* ByteArrayInputStream :包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。
* ByteArrayOutputStream : 此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
* CharArrayReader: 此类实现一个可用作字符输入流的字符缓冲区。
* CharArrayWriter:此类实现一个可用作 Writer 的字符缓冲区。缓冲区会随向流中写入数据而自动增长。可使用 toCharArray() 和 toString() 获取数据。
*
* 注意:void close():关闭 内存流 无效。 之前的IO流都是跟磁盘文件建立了连接,需要关闭连接即关闭流! 而关闭内存流跟连接无关
*/
//内存字节流
ByteArrayOutputStream baos = new ByteArrayOutputStream();//不需要路径,写入内存,跟磁盘无需关联
baos.write("ByteArrayOutputStream".getBytes());//将字符串变成字节数组,写入内存
baos.close();//此处关闭内存流无效 下面的数据也可写入
baos.write("\r\nhelloworld".getBytes());//注意:之前的IO流都是跟磁盘文件建立了连接,需要关闭连接即关闭流! 而关闭内存流跟连接无关
byte[] byteArray = baos.toByteArray();//获取内存中存数据的数组
//使用内存输入流 读取获得内存中的保存数据的数组
ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);//ByteArrayInputStream(byte[] buf):创建一个 ByteArrayInputStream,使用 buf 作为其缓冲区数组。
//读
int len;
byte[] b = new byte[1024];
while((len = bais.read(b)) != -1){
System.out.println(new String(b,0,len));
}
//内存字符流
CharArrayWriter caw = new CharArrayWriter();
caw.write("CharArrayWriter");
char[] ch = caw.toCharArray();
//使用内存输入流 读取获得内存中的保存数据的数组
CharArrayReader car = new CharArrayReader(ch);
//读
int len2;
char[] c = new char[10];
while((len2 = car.read(c)) != -1){
System.out.print(new String(c,0,len2));
}
}
}
1.关系图
@Test
public void testStream() throws FileNotFoundException {
/**
* 提供了一系列重载的print()和println()方法,用于多种数据类型的输出。
* PrintStream和PrintWriter的输出不会抛出IOException异常。
* PrintStream和PrintWriter有自动flush功能。
* PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。 在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。
* System.out返回的是PrintStream的实例。
*
*/
File file=new File("E:"+File.separator+"AioDir"+File.separator+"printFile.txt");
PrintStream printStream=new PrintStream(file);
printStream.println(123);
printStream.println("你好");
printStream.println("1+1="+2);
printStream.printf("姓名:%s;年龄:%d;成绩:%f;性别:%c","tom",18,99.5f,'男') ;
printStream.close();
}
2.使用代码
@Test
public void testRandomAccessFile(){
/**
* 优点:
* 1.既可以读也可以写
* 2.可以指定位置进行读写
* 构造器中定义的四种模式
* r 以只读的方式打开文本
* rw 读和写操作都是被允许的(文件不存在,自动创建)
* rws 相当于“rw”,要求对文件内容或元数据的每个更新都同步写入底层设备
* rwd 相当于“rw”,要求对文件内容的每个更新都同步写入底层设备
* 操作文件记录指针:
* long getFilePointer():返回文件记录指针的当前位置
* void seek(long pos) : 将文件记录指针定位到pos位置
*/
RandomAccessFile randomAccessFile=null;
try {
randomAccessFile=new RandomAccessFile("E:"+ File.separator+"AioDir"+File.separator+"randomAccessFile.txt","rw");
System.out.println(randomAccessFile.getFilePointer());
randomAccessFile.write("abcd123".getBytes());
System.out.println(randomAccessFile.getFilePointer());
randomAccessFile.seek(5);
System.out.println(randomAccessFile.readLine());
} catch (IOException e) {
e.printStackTrace();
}finally {
if(randomAccessFile!=null){
try {
randomAccessFile.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
@Test
public void testCharBufferedStream(){
File file=new File("E:"+File.separator+"AioDir"+File.separator+"bufferedOutputFile.txt");
try {
FileOutputStream outputStream=new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream=new BufferedOutputStream(outputStream);
bufferedOutputStream.write("abcdefg".getBytes());
bufferedOutputStream.close();
outputStream.close();
FileInputStream fileInputStream=new FileInputStream(file);
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
byte[] b=new byte[1024];
int len=0;
while ((len=bufferedInputStream.read(b))!=-1){
System.out.println(new String(b,0,len));
}
bufferedInputStream.close();
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testCharacterBufferStream(){
/**
* 使用字符缓存流可以边读边写
*/
File file=new File("E:"+File.separator+"AioDir"+File.separator+"bufferedCharacterFile.txt");
try {
FileReader reader=new FileReader(file);
BufferedReader bufferedReader=new BufferedReader(reader);
File file1=new File("E:"+File.separator+"AioDir"+File.separator+"writeBufferedCharacterFile.txt");
FileWriter writer=new FileWriter(file1);
BufferedWriter bufferedWriter=new BufferedWriter(writer);
String str="";
while ((str=bufferedReader.readLine())!=null){
System.out.println(str);
bufferedWriter.write(str);
bufferedWriter.newLine();
}
char[] c=new char[1024];
int len=0;
while ((len=bufferedReader.read(c))!=-1){
bufferedWriter.write(c,0,len);
}
bufferedWriter.flush();
bufferedWriter.close();
bufferedReader.close();
writer.close();
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
2.使用代码
public class ObjectStream {
/**
* ObjectOutputStream:序列化
* ObjectInputStream:反序列化
*不能序列化Static和Transient修饰的成员变量
**/
public static void main(String[] args) {
/**
* ObjectOutputStream:序列化
* ObjectInputStream:反序列化
*不能序列化Static和Transient修饰的成员变量
* 要序列化的对象必须实现Serializable接口,并且尽量显示的声明serialVersionUID常量
*
**/
File file=new File("D:"+ File.separator+"TestIo"+File.separator+"demo.txt");
//序列化:将内存中对象或基本类型数据序列化到磁盘中
try {
FileOutputStream fileOutputStream=new FileOutputStream(file);
ObjectOutputStream oos=new ObjectOutputStream(fileOutputStream);
oos.writeObject(new String("1223"));
oos.flush();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
//反序列化:将磁盘中的可序列话文件反序列化到内存中
try {
FileInputStream fileInputStream=new FileInputStream(file);
ObjectInputStream ois=new ObjectInputStream(fileInputStream);
try {
Object object=ois.readObject();
System.out.println(object);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}