输入/输出(一)

File类

访问文件和目录

不管是文件还是目录都是使用File来操作的,File能新建、删除、重命名文件和目录,File不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。
File类提供了很多方法来操作文件和目录:
在这里插入图片描述
在这里插入图片描述

流的分类

1. 输入流和输出流

  • 输入流:只能从中读取数据,而不能向其写入数据;
  • 输出流:只能向其写入数据,而不能从中读取数据;

Java的输入流主要由InputStream和Reader作为基类,而输出流则主要由OuputStream和Writer作为基类。它们都是一些抽象基类,无法直接创建实例。
2. 字节流和字符流

  • 字节流:操作的数据单元是8位的字节;
  • 字符流:操作的数据单元是16位的字符;

字节流主要由InputStream和OuputStream作为基类,而字符流主要由Reader和Writer作为基类。
3. 节点流和处理流

  • 节点流:可以从/向一个特定的IO设备(如磁盘、网络)读/写数据的流,节点流也被称为低级流;
  • 处理流:用于对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能,处理流也被称为高级流;

在这里插入图片描述
当使用处理流进行输入/输出时,程序并不会直接连接到实际的数据源,没有和实际的输入/输出节点连接。

流的概念模型

Java的IO流40多个类都是从如下4个抽象基类派生的:

  • InputStream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流;
  • OuputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流;

对于InputStream和Reader而言,它们把输入设备抽象成一个水管,这个水管里的每个水滴依次排列:
在这里插入图片描述
字节流和字符流的处理方式其实非常相似,只是它们处理的输入/输出单位不同而已。输入流使用隐式的记录指针来表示当前正准备从哪个“水滴”开始读取,每当程序从InputStream/Reader里取出一个或多个“水滴”后,记录指针自动向后移动。除此之外InputStream和Reader里都提供一些方法来控制记录指针的移动。

对于OuputStream和Writer而言,它们同样把输出设备抽象成一个水管,只是这个水管里没有任何水滴:
在这里插入图片描述
当执行输出时,程序相当于依次把水滴放入到输出流的水管中。输出流同样采用隐式的记录指针来标识当前水滴即将放入的位置,每当程序OuputStream和Writer里输出一个或多个水滴后,记录指针自动向后移动。

处理流可以嫁接在任何已存在的流的基础之上,这就允许Java应用程序采用相同的代码、透明的方式来访问不同的输入/输出设备的数据流:
在这里插入图片描述

InputStream和Reader

InputStream和Reader是所有输入流的抽象基类,本身不能创建实例来执行输入,但它们将成为所有输入流的模板:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
FileInputStreamTest.java

public class FileInputStreamTest
{
	public static void main(String[] args) throws IOException
	{
		//创建字节输入流
		FileInputStream fis = new FileInputStream("FileInputStreamTest.java");
		//创建一个长度为1024的“竹筒”
		byte[] bbuf = new byte[1024];
		//用于保存实际读取的字节数
		int hasRead = 0;
		//使用循环来重复“取水”过程
		while ((hasRead = fis.read(bbuf)) > 0 )
		{
			//取出“竹筒”中水滴(字节),将字节数组转换成字符串输入!
			System.out.print(new String(bbuf , 0 , hasRead ));
		}
		fis.close();
	}
}

控制台输出:
在这里插入图片描述
FileReaderTest.java

            //创建字符输入流
			FileReader fr = new FileReader("FileReaderTest.java");
			//创建一个长度为32的“竹筒”
			char[] cbuf = new char[32];

与前面FileInputStreamTest没有什么太大区别;
在这里插入图片描述

OuputStream和Writer

在这里插入图片描述
FileOutputStreamTest.java

public class FileOutputStreamTest
{
	public static void main(String[] args) throws IOException
	{
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try
		{
			//创建字节输入流
			fis = new FileInputStream("FileOutputStreamTest.java");
			//创建字节输入流
			fos = new FileOutputStream("newFile.txt");
			byte[] bbuf = new byte[32];
			int hasRead = 0;
			//循环从输入流中取出数据
			while ((hasRead = fis.read(bbuf)) > 0 )
			{
				//每读取一次,即写入文件输出流,读了多少,就写多少。
				fos.write(bbuf , 0 , hasRead);
			}
		}
		catch (IOException ioe)
		{
			ioe.printStackTrace();
		}		
	}
}

运行,将看到系统当前路径下多了一个文件:newFile.txt。内容与FileOutputStreamTest.java一样;
FileWriterTest.java

public class FileWriterTest
{
	public static void main(String[] args) throws IOException
	{
		//创建字符输出流
		try(FileWriter fw = new FileWriter("poem.txt"))  //带资源的try,java会对try块参数中声明的对象自动调用close()
		{						
			fw.write("锦瑟 - 李商隐\r\n"); 
			fw.write("锦瑟无端五十弦,一弦一柱思华年。\r\n");  //\r\n这是Windows平台的换行符
			fw.write("庄生晓梦迷蝴蝶,望帝春心托杜鹃。\r\n");
			fw.write("沧海月明珠有泪,蓝田日暖玉生烟。\r\n");
			fw.write("此情可待成追忆,只是当时已惘然。\r\n");
		}
		catch (IOException ioe)
		{
			ioe.printStackTrace();
		}		
	}
}

处理流的用法

使用处理流的典型思路是,使用处理流来包装节点流,程序通过处理流来执行输入/输出功能,让节点流与底层的I/O设备、文件交互。
实际识别处理流非常简单,只要流的构造器参数不是一个物理节点,而是已经存在的流,那么这种流就一定是处理流;而所有节点流都是直接以物理IO节点作为构造器参数的。
PrintStreamTest.java

public class PrintStreamTest
{
	public static void main(String[] args)throws IOException
	{
		
		try(FileOutputStream fos = new FileOutputStream("test.txt");//创建一个节点输出流:FileOutputStream
				PrintStream ps = new PrintStream(fos))//以PrintStream来包装FileOutputStream输出流
		{											
			//使用PrintStream执行输出
			ps.println("普通字符串");
			ps.println(new PrintStreamTest());
		}
		catch (IOException ioe)
		{
			ioe.printStackTrace();
		}		
	}
}

程序使用处理流非常简单,通常只需要在创建处理流时传入一个节点流作为构造器参数即可;

输入/输出流体系

在这里插入图片描述
如果进行输入/输出的内容是文本内容,则应该考虑使用字符流;如果进行输入/输出的内容是二进制内容,则应该考虑使用节点流;

转换流

输入/输出流体系中还提供了两个转换流,这两个转换流用于实现将字节流转换成字符流:

  • InputStreamReader:将字节输入流转换为字符输入流;
  • OutputStreamWriter:将字节输出流转换为字符输出流;

为什么没有把字符流转换成字节流的转换流呢?
因为字符流比字节流操作更加方便,所以如果有一个流已经是字符流了,是一个用起来更加方便的流了,那么为什么要转换成字节流呢?
KeyinTest.java

public class KeyinTest
{
	public static void main(String[] args) 
	{
		
		try(InputStreamReader reader = new InputStreamReader(System.in);//将Sytem.in对象转换成Reader对象	
				BufferedReader br = new BufferedReader(reader);	)//将普通Reader包装成BufferedReader	
		//BufferedReader流具有缓冲功能,它可以一次读取一行文本----以换行符为标志,如果没有读到换行符,则程序阻塞,等到读到换行符为止		
		{											
			String buffer = null;
			//采用循环方式来一行一行的读取
			while ((buffer = br.readLine()) != null)
			{
				//如果读取的字符串为"exit",程序退出
				if (buffer.equals("exit"))
				{
					System.exit(1);
				}
				//打印读取的内容
				System.out.println("输入内容为:" + buffer);
			}
		}
		catch (IOException ioe)
		{
			ioe.printStackTrace();
		}		
	}
}

在这里插入图片描述
以上只是学习所做的笔记,不做任何用途(其实就是照着书抄啦)!!!
书籍:疯狂Java讲义

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值