IO流分为字节流和字符流,首先在介绍IO流的同时先介绍下文件的基本操作:
对于定位一个文件或者文件夹:
File file = new File("d:\\abc\text.text");//可以
File file2 = new File("d:/text.text");//可以
File file3 = new File("d:\text.text");//不可以(\t属于制表符)
File file4 = new File("d:/abc/xyz");
上面的这个其实也就是定位以为文件或者文件夹,实际操作还需要根据具体方法:
file.createNewFile();//这个是创建一个新的文件;如果abc这个文件夹不存在,则报文件路径错。
file4 .mkdir();//这个是创建一个新的文件夹。要求前面的abc文件夹必须存在。
file4.mkdirs();//这个是在整个目录结构都不存在的情况下用这个创建。如果abc这个目录存在,那么创建失败;
file.isDirectory();//判断是否是文件夹
file.isFile();//判断是否是文件
file2.exists()//判断这个目录是否存在
file.list();//列出这个目录下的所有的文件以及文件夹,子目录不会出来。
文件操作中过滤文件:
public static void main(String[] args)
{
File file = new File("D:/abc/xyz/hello");
String[] strings = file.list(new FilenameFilter() {
//使用的是一个匿名类,也就是也就是有一个不知名的类实现了FilenameFilter这个接口,
//就可以重写这个方法,然后得到这个功能,其实这个就是一个策略模式
//这个也是返回所有文件的名字
@Override
public boolean accept(File dir, String name)
{
if(name.endsWith(".java"))//只有这个名字符合,才会放到这个string这个数组中来
{
return true;
}
else
{
return false;
}
}
});
for(String string: strings)
{
System.out.println(string);
}
}
接下来就是字符流和字节流:
首先理解下输入输出流:
输入/输出是相对于程序来说的。程序在使用数据时所扮演的角色有两个:一个是源,一个是目的。若程序是数据流的源,即数据的提供者,这个数据流对程序来说就是一个“输出数据流”(数据从程序流出)。若程序是数据流的终点,这个数据流对程序而言就是一个“输入数据流”(数据从程序外流向程序);
从功能上分为两大类:输入流和输出流。
从流结构上可分为字节流(以字节为处理单位或称面向字节)和字符流(以字符为处理单位或称面向字符)。
字节流:的输入流和输出流基础是InputStream和OutputStream这两个抽象类,字节流的输入输出操作由这两个类的子类实现。
字符流:是Java1.1版后新增加的以字符为单位进行输入输出处理的流,字符流输入输出的基础是抽象类Reader和Writer。
字节流和字符流。字节流(byte stream)为处理字节的输入和输出提供了方便的方法。例如使用字节流读取或写入二进制数据。字符流(character stream)为字符的输入和输出处理提供了方便。它们采用了统一的编码标准,因而可以国际化。当然,在某些场合,字符流比字节流更有效
声明::在最底层,所有的输入/输出都是字节形式的。基于字符的流只为处理字符提供方便有效的方法!!!(重)
读数据的逻辑为:
open a stream
while more information
read information
close the stream
写数据的逻辑为:
open a stream
while more information
write information
close the stream
具体流的分类:
节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。
过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。
字节流:
简单看下inputstream的用法:
public static void main(String[] args) throws Exception
{
InputStream is = new FileInputStream("d:/test.text");
// 输入流
// InputStream是所有输入流所要继承的一个类,并且所有实现这个类的类中都会提供
// 重写的方法read()方法,这里FlieInputStream类是一个专门用于文件输入流
// 这个类继承了InputStream这个类,参数是指定文件
byte[] buffer = new byte[200];
// 你肯定需要把你读取的字节流存放到一个Byte类型的数组里面所以这里定义了一个数组
// 但是那个while循环怎么来的呢,因为这个定义的数组只有200个,所以当你这个文件
// 中不止这么多那么就使用一个循环来获取
int length;
while(-1!=(length=is.read(buffer,0,200)))
// read的第一个参数指代的是我们读取的字节流存放的数组,第二个参数是从第几个
// 字节开始存,第三个就是每次存取的最大字节流的个数,但是实际可能没有这么多
// 因为可能这个文件中也就不到200
{
String string = new String(buffer,0,length);
//取出一个读一个,将读到的字节转化为字符串,这里使用的是一个String类
//提供的一个构造方法,就是讲byte类型的数组,转化为String类型的变量
//length就是实际读多长,我们就读多长
System.out.println(string);
}
is.close();
// 关闭流
}
outputstream相关用法:
public static void main(String[] args) throws IOException
{
OutputStream os = new FileOutputStream("d:/out.text",true);//这个是一个字节输出流
//当使用这个构造方法的时候就相当于在这个文件的后面增加
//当使用只有一个参数的,那么就会将这个文件里面的东西改为我要输入的东西,原来的东西就不存在了
//这个输入流不需要out.text这个文件必须存在,这个文件在write的时候就会自动创建
String string = "hello world";
byte[] buffer = string.getBytes();
os.write(buffer);//写字节流
//将buffer这个字节数组,通过这个文件输出流,将里面的内容写到那个文件输出流指定的文件当中
//将buffer里面的东西写到这个文件输出流里面去
//因为在FileOutputStream中只能write字节,这是一个字节的输出流
os.close();
}
带有缓冲的输出流:
public static void main(String[] args) throws IOException
{
OutputStream os = new FileOutputStream("D:/test.text");
BufferedOutputStream bof = new BufferedOutputStream(os);//提高效率
//这个是一个缓冲的,可以通过缓冲将东西输出到一个文件输出流,再把东西写到这个文件当中
//bof这个缓冲对应的就是os这个文件
bof.write("http://www.baidu.com".getBytes());
//这个必须得转化为字节,因为这个是一个字节流的输出流
//在输出流中write就是将参数中的东西输出到那个缓冲的输出流当中去,然后这个缓冲的输出流又包装了
//一个文件输出流,这样一来,就可以直接利用这个机制将buffer输出流里面的东西输出到一个文件当中
bof.close();
os.close();
}
字节输入输出流:
public static void main(String[] args) throws IOException
{
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("D:/out.text")));
//FileOutputStream就是一个节点流,其他的是过滤流,过滤流可以包装节点流
//DataOutputStream是一个字节的输出流,可以使用这个将不同类型的数据利用字节输出流
//将其放到这个字节输出流,然后再封装一个buffer输出流,将字节输出流中的东西放到buffer
//输出流当中,同样利用buffer输出流将这个里面的东西放到文件输出流当中,这样一来,就把这些数据
//写到了文件里面
byte b = 3;
int i = 12;
char ch = 'a';
float f = 2.3f;
dos.writeByte(b);
//将b写到这个字节输出流
dos.writeInt(i);
dos.writeChar(ch);
dos.writeFloat(f);
//写到字节输出流中不同的数据类型只能一个一个放进去,因为这里的定义了多个不同类型的数据
dos.close();
//其实最外面关闭了,最里面也就关闭了,所以这里只需要关闭最外面就行
// 装饰模式对应了又四个角色
/*
* 首先 是抽象构件角色:给出一个抽象的接口,以规范准备接受附加责任的对象:在这里就是那个InputStream
* 接着是具体构件角色:定义一个将要接受附加责任的类:指代的是FileInputStream
* 再者是抽象装饰角色:只有一个构件对象的引用,,并定义一个与抽象构件接口一致的接口:指代的是FilterInputStream
* 最后是具体装饰角色:负责给构件对象“贴上”附加的责任:在这里指代的是就是new DataInputStream
*/
DataInputStream dInputStream = new DataInputStream(new BufferedInputStream(new FileInputStream("D:/out.text")));
/*
* FileInputStream可以以字节的形式读文件,作为输入流,DataInputStream可以数据类型du
* 数据,也就是可以将字节形式的数据合成有用的数据类型
*/
System.out.println(dInputStream.readByte());
System.out.println(dInputStream.readInt());
System.out.println(dInputStream.readChar());
System.out.println(dInputStream.readFloat());
}
•FileInputStream和FileOutputStream
节点流,用于从文件中读取或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。
•BufferedInputStream和BufferedOutputStream
过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。
•DataInputStream和DataOutputStream
过滤流,需要使用已经存在的节点流来构造,提供了读写Java中的基本数据类型的功能。
•PipedInputStream和PipedOutputStream
管道流,用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。
System类的类变量out表示标准输出流
System类的类变量in表示标准输入流
字符流
这里简单看下几个例子:
首先字符流和字节流连接有两个中间(InputStreamRead和OutputStreamwriter)
public static void main(String[] args)throws Exception
{
FileOutputStream fos = new FileOutputStream("D:\\test.txt");
//字节流
OutputStreamWriter osw = new OutputStreamWriter(fos);
//相当于字符和字节之间的桥梁,这个是一个字符写到字节中的一个流
BufferedWriter bw = new BufferedWriter(osw);
bw.write("http://www.google.com");
//通过OutputStreamWriter这个输出流,实现字符流到字节流的转换
bw.write("\n");
//这个是一个换行的
bw.write("http://www.baidu.com");
bw.close();//记住这个在这里需要关闭
FileInputStream fis = new FileInputStream("D:\\test.txt");
//字节流
InputStreamReader isr = new InputStreamReader(fis);
//字符流,这个也是相当于是字节和字符之间的桥梁,因为从文件中以字节流读进来,然后经过这个
//桥梁吧字节的输入流转化为字符的输入流。下面再用一个缓冲的字符输入流将这个写到字符输入流,最后
//read出来
BufferedReader br = new BufferedReader(isr);
//字符流
// char[] ch = new char[100];
// br.read(ch);
// String string = ch.toString();
// System.out.println(string);
//
// System.out.println(br.readLine());//读一行,遇见换行就停止
// System.out.println(br.readLine());
// br.close();//一定要关闭
String string = br.readLine();
while(null != string)//if语句的话那么就只能输出一行
{
System.out.println(string);
string = br.readLine();//当读到最后一行这个while循环就结束
}
br.close();
}
从控制台:
public static void main(String[] args)throws IOException
{
InputStreamReader isr = new InputStreamReader(System.in);
//System.in从标准的输入设备中输入,然后使用包装的方法
BufferedReader bf = new BufferedReader(isr);
// String string ;
// while(null != (string = bf.readLine()))
// {
// System.out.println(string);
//
// }
String string = bf.readLine();
while(null != string)
{
System.out.println(string);
string = bf.readLine();
}
}
读字符数组:
public static void main(String[] args) throws IOException
{
String string = "akdhiushf";
char[] ch = new char[string.length()];
string.getChars(0,string.length(),ch,0);
//这个是将字符串转化啊为字符数组,
//将字符数组转化为字符串是String string = new String(ch)
CharArrayReader charArrayReader = new CharArrayReader(ch);
//读字符数组
int i;
while(-1 != (i = charArrayReader.read()))
//这里read方法返回的是一个整数,所以得到的这个i是那个字符所对应的整数,
//所以在下面需要将这个强制类型装换,这样就能将这个输出,否则输出的就是一个整数
{
System.out.println((char)i);
//读到的是一个整数,可以将这个转化为一个字符
}
}
字符流读文件:
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("D:/FileReader1.java");
BufferedReader br = new BufferedReader(fr);
String string;
while(null != (string = br.readLine()))
//一行一行的读取出来
{
System.out.println(string);
}
br.close();
}
字符流写文件:
public static void main(String[] args) throws IOException
{
String string = "hello world welcome nihao hehe";
char[] buffer = new char[string.length()];
string.getChars(0,string.length(),buffer,0);
//这个方法是将一个字符串转化为一个字符数组
FileWriter fileWriter = new FileWriter("D:/test.text",true);
//在文件字符流当中既可以写字符,也可以写字符串
//1 fileWriter.write(buffer);//这个是直接将所有的直接一次性一个一个字符的放到这个文件当中
//2 for(int i = 0; i < buffer.length; i ++)
// {
// fileWriter.write(buffer[i]);//每个字符对应一种类型
// }
//3 fileWriter.write(string);
//4 fileWriter.write(buffer,0,4);
//5 fileWriter.write(string,0,5);
//这几个都可以,针对不同的情况将参数中的值写到文件当中,
//FileWriter这个是建立和文件的一个字符输出流
fileWriter.close();
}
读写都可以的(RandomAccessFile):
public static void main(String[] args)throws Exception
{
Person person = new Person(1,"niesong",1.75);
RandomAccessFile rFile = new RandomAccessFile("D:/test.text","rw");
person.write(rFile);
//这个是一个随机写的,写完后就在最后面,所以需要把指针移到开头,在这个类中有一个seek()方法
rFile.seek(0);//让读的位置重新回到文件的开头
Person person2 = new Person();
person2.read(rFile);//将读到的内容放到person2当中
System.out.println(person2.getId()+","+ person2.getName()+","+person2.getHeight());
}