流概述:
流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种。I/O(Input/Output,输入/输出)流提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。
输入和输出模式如下图:
输入/输出流
所有输出流泪都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类,所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。
字符流和字节流的区别:
因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。
1.读写单位不同,字节流以字节为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
2.处理对象不同,字节流能处理所有的类型的数据,而字符流自能处理字符类型的数据
3.字节流在操作的时候不会用到缓冲区,是文件本身的直接操作,而字符流在操作时会用到缓冲区。
总的来说,一般都选择用字节流,除了纯文本的情况用字符流更加高效。
示例(将一些文字存储到文件中):
/*
思路:因为是纯文本的,所以使用字符流
因为是写入到文件中,所以要创建一个输出流对象,并且要明确一个目的地,如果目的地没有
文件那么就自动创建一个,如果存在就覆盖
*/
import java.io.*;
class FileWriterDemo
{
public static void main(String[] args) throws IOException
{
FileWriter fw = new FileWriter("FileDemo.txt");//创建目的文件
fw.write("abc");//用write方法写入数据
fw.flush();//刷新流数据,将数据写入到目的地中
fw.close();//关闭流
}
}
如果创建文件对象时,使用FileWriter fw = new FileWriter("FileDemo.txt",true) 那么目的中的文件就不会被覆盖,而是会续写。
示例(将一个文件中的数据在控制台显示):
import java.io.*;
class FileReaderDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("FileDemo.txt");//选择源文件
int i = 0;
while((i=fr.read())!=-1)
{
System.out.println((char)i); //强转之后输出到控制台
}
fr.close();//关闭流
}
}
运行结果:
示例(复制一个文本文件):
import java.io.*;
class CopyDemo
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("FileDemo.txt"); //读取一个已有的本文文件并用字符流关联
FileWriter fw = new FileWriter("FileDemoCopy.txt");//创建一个目的文件用来存储数据
int i = 0;
while((i=fr.read())!=-1)//循环读写
{
fw.write(i);
}
fw.close();
fr.close();
}
}
可以使用缓冲区提高读写效率。 缓冲区:就像是喝水,一滴一滴的喝想要解渴太久了,用水杯将水装满之后再喝就快多了。
import java.io.*;
public class BufferedWriterDemo{
public static void main(String[] args) throws IOException{
FileWriter fw = new FileWriter("buf.txt" );
//创建一个字符写入流的缓冲区对象,并且指定与要被缓冲的流对象相关联
BufferedWriter bufw = new BufferedWriter(fw);
for(int x = 1; x <= 4; x++){
//将数据先写入到缓冲区中
bufw.write( "abcdef" + x);
//换行方法:newLine();
bufw.newLine();
bufw.flush();
}
//将数据刷目的地中
bufw.flush();
//关闭缓冲区
fw.close();
}
}
操作文本文件用字符流更高效。不过字节流的运用更广。例如音频视屏文件都只能用字节流来操作。
示例(复制一个map3文件,运用缓冲区更加高效):
import java.io.*;
class CopyMp3Demo
{
public static void main(String[] args) throws IOException
{
FileInputStream fis = new FileInputStream("1.map3"); //读取已有文件并用字节流关联
FileOutputStream fos = new FileOutputStream("2.mp3"); //创建一个目的存储数据
byte[] buf = new byte[1024]; //创建缓冲区
int len = 0;
while((len=fis.read(buf))!=-1) //字节不断的写入数据
{
fos.write(buf,0,len);
}
fis.close(); //关闭流
fos.close();
}
}
写IO流的程序。首先应该明确几点
1源和目的
源 InputStream 或者 Reader
目的 OutputStream 或者 Writer
2是否是纯文本
纯文本就用字符流 Reader 或者 Writer
不是纯文本就用字节流 InputStream 或者 OutputStream
另外还有: 判断是否要加入缓冲区功能
关于转换流:
InputStreamReader 字节到字符,解码
OutputStreamWriter 字符到字节,编码
为了方便字符流和字节流之间的操作
当字节流中的数据都是字符时,将字节转换成字符操作更高效
示例(将输入的字母转换成小写的,并在控制台显示):
import java.io.*;
class TranDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while((line=bufr.readLine())!=null)
{
if("886".equals(line))
break;
bufw.write(line.toLowerCase());
bufw.newLine();
bufw.flush();
}
}
}
运行结果:
示例(将键盘输入的数据存储到文件中):
分析:
源:键盘 System.in
目的:文件 FIle
是否纯文本: 是
是否要使用缓冲区:是
另外:将读取的字节流数据转换成字符流操作更高效,所以要用到转换流
import java.io.*;
class TranDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("TranDemo.txt")));
String line = null;
while((line=bufr.readLine())!=null)
{
if("886".equals(line))
break;
bufw.write(line);
bufw.newLine();
bufw.flush();
}
}
}
FileWriter其实就是转换流指定了本机默认码表的体现,而且这个转换流的子类对象,可以方便操作文本文件。
简单说:操作文件的字节流+本机默认的编码表。
这是按照默认码表来操作文件的便捷类
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"GBK");
如果操作文本文件需要明确具体的码表,FileWriter就不行了,必须用转换流。
示例:
示例(将一个指定的txt文件中的内容在控制台显示):
import java.io.*;
public class TransStreamDemo {
public static void main(String[] args) throws IOException {
writeText();
}
public static void writeText() throws IOException {
//下面这句代码等同于FileWriter fw = new FileWriter("b.txt");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt" ),"UTF-8" );
osw.write( "您好");
osw.close();
}
}
import java.io.Exception
class TransStreamDemo {
public static void main(String[] args) throws IOException {
writeText();//调用方法
}
public static void writeText() throws IOException {
InputStreamReader isr = new InputStreamReader(new FileInputStream("demo.txt" ),"UTF-8" );//确定一个源并用流联立
char[] buf = new char[10];//创建一个缓冲区
int len = isr.read(buf); //读取文档中的内容
String str = new String(buf,0,len); //将数据封装到字符串
System.out.println(str);
isr.close(); //流关闭
}
}
示例(获取目录下的文件和文件的名称):
import java.io.*;
class FileListDemo{
public static void main(String[] args) throws IOException {
listDemo();
}
public static void listDemo() throws IOException {
File file = new File("c:\\" );
//获取目录下的文件以及文件夹的名称,包含隐藏文件
//调用list方法的File对象中封装的必须是目录,否则会产生NullPointerException
//如果访问的是系统级目录也会发生空指针异常
//如果目录存在但是没有内容,会返回一个数组,但是长度为0
String[] names = file.list();
for(String name : names){
System.out.println(name);
}
}
}
示例(获取D盘下java文件夹中.java结尾的文件):
import java.io.*;
class FileListDemo{
public static void main(String[] args){
listDemo(); //调用listDemo()方法
}
public static void listDemo(){
File dir = new File("d:\\java" ); //读取指定目录
String[] names = dir.list( new FilterByJava()); //获取文档名称
for(String name : names){ //高级的for循环递归
System.out.println(name);
}
}
}
class FilterByJava implements FilenameFilter{
public boolean accept(File dir,String name){//判断文件名称是否符合
return name.endsWith(".java" );
}
}
示例(将指定目录下所有.java文件拷贝到另一个目的中,并改为.txt格式):
import java.io.*;
import java.util.*;
class JavaDocDemo
/*
要求:编写程序,将指定目录下所有.java文件拷贝到另一个目的中,并将扩展名改为.txt
思路 1.用递归的方法遍历指定目录下的文件
2.将以.java结尾的文件名存入集合
3.将以.java结尾的文件复制到指定目的并改名
*/
{
public static void main(String[] args) throws Exception
{
ArrayList<String> list = new ArrayList<String>();//定义集合用来存储java文件的名字
File src = new File("C:\\Users\\zlf\\Desktop\\java");//源文件的路径
File des = new File("C:\\Users");//目的文件路径
if(!des.exists())//判断目的文件是否存在,不存在创建
des.mkdirs();
fileTolist(src,list);//将源文件中的Java文件的名字存入到集合中
for(String fileName:list)
writeTofile(src,des,fileName);//将源文件中的Java文件存入到目的文件夹中
}
//将源文件中的Java文件的名字存入到集合中
public static void fileTolist(File file,List<String>list)
{
File[] files = file.listFiles();//获取源文件夹中的文件
for(File f:files)//遍历文件并将Java文件的名字存到集合中
{
list.add(f.getName());
}
}
//将源文件中的Java文件存入到目的文件夹中
public static void writeTofile(File src,File des,String fileName)throws Exception
{
BufferedReader bufr = new BufferedReader(new FileReader(new File(src,fileName)));
BufferedWriter bufw = new BufferedWriter(new FileWriter(new File(des,fileName.replace(".java",".txt"))));
String line = null;
while((line=bufr.readLine())!=null)
{
bufw.write(line);
bufw.newLine();
bufw.flush();
}
bufw.close();
bufr.close();
}
}