文件专属流
文章目录
- 文件专属流
- FileInputStream流
- FileInputStream初步读取
- FileInputStream循环读
- IDEA默认当前路径
- 往byte数组中读
- 最终版FileInputStream流
- FilleInputStream类的其他方法
- FileOutputStream流
- 回顾:
- 字节流文件的复制
- FileReader流
- 代码示例
- FileWriter流
- 代码示例:
- 字符流文件复制
FileInputStream流
FileInputStream初步读取
创建文件字节输入流对象:
FileIputStream file = new FileInputStream("文件路径")
代码示例:
java.io.FileInputStream:
1.文件字节输入流、万能的,任何类型的文件都可以采用这个流来读
2.字节的方式,完成输入的操作,完成读的操作(硬盘------》内存)
public class FileInputStream01 {
public static void main(String[] args) {
FileInputStream stream = null ;
try {
//创建文件字节输入流对象
//以下都是采用了:绝对路径的方式
//文件路径:E:\Typora笔记\JavaSE\IO流\语录
//采用这个路径也可以:E:/Typora笔记/JavaSE/IO流/语录.txt
stream = new FileInputStream("E:\\Typora笔记\\JavaSE\\IO流\\语录.txt");
//开始读
//这个方法的返回值是:读取到的“字节”本身
int readData = stream.read();
System.out.println(readData);//229
//再读
readData = stream.read();
System.out.println(readData);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//在finally语句块当中确保流一定关闭
if (stream!=null) { //避免空指针异常
//关闭流的前提是:流不是空,流是null的时候没必要关闭
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
运行结果:
229
189
注意:当再读时,会读取下一个字节
当读取的数值为 -1 时,文本字节读取完毕
FileInputStream循环读
在创建文件字节输入流对象的try 语句块中,添加循环
// while (true){
// int readData = fis.read();
// if (readData==-1){
// break;
// }
// System.out.println(readData);
// }
//改良while循环
int readDate = 0 ;
while ((readDate = fis.read()) != -1) {
System.out.println(readDate);
运行结果(部分):
229
189
147
分析这个程序的缺点:
一次读取一个字节byte,这样内存和硬盘交互太频繁,基本上时间、资源都消耗在交互上面了。
能不能一次读取多个字节呢?可以
IDEA默认当前路径
//相对路径的话呢?相对路径一定是从当前所在位置作为起点开始找!
//IDEA默认的当前路径是哪里?工程Project的根就是IDEA的默认当前路径
// fis = new FileInputStream("temp.txt");
fis = new FileInputStream("基础语法/src/com/IO/IO流");
往byte数组中读
在创建文件字节输入流对象的try 语句块中,添加byte数组
//开始读,采用byte数组,一次读取多个字节,最多读取 “数组.length” 个字节
byte[] bytes = new byte[4];
//这个方法的返回值是:读取到的字节数量(不是字节本身)
int readCount = fis.read(bytes);
System.out.println(readCount);
//将字节数组全部转换成字符串
//System.out.println(new String(bytes));
//不应该全部都转换,应该是读取了多少个字符,转换多少个
System.out.println(new String(bytes,0 ,readCount));
//虽然读取了四个字节,但是会把第一次读取的四个字节进行覆盖
readCount = fis.read(bytes);
System.out.println(readCount);
System.out.println(new String(bytes));
//读取几个字节就返回几 ,读取不到任何字节返回-1
最终版FileInputStream流
public class FileInputStream04 {
public static void main(String[] args) {
FileInputStream fils = null ;
try {
fils = new FileInputStream("E:/Typora笔记/JavaSE/IO流/语录.txt");
//准备一个byte数组
byte[] bytes= new byte[4];
// while (true) {
// int readCount = fils.read(bytes);
// if (readCount==-1) {
// break;
// }
// //把byte数组转换成字符串,读到多少个转换多少个
// System.out.print(new String(bytes,0,readCount));
int readCount = 0 ;
while ((readCount = fils.read(bytes)) != -1) {
System.out.print(new String(bytes,0,readCount));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fils!=null){
try {
fils.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
运行结果:
Do you love life ? Then do not squander time ; for that's the stuff life is made of .
如果是文件中的内容为中文,可以改变数组长度【乱码的原因是,中文字节只读取了一半】或改变编码为UTF-8
FilleInputStream类的其他方法
1.int available() ; 返回流当中剩余的没有读到的字节数量
try{
fils = new FileInputStream("E:/Typora笔记/JavaSE/IO流/语录2.0.txt");
System.out.println("总字节数量:"+fils.available());
//读1个字节
int readByte = fils.read();
//剩下字节:84
System.out.print("还剩下几个字节未读:"+fils.available());
}
运行结果:
总字节数量:85
还剩下几个字节未读:84
1.1这个方法有什么所有呢
不需要循环了 , 直接读一次就行了
byte[] bytes = new byte[fils.available()];
这种方式不适合太大的文件,因为byte数组不能太大
int readCount = fils.read(bytes);//85
System.out.println(new String(bytes,0,readCount));
运行结果:
Do you love life ? Then do not squander time ; for that's the stuff life is made of .
注意!:这种方式不适合太大的文件,因为byte数组不能太大
2.long skip(long n) ; 跳过几个字节不读
try {
fils = new FileInputStream("E:/Typora笔记/JavaSE/IO流/语录2.0.txt");
fils.skip(3);
System.out.println(fils.read());//121
}
...
运行结果:
121
这里输出的是字节
FileOutputStream流
创建文件字节输出流对象:
FileOutputStream fos = new FileOutputStream("文件路径")
代码示例:
FileOutputStream fos = null ;
try {
//这种方式谨慎使用,这种方式会先将原文件清空,然后重新写入
fos=new FileOutputStream("E:/Typora笔记/JavaSE/IO流/语录2.0.txt");
//开始写
byte[] bytes ={98,99,100,101,102};
//将byte数组全部写出
fos.write(bytes);
//将byte数组的一部分写出!
fos.write(bytes,0,2);
//写完之后一定要刷新
fos.flush();
}
当文件路径所指的文件不存在时,会新建
上述写入会先将原文件清空,然后重新写入,那如何解决呢?在文件尾添加想要的内容?
在文件路径后,添加true即可解决
fos=new FileOutputStream("E:/Typora笔记/JavaSE/IO流/语录2.0.txt",true);
回顾:
将字符串转换为byte数组
String s = "采三秀兮于山间,石磊磊兮葛蔓蔓";
//将字符串转换为byte数组
byte[] bs = s.getBytes();
字节流文件的复制
- 使用FileInputStream + FileOutputStream完成文件的拷贝
- 拷贝的过程应该是一边读,一边写
- 使用以上的字节流拷贝文件的时候,文件类型随意,万能的,什么样的文件都能拷贝
public class Copy01 {
public static void main(String[] args) {
FileInputStream fis = null ;
FileOutputStream fos = null ;
try {
//创建一个输入流对象
fis = new FileInputStream("E:\\Typora笔记\\JavaSE\\集合\\图\\Collection体系集合.png");
//创建一个输出流对象
fos = new FileOutputStream("E:/Typora笔记/JavaSE/Collection体系集合.png",true);
//最核心问题:一边读,一边写
byte[] bytes = new byte[1024*1024];//一次最多拷贝1m
int readCount = 0 ;
if ((readCount=fis.read(bytes))!=-1) {
fos.write(bytes,0,readCount);
}
//刷新
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//分开try,不要一起try,不然第一个异常,第二个就关闭不了了
//一起try的时候,其中一个出现异常,可能会影响另一个流的关闭
if (fis!=null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos!=null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileReader流
操作基本与FileInputStream相同
但FileReader流使用的不是 byte[] 数组,而是使用 char[] 数组
- FileReader:
- 文件字符输入流,只能读取普通文本
- 读取文本内容时,比较方便,快捷
代码示例
public static void main(String[] args) {
FileReader reader = null ;
try {
reader = new FileReader("E:/Typora笔记/JavaSE/IO流/语录2.0.txt");
char[] chars = new char[4];//一次读取4个字符
int readerCount = 0 ;
while((readerCount = reader.read(chars))!=-1){
System.out.print(new String(chars,0,readerCount));
}
运行结果:
采三秀兮于山间,石磊磊兮葛蔓蔓------屈原-《九歌·山鬼》
对字符数组进行遍历
public static void main(String[] args) {
FileReader reader = null ;
try {
reader = new FileReader("E:/Typora笔记/JavaSE/IO流/语录2.0.txt");
//准备一个char数组
char[] chars = new char[4];
//往char数组中读
reader.read(chars);
for (char c : chars) {
System.out.println(c);
}
}
运行结果:
采
三
秀
兮
FileWriter流
- FileWriter:
- 文件字符输出流,写
- 只能输出普通文本
代码示例:
public class FileWriterTest {
public static void main(String[] args) {
FileWriter writer = null ;
try {
writer = new FileWriter("E:/Typora笔记/JavaSE/IO流/语录2.0.txt");
//如果不想进行覆盖,而是后加
// writer = new FileWriter("E:/Typora笔记/JavaSE/IO流/语录2.0.txt",true);
char[] chars = {'我','是','中','国','人'};
writer.write(chars);//我是中国人
writer.write(chars,2,3);
writer.write("我是一名java软件工程师!");
writer.write("\n");
writer.write("Hello world!");
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}finally{
if (writer!=null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
运行结果(txt文本内):
我是中国人中国人我是一名java软件工程师!
Hello world!
如果不想进行覆盖,而是后加,则在路径后面加 true
writer = new FileWriter(“E:/Typora笔记/JavaSE/IO流/语录2.0.txt”,true);
注意:只能读普通文本文件,其他的都不能读(包括word文本)
字符流文件复制
使用FileReader、FileWriter进行拷贝的话,只能拷贝“普通文本”文件
public class Copy {
public static void main(String[] args) {
FileReader reader = null ;
FileWriter writer = null ;
try {
//读
reader = new FileReader("E:/Typora笔记/JavaSE/IO流/语录2.0.txt");
//写
writer = new FileWriter("E:/Typora笔记/JavaSE/IO流/语录3.0.txt");
//一边读一边写:
char[] chars = new char[1024*512];//1M
int readerCount = 0;
while ((readerCount = reader.read(chars)) != -1) {
writer.write(chars,0,readerCount);
}
writer.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (reader!=null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (writer!=null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
- 能用记事本编辑的都是普通文本文件
- 普通文本文件和后缀无关,不一定都是 .txt【.java也是普通文本文件】