基本知识
主要用的是这些
各流详解
FileWriter
将文本内容写入文本文件中
write写入单个字符
示例如下:
若d:/a.txt不存在,FileWriter会自动创建一个新文件
若d:/a.txt存在,FileWriter会清空文件中的原有内容
public class FileWriterTest {
public static void main(String[] args) {
FileWriter fw = null;
try {
//1.构造FileWriter类型的对象并与d:/a.txt相关联
fw = new FileWriter("d:/a.txt");
//2.通过流对象写入数据内容
fw.write('a');
System.out.println("写入数据成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流对象并释放有关资源
if(null != fw) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
若想以追加的方式创建对象去关联文件
fw = new FileWriter("d:/a.txt");
改为
fw = new FileWriter("d:/a.txt",true);
就可以在原内容上追加内容,文件不存在也会创建新文件
写入多个字符
void write(char[] cbuf,int off,int len)
将指定字符数组从偏移量off开始的len个字符写入此文件输出流
public class FileWriterTest {
public static void main(String[] args) {
FileWriter fw = null;
try {
//1.构造FileWriter类型的对象并与d:/a.txt相关联
fw = new FileWriter("d:/a.txt");
//2.通过流对象写入数据内容
fw.write('a');
//准备一个字符数组
char[] cArr = new char[]{'A','B','C','D'};
//将字符数组的一部分写进去
fw.write(cArr,1,2);//BC
//将整个字符数组写进去
fw.write(cArr);//ABCD
System.out.println("写入数据成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流对象并释放有关资源
if(null != fw) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
结果如下
则每当写入一个字符后,文件中的读写位置自动后退一位
上面代码整个流程是fw = new FileWriter(“d:/a.txt”);创建连接后不断写入,直到close
FileReader
从文本文件中读取内容
public class FileReaderTest {
public static void main(String[] args) {
FileReader fr = null;
try {
//1.构造FileReader类型的对象与d:/a.txt文件连接
fr = new FileReader("d:/a.txt");
//2.读取数据内容并打印
int fe = fr.read();
System.out.println("读取的单个字符是"+(char)fe);
} catch (IOException e) {
e.printStackTrace();
} finally {
//3.关闭流对象并释放资源
if(null!=fr){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileReader中其他方法的使用
public class FileReaderTest {
public static void main(String[] args) {
FileReader fr = null;
try {
//准备一个字符数组来保存读到的字符
fr = new FileReader("d:/a.txt");
char[] cArr = new char[5];
//期望读取字符数组中的一部分空间,也就是读取3个字符放入数组cArr中下标从1开始的位置上
int res = fr.read(cArr,1,3);//所以cArr下标为0的地方空着
System.out.println("实际读取到的字符个数是"+res);
for(char cv:cArr){
System.out.println("实际读取到的字符是"+(char)cv);
}
System.out.println("-----------------------------------");
} catch (IOException e) {
e.printStackTrace();
} finally {
//3.关闭流对象并释放资源
if(null!=fr){
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件字符流实现文件的拷贝
public class FileCharCopyTest {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
//1.创建FileReader类型的对象与d:/a.txt关联
fr = null;
fr = new FileReader("d:/a.txt");
//2.创建FileWriter类型的对象与d:/b.txt关联
fw = null;
fw = new FileWriter("d:/b.txt");
//3.不断的从输入流中读取数据内容并写入输出流中
System.out.println("开始拷贝!");
int res = 0;
while((res=fr.read())!=-1){
fw.write(res);
}
System.out.println("拷贝成功!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流对象并释放资源
try {
if(null != fw) {
fw.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null!=fr) {
fr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字节流
用于拷贝任意文件,如图片等
FileOutputStream&FileInputStream
实现图片的拷贝
public class PictureCpoyTest {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
//1.创建FileInputStream类型的对象与d:/要复制的图片.png关联
fis = null;
fis = new FileInputStream("d:/要复制的图片.png");
//2.创建FileOutputStream类型的对象与d:/复制成功的图片.png关联
fos = null;
fos = new FileOutputStream("d:/复制成功的图片.png");
//3.不断的从输入流中读取数据内容并写入输出流中
System.out.println("开始拷贝图片!");
int res = 0;
while((res = fis.read()) !=-1){
fos.write(res);
}
System.out.println("拷贝图片完成!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流对象并释放资源
try {
if(null!=fos) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null!=fis) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
拷贝视频文件
- 方式一:如拷贝图片一样,按单个字节为单位来拷贝,每次读取一个字节写入一个字节。但这样文件大时拷贝效率低
- 方式二:准备一个和文件大小一样的缓冲区,一次性将文件中所有内容取到缓冲区中然后一次性写进去
public class Mp4CopyTest {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = null;
fis = new FileInputStream("d:/要复制的视频.mp4");
fos = null;
fos = new FileOutputStream("d:/复制成功的视频.mp4");
System.out.println("开始拷贝视频!");
int len = fis.available();
System.out.println("获取到的文件大小是:"+len);
byte[] bArr = new byte[len];
int res = fis.read(bArr);
System.out.println("读取到的文件大小是:"+res);
fos.write(bArr);
System.out.println("拷贝视频完成!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(null!=fos) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null!=fis) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
方式二明显在效率上比方式一快很多
缺点:若文件过大时,无法申请和文件大小一样的缓冲区,因为真实内存不足
- 方式三(推荐使用)
准备一个相对适当的缓冲区,分多次将文件拷贝完成
public class RealMeathodCopyTest {
public static void main(String[] args) {
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = null;
fis = new FileInputStream("d:/要复制的视频.mp4");
fos = null;
fos = new FileOutputStream("d:/复制成功的视频.mp4");
System.out.println("开始拷贝视频!");
byte[] bArr = new byte[1024];
int res = 0;
while((res = fis.read(bArr))!=-1){
fos.write(bArr,0,res);
}
System.out.println("拷贝视频完成!");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(null!=fos) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null!=fis) {
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
缓冲字节流
BufferedInputStream
java.io.BufferedInputStream类主要用于描述缓冲输入流
BufferedOutputStream
java.io.BufferedOutputStream类主要用于描述缓冲输出流,此时不用为写入的每个字节调用底层系统
BufferedInputStream自身会给给一个1024×8=8192的缓冲区
public class BufferedCopyTest {
public static void main(String[] args) {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
//1.创建BufferedInputStream类型的对象与d:/要复制的视频.mp4关联
bis = null;
bis = new BufferedInputStream(new FileInputStream("d:/要复制的视频.mp4"));
//2.创建BufferedOutputStream类型的对象与d:/复制成功的视频.mp4关联
bos = null;
bos = new BufferedOutputStream(new FileOutputStream("d:/复制成功的视频.mp4"));
//3.不断的从输入流中读取数据并写入输出流中
System.out.println("开始拷贝视频!");
byte[] bArr = new byte[1024];
int res = 0;
while((res = bis.read(bArr))!=-1){
bos.write(bArr,0,res);
}
System.out.println("拷贝视频完成!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流并释放有关资源
if(null!=bos) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null!=bis) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
这段代码在copy中进一步再给一个1024的缓冲区
不给缓冲区的话中间那段就是这样的
System.out.println("开始拷贝视频!");
int len = bis.available();
byte[] bArr = new byte[len];
//byte[] bArr = new byte[1024];
int res = 0;
while((res = bis.read(bArr))!=-1){
bos.write(bArr,0,res);
}
System.out.println("拷贝视频完成!");
在以后开发中涉及到文件的拷贝使用缓冲流较好,效率高
缓冲字符流
字符流只能与文本文件关联
BufferedWriter类
java.io.BufferedWriter类主要用于写入单个字符、字符数组以及字符串到输出流中
BufferedReader类
行分隔符就是换行
缓冲字符流实现文件的拷贝
public class BufferedCharCopyTest {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
//1.创建BufferedReader类型的对象与d:/a.txt关联
br = null;
br = new BufferedReader(new FileReader("d:/a.txt"));
//2.创建BufferedWriter类型的对象与d:/b.txt关联
bw = null;
bw = new BufferedWriter(new FileWriter("d:/b.txt"));
//3.不断的从输入流中读取数据并写入输出流中
System.out.println("开始拷贝视频!");
String str = null;
while((str = br.readLine()) !=null){
bw.write(str);
bw.newLine();//行分隔符
}
System.out.println("拷贝视频完成!");
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流并释放有关资源
if(null!=bw) {
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null!=br){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
打印流和转换流模拟聊天的功能实现
PrintStream类
java.io.PrintStream类主要用于更加方便地打印各种数据内容。
PrintWriter类
java.io.PrintWriter类主要用于将对象的格式化形式打印到文本输出流。
案例题目
不断地提示用户输入要发送的内容,若发送的内容是"bye"则聊天结束,否则将用户输入的内容写
入到文件d:/a.txt中。
要求使用BufferedReader类来读取键盘的输入 System.in代表键盘输入
要求使用PrintStream类负责将数据写入文件
public class PrintStreamChatTest {
public static void main(String[] args) {
BufferedReader br = null;
PrintStream ps = null;
try {
br = new BufferedReader(new InputStreamReader(System.in));
ps = new PrintStream(new FileOutputStream("d:/a.txt"));
while(true) {
//1.提示用户输入要发送的聊天内容并使用变量来记录
System.out.println("请输入聊天内容");
//BufferedReader的构造方法需要的是Reader类型的引用,但Reader是抽象类,实参只能传递子类的对象 字符流
//System.in是键盘输入,且是InputStream类型的 字节流
String str = br.readLine();
//2判断用户输入的内容是否为"bye",若是则结束
if ("bye".equals(str)) {
System.out.println("聊天结束!");
break;
}
//3.若不是则将用户输入的内容写入d:/a.txt中
else {
ps.println(str);
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//4.关闭流对象并释放有关资源
if(null!=ps) {
ps.close();
}
try {
if(null!=br) {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
优化一下
上面要用到 InputStreamReader类
java.io.InputStreamReader类主要用于实现从字节流到字符流的转换
顺便提到 OutputStreamWriter类
java.io.OutputStreamWriter类主要用于实现从字符流到字节流的转换