1、IO流
在程序中所有的数据都是以流(Stream)的方式进行传输的,程序需要数据的时候要使用输入流读取数据,当程序需要将一些内存中的数据保存到硬盘时,需要使用输出流写入数据完成。Java中所有的流类型都是在java.io包中。
IO流体系结构
2、流的分类
IO流主要用来处理设备之间的数据的传输,按照其传输方式可以分为输入流/输出流,按照操作数据单位大小分为字节流/字符流(一个字符等于两个字节)
1、输入流/输出流
输入流 :从外部设备获取到数据存放到计算机内存(程序)中(读操作)
输出流 :就是将暂存在计算机内存中的数据输出到到相应的外部设备(写操作)
个人理解:输入流输出流针对的都是程序(cup处理),当程序要读取其他设备的数据时,数据从外部设备进入程序,因而为输入流(读取数据);同理,当程序要向外部设备写入数据时,程序内的数据需要传输到外部设备,因而为输出流(写入数据)
2、字节流/字符流
字节流 :主要操作二进制数据类型[音频、视频、图片],主要操作byte类型数据,以byte为基数。
字符流 :
对于字节流/字符流来说,只要是处理纯文本数据,优先考虑字符流,除此之外[音频、视频、图片]都是使用字节流
3、字节流
InputStream是所有字节输入流的基类(父类),outputStream是所有字节输出流的基类
0、字节流体系结构
1、字节输出流:【outputStream】
字节输出流主要使用到的类是FileOutputStream
2、字节输出流(写入数据)操作步骤
[1]、使用File类构造file对象
[2]、通过输出流对象FileOutStream构造输出流对象
[3]、使用写入的方法完毕后刷新[flush()]与close()关闭字节输出流
案例 :
package com.lanqiao.IO;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class OutputStreamDemo1 {
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
//构造字节输出流对象要求首先构造file对象
File file = new File("F:" + File.separator + "File" +File.separator + "a.java");
//第一步构造字节输出流对象
/**
* boolean append 参数:
* 当append参数为true则表示写入的内容叠加
* 当append参数为false则表示写入的内容覆盖
* 默认值为false;即覆盖
*/
FileOutputStream fileOutput = new FileOutputStream(file,true);
String str = "韩山师范学院";
fileOutput.write("\n".getBytes());
fileOutput.write(str.getBytes());
fileOutput.flush();
fileOutput.close();
}
}
3、字节输入流 : 【inputStream】
字节输入流主要使用到的类是 : FileInputStream[文件输入流,主要进行读取操作]
案例:
package com.lanqiao.IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class InputStreamDemo1 {
public static void main(String[] args) throws IOException{
// TODO Auto-generated method stub
//需求:将F盘中的File目录下的a.java文件的内容输出到控制台(读)
//[1]通过File 类构造file对象
File file = new File("F:" + File.separator + "File" + File.separator + "A.java");
//判断文件或目录是否存在
if(!file.exists()){
System.out.println("文件不存在");
return;
}
//[2]通过FileInutStream构造输入流对象
FileInputStream fileInput = new FileInputStream(file);
//[3]读取数据,获取操作文件的大小
byte[] b = new byte[fileInput.available()];
int len = 0;
while((len = fileInput.read(b))!=-1){
/*
* 说明 :
* 中文编码格式 : ISO-8859-1<GBK<UTF-8
* 指定字符集编码格式是根据工程的字符格式来指定
*/
String str = new String(b,"GBK");//指定字符集编码格式
System.out.println(str);
}
}
}
综合案例1:
package com.lanqiao.IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.TreeSet;
/*
* 练习 :
* 以代码的方式实现以下功能
* [1]在D盘中构造一个文本A.txt,向文本中写入内容;AaaAcDFAFAOFJIO132
* 向D盘写入数据,创建输出流
* [2]读取该文件内容,去除重复的字母(区分大小写)并且按照自然排序输出到B.txt文件
* 想要输出数据(写入数据),需要创建输入流对象
* 因为文本要排序,且不重复,可以将数据存入HashSet中
* 再通过遍历集合将数据按字节的方式写入到b中
* [3]即文件内容为:123ABCabc这种格式
*/
public class IOTest1 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//[1]创建hashSet集合
TreeSet<Character> charTree = new TreeSet<>();
//[1]在目标目录中创建A.txt和B.txt
File fileA = new File("F:" + File.separator + "File" + File.separator + "AA.txt");
File fileB = new File("F:" + File.separator + "File" + File.separator + "BB.txt");
fileA.createNewFile();
fileB.createNewFile();
//创建输出流,向文本A.txt中写入数据
FileOutputStream outputA = new FileOutputStream(fileA);
String strA = "ADFFBOG123cgfser";
//写入数据
outputA.write(strA.getBytes());
//刷新流
outputA.flush();
//关闭流
outputA.close();
//读取AA.txt中的内容,并将其里面的文本内容赋值给hashSet集合
//创建输入流,读取AA.txt中数据
FileInputStream inputA = new FileInputStream(fileA);
byte[] b = new byte[inputA.available()];
int len = 0;
/*
* TreeSet<Integer> charStr = new TreeSet<>();
* int fileChar = 0;
* while((fileChar=fileInput.read())!=-1){
* charStr.add(fileChar);
* }
*/
while((len = inputA.read(b))!=-1){
//得到A中的内容,并生成字符串格式
String strFromA = new String(b);
//将字符串强转为字符型数组
char[] charA = strFromA.toCharArray();
//将字符数组遍历并赋值给hashSet集合
for (char c : charA) {
charTree.add(c);
}
}
//读取结束,关闭输入流
inputA.close();
//将hashset集合中的数据写入到b.txt中
/*System.out.println(charTree);*/
/*System.out.println(charTree.toString());*/
//创建输出流,写入数据
FileOutputStream outputB = new FileOutputStream(fileB);
//将charTree中的字符集转换为String型
for (char ch :charTree ) {
outputB.write(String.valueOf(ch).getBytes());
}
//刷新输出流
outputB.flush();
//关闭流
outputB.close();
}
}
4、字符流
字符流是相对字节流来说的,由于一个中文字符占用两个字节,因此字节流读取中文时不如字符流效率高,因此在遇到文本情况时,能用字符流更好,在java.io包中提供了Reader/Writer两个抽象类来操作。
1、字符输入流 【Reader抽象类】 ======>读取内容
fileReader : 操作字符输出流的便捷类
InputStreamReader :转换流【将输入字节流转换为输入字符流操作】
BufferedReader :字符输入缓冲流
2、字符输出流 【Writer 抽象类】 ======>写入内容
FileWrite : 操作字符输出流的便捷类
OutputStreamWriter :转换流 【将输出字节流转换为输出字符流操作】
BufferedWriter : 字符输出缓冲流
3、 Write() : 写入方法
附:换行小问题
1、在windows下换行是:\r\n
2、在Linux下换行是:\n
3、在Mac下换行是 :\r
注:在字符缓冲流中【BufferedWrite】中有一个方法【newLine()】实现平台换行
public class FileWriteDemo {
public static void main(String[] args) throws IOException{
File file = new File("F:" + File.separator + "File" + File.separator + "cc.txt");
FileWriter fw = new FileWriter(file);
String strValue = "aaaa";
fw.write(strValue);
//fw.write("\r\n");
//字符流每次都要刷新
fw.flush();
fw.close();
System.out.println("=======读取数据========");
FileReader fr = new FileReader(file);
char[] charStr = new char[(int)file.length()];
//int len = 0;
while(fr.read()!=-1){
System.out.println( new String(charStr));
}
}
}
4、总结 :
1、通过以上的学习发现字节流与字符流在操作上并没有任何区别,只是操作单元不同,其具体区别:字节流操作时是直接与文件本
身操作的,而字符流在操作文件时是在使用缓冲区的字节流在操作,因此对应的在字节流在操作文件时即使不关闭资源(flush/close)文件也能输出,但是字符流在操作时就一定要进行资源的处理[flush/close]不然不会输出任何内容。
2、对于流的操作
1、明确数据源与目的地
数据源 : 就是需要读取,可以使用字符流/字节流【Reader/FileInputStream】
硬盘、内存、键盘输入的内容[System.in]
目的地 : 就是需要写入内容的地方,可以使用字符流/字节流【Write/FileOuptStream】
硬盘、内存、控制台[System.out]
2、操作说明
对于纯文本 : 就使用字符流操作【Reader/Write】
而不是 : InputStream/OutputStream