欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

IO流的整体介绍(较全面)

程序员文章站 2024-03-07 08:41:20
...

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

具体流的分类:

节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。

过滤流:使用节点流作为输入或输出。过滤流是使用一个已经存在的输入流或输出流连接创建的。

字节流

IO流的整体介绍(较全面)

简单看下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表示标准输入流

IO流的整体介绍(较全面)

字符流


这里简单看下几个例子:

首先字符流和字节流连接有两个中间(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());
		
	}