/** * 1、关于IO流的分类: * 一、按流的方向进行分类:(以内存为参照物) * 往内存中取,称为输入(Input)/读(Read) * 从内存中出去,称为输出(Output)/写(Write) * 二、按读取数据方式不同进行分类: * 字节流:按字节的方式读取数据,一次读取1个字节byte, * 这种流是万能的,什么类型的文件都可读取。 * 字符流:按字符的方式读取数据,一次读取1个字符, * 这种流只能读取纯文本文件(如.txt)。 * 普通文本文件:可以用记事本打开的文件为普通文本文件。 * 2、IO流主要研究方向: * 如何new流对象 * 调用流对象的哪个方法是读,哪个方法是写。 * 3、IO流四大家族:(下面四个都是抽象类) * java.io.InputStream 字节输入流 * java.io.OutputStream 字节输出流 * "以Stream结尾的都是字节流" * java.io.Reader 字符输入流 * java.io.Writer 字符输出流 * "以Reader/Writer结尾的都是字符流" * 所有的流都实现了: * java.io.closeable接口,都是可关闭的,都有close()方法。 * 建议用完流一定要关闭。 * 所有的输出流都实现了: * java.io.flushable接口,都是可刷新的,都有flush()方法。 * 建议输出流在最终输出后,应使用flush()刷新一下, * 这个刷新表示将通道中剩下未输出的强制输出完(即清空) * 注意:若flush()可能会导致数据丢失。 * 4、java.io包下主要需要掌握的流(16个): * 文件专属: * FileInputStream * FileOutputStream * FileReader * FileWriter * 缓冲流专属: * BufferedReader * BufferedWriter * BufferedInputStream * BufferedOutputStream * 转换流:(将字节流转换为字符流) * InputStreamReader * OutputStreamWriter * 数据流专属: * DataInputStream * DataOutputStream * 标准输出流: * PrintWriter * printStream * 对象专属流: * ObjectInputStream * ObjectOutputStream * * */
FileInputStream:
/**
* 关于FileInputStream:
* 1、文件字节输入流,任何类型的文件都可采用这个流来读。
* 2、以字节的方式,完成输入的操作/读的操作(硬盘-->内存)
*/
public class FileInputStreamTest01 {
public static void main(String[] args) {
FileInputStream fis = null;
try{
fis = new FileInputStream("D:\\java\\javaas");//括号里跟一个文件路径
//循环读出,read()一次读取一个字节,交互频繁,
while(true){
int readData = fis.read();//进行数据读取,以一个字节为单位,读到末尾后放回-1
if(readData == -1){
break;
}
System.out.println(readData);
}
//改造while循环
int readData1 = 0;
while((readData1 = fis.read()) != -1){ //while()括号中跟一个boolean类型值
System.out.println(readData1);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
if (fis != null) {
//如果不为空
try{
fis.close();//关闭流
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* FileInputStream类的其他常用方法:
* int available(); 返回流中剩余的没有读到的字节数量
* long skip(long n); 跳过几个字节不读
*/
public class FileInputStreamTest02 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("untitled/src/HaHa");//abcdj
int readData = fis.read();//读一个字节
//available()
System.out.println("剩下多少个字节未读:"+fis.available());//输出4
//无需循环,即可全部读出
byte[] bytes = new byte[fis.available()];
int readCount = fis.read(bytes);//5
System.out.println(new String(bytes));//abcdj
//Skip
fis.skip(3);//跳过3个字节
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* int read(byte[] b)
* 一次读取b.length个字节,往byte[]数组中读。
*/
public class ReadTest01 {
public static void main(String[] args) {
FileInputStream fis =null;
try {
fis = new FileInputStream("untitled/src/HaHa");//这个路径txt文本中内容为abcdj
//准备一个3个长度的byte数组,一次最多读取3个字节
byte[] bytes = new byte[3];
int readCount = fis.read(bytes);//这个方法返回值是读取到的字节数量(read()是字节本身)
System.out.println(readCount);//第一次读到了3个字节。输出3
//将字节数组全部转换成字符串
System.out.println(new String(bytes));//输出abc
//读取多少个字节,转换为多少个字符串
System.out.println(new String(bytes,0,readCount));//输出abc
readCount = fis.read(bytes);//第二次只能读到2个字节
System.out.println(readCount);//输出2
//将字节数组全部转换成字符串
System.out.println(new String(bytes));//输出djc
System.out.println(new String(bytes,0,readCount));//输出dj
readCount = fis.read(bytes);//一个字节都没有读取到
System.out.println(bytes);//输出-1
//利用循环读出(升级版)
int readCount1 = 0;
while((readCount1 = fis.read(bytes)) != -1){
//将byte数组转换成字符串,读到多少个转换多少个
System.out.println(new String(bytes,0,readCount1));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileOutputStream:
/**
* 文件字节输出流,负责写。
* 从内存到硬盘
*/
public class FileoutputTest01 {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
//往该文件中写入内容,若文件不存在,则自动新建文件。
//这种方式会先将原文件清空,然后重新写入
//fos = new FileOutputStream("wenjian");
//以追加的方式在文件末尾写入,不会清空原文件内容
//这里的true表示是否在文本末尾追加
fos = new FileOutputStream("wenjian001",true);
byte[] bytes ={97,98,99,100,101};
//将byte数组全部写出
fos.write(bytes);//abcde
//将byte数组一部分写出
fos.write(bytes,0,2);//ab
//写完之后,需要刷新以下
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字节流拷贝:
/**
* 利用FileInputStream和FIleOutputStream完成文件拷贝
* 拷贝过程为 一边读,一边写(如:c盘--(输入/读)-->内存--(输出/写)-->d盘)
*/
public class CopyTest1 {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//创建输入流对象
fis = new FileInputStream("wenjian");
//创建输出流对象
fos = new FileOutputStream("wenjian2");
//核心:一边读一边写
byte [] bytes = new byte[1024 * 1024];//一次最多拷贝1MB
int readCount = 0;
while((readCount = fis.read(bytes)) !=-1){
fos.write(bytes,0,readCount);
}
//刷新
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//输入输出流分开关闭,防止一个出现异常时,另一个无法关闭
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流拷贝:
/**
* FileReader和FileWriter操作差不多,
* 只不过这两个使用的时char数据类型,且FileWriter的写操作可以直接写入字符串
* 如:writers.write("直接放入字符串");
*
* 以下实现文本拷贝操作
*/
public class CopuTest02 {
public static void main(String[] args) {
FileReader reader = null;
FileWriter out = null;
try {
reader = new FileReader("wenjian");//读某个文件
out = new FileWriter("wenjian10086");//往某个文件中写入
char[] chars = new char[1024 * 512];//1MB
int readCount = 0;
while((readCount = reader.read(chars)) != -1){
out.write(chars,0,readCount);
}
//刷新
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}