JAVA基础之IO流

JAVA基础之IO流

一.概念
IO流:传输数据的一套机制

I:input (输入)
O:output(输出)

存储数据:内存 持久化存储
持久化存储:长期保存

IO流分为输入流和输出流
IO流从功能上来说分为字符流和字节流
字符流是只能操作字符(txt、.java、.html)
字节流:可以操作所有文件

输入流输出流
字符流ReaderWriter
字节流InputStreamOutputStream

以上4种都是抽象类,不能直接使用

输入还是输出是相对于内存来说
如果向内存中读取内容,就是输入到内存。输入流
如果从内存中向外面写入内容,就是输出。

字符输出流:FileWriter 将字符写入到文件中
如果想要追加数据,在构造方法后面提供 true

二.字符输出流
1.字符输出流

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterDemo {
	public static void main(String[] args) throws IOException {
		// 字符输出流
		// 如果路径有,就直接创建文件
		// 如果文件已经存在,会创建新的文件覆盖掉原来的文件
		FileWriter fw = new FileWriter("F:\\a.txt",true);//往a.txt中添加,不覆盖

		// 写入数据到缓冲区
		fw.write("愿微风不燥,阳光正好,时光不老~");
		// 冲刷缓冲区
//		fw.flush();
		// 关闭,释放资源
		// 关闭时会自动冲刷缓冲区
		fw.close();
		// 清空对象
		fw = null;
	}
}

2.处理异常

异常处理:
1、先在try…catch外面声明对象,设置为null,保证对象的作用域在try…catch…finally里面
2、创建对象,并且在finally里面判断是否为null。因为一旦对象为null,那么就会出现空指针异常。
3、在finally的判断方法中,关闭流。关闭流也需要捕获异常,因为关闭流也不一定成功。
4、在捕获关闭流异常的try catch中添加finally,无论关闭流是否成功,都给对象设置为null。
5、如果写入数据,需要去冲刷缓冲区,防止数据的丢失。

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterExceptioonTest {
	public static void main(String[] args) {
		
		// 创建对象
		FileWriter fw = null;
		try {
			fw = new FileWriter("F:\\b.txt");
			fw.write("你好,hello world");
			// 冲刷
			fw.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			if (fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					fw = null;
				}
			}
		}
	}
}

3.JDK1.7的特性
Try with resource
try(AutoCloseable的子类/子接口){
对象可以保证自动关闭
}
注意:try小括号中内容不能是传递过来的

import java.io.FileWriter;

public class TryWithResourceDemo {
	public static void main(String[] args) {
		
		// JDK1.7特性
		// try ... with ... resouce  可以保证自动关闭
		// 使用格式 try(AutoCloseable的子类或者子接口)
		// 可以保证里面的对象自动关闭
		try (FileWriter fw = new FileWriter("F:\\b.txt")){    //注意小括号
			fw.write("再见,周杰伦");
		}catch(Exception e){
			e.printStackTrace();
		}

	}
}

三.字符输入流:FileReader
FileReader默认一次读取一个字符,效率比较低下,可以通过字符数组形成一个缓冲区,从而来提升效率。
1.将文件内容读取到内存中 字符输入流

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderDemo {
	public static void main(String[] args) throws IOException {
		// 将文件内容读取到内存中 字符输入流
		// 创建对象
		FileReader fr = new FileReader("F:\\c.txt");
		// 读取字符
		// 一次读取一个字符
		// 如果读取到最后,没有字符,返回-1
		// 因为是从文件中一个个的读取,所以这种写法,效率比较低
		int ch;
		while ((ch = fr.read()) != -1){
			// 读一次打印一次
			System.out.println((char)ch);
		}
		// 关闭流
		fr.close();
	}
}

2.通过字符数组作为缓冲区,读取数

import java.io.FileReader;
import java.io.IOException;

public class FileReaderDemo02 {
	public static void main(String[] args) throws IOException {
		// 通过字符数组作为缓冲区,读取数据
		FileReader fr = new FileReader("F:\\c.txt");
		// 定义一个字符数组
		char[] chs = new char[3];
		
		// 读一次就获取对应字符数组长度的内容
		// 如果没有读取到数据,那么返回-1
		// 读取到的字符长度
		int len;
		while((len = fr.read(chs)) != -1){
			System.out.println(new String(chs,0,len));
		}
		
		
		fr.close();
	}
}

3.复制文件

import java.io.FileReader;
import java.io.FileWriter;

public class CopyTxt {
	public static void main(String[] args) {
		// 拷贝文件  思路:先去对应的文件中读取内容
		// 读取一行写入一行
		// 读取时候使用字符数组
		
		long startTime = System.currentTimeMillis();
		FileReader fr = null;
		FileWriter fw = null;
		try{
			fr = new FileReader("F:\\a.txt");
			fw = new FileWriter("F:\\b.txt");
			
			// 先读再写
			// 读取需要使用到字符数组,那么先创建数组
			char[] chs = new char[1024 * 8];
			// 定义一个变量来接收实际读取到的长度
			int len;
			while ((len = fr.read(chs)) != -1){
				// 表示读取到了内容 长度就是len
				// 写入到文件中
//				fw.write(new String(chs,0,len));
				fw.write(chs, 0, len);
			}
			fw.flush();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			// fr和fw都有可能是null
			if (fr != null){
				try{
					fr.close();
				}catch(Exception e){
					e.printStackTrace();
				}finally{
					fr = null;
				}
			}
			
			if (fw != null){
				try{
					fw.close();
				}catch(Exception e){
					e.printStackTrace();
				}finally{
					fw = null;
				}
			}
		}
		// 复制文本花费的总时间
		System.out.println(System.currentTimeMillis() - startTime);
	}
}

四.BufferedReader和BufferedReader

BufferedReader:默认提供了一个缓冲区,相对于fileReader效率更高。底层还是使用的FileReader来读取.
BufferedReader:提供一个特有的方法 readLine 可以一次读取一行字符串
注意:readLine并没有读取换行符 \r\n

设计模式:解决同一类问题的常用手段。
装饰设计模式:用同类的对象来构建本类对象,从而对所构建的本类对象的功能进行增强或者修复。
BufferedReader和BufferedWriter就是所谓的装饰设计模式

1.BufferedReader

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
	public static void main(String[] args) throws IOException {
		// 创建对象
		// 传入FileReader对象
		// 底层使用FileReader
		BufferedReader br = new BufferedReader(new FileReader("F:\\667.txt"));
		
		// 可以一次读取一行
		String str;
		while((str = br.readLine()) != null){
			System.out.println(str);
		}
		
		// 关闭流
		br.close();
		
	}
}

2.BufferedWriter
BufferedWriter:写入数据。提供了一个特有的方法(newLine),可以换行。

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterDemo {
	public static void main(String[] args) throws IOException {
		// 创建对象
		BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\a689.txt"));
		bw.write("爱情这杯酒,谁喝都会醉");
		// 换行
		bw.newLine();
		bw.write("什么爱情,什么永久!!");
		
//		bw.flush();
		bw.close();
	}
}

3.统计java代码行数

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class PracticeDemo {
	static int javaCount = 0;
	public static void main(String[] args) throws IOException {
		// 统一workspace中的代码行数
		// 代码都写在.java文件中
		// 先找到.java文件
		// 然后通过BufferedReader读取一行
		// 然后进行行数的计数
		
		// File类来操作文件和目录
		File file = new File("F:\\workspace");
		count(file);
		System.out.println("总共写了" + javaCount + "行代码");
	}
	
	// 定义一个方法,来寻找.java文件
	public static void count(File file) throws IOException{
		if (file.isDirectory()){
			// 如果是目录,列出目录所有内容
			File[] files = file.listFiles();
			for (File f : files) {
				count(f);
			}
		}else if(file.getName().endsWith(".java")){
			// 找到.java文件  CopyTxt.java
			BufferedReader br = new BufferedReader(new FileReader(file.getAbsolutePath()));
			String str;
			while ((str = br.readLine()) != null){
				javaCount++;
			}
			
			br.close();
		}
	}
}

五.FileInputStream和OutputStreamWriter
1.FileInputStream

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamDemo {
	public static void main(String[] args) throws IOException {
		// 字节输入流   以字节的形式输入到内存中
		FileInputStream fis = new FileInputStream("F:\\c.txt");
		
		// 定义字节数组,用于缓冲区
		byte[] bys = new byte[10];
		int len;
		while ((len = fis.read(bys)) != -1){
			System.out.println(new String(bys,0,len));
		}
		
		fis.close();
		
		
	}
}

2.OutputStreamWriter

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class OutPutStreamDemo {
	public static void main(String[] args) throws IOException {
		// 转换输出流  可以将字节流转换为字符流
		// 可以通过写入字符的形式来使用字节流
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("F:\\d.txt"));
		
		// 写入数据
		osw.write("4555645dfgdf");
		// 关流
		osw.close();
			}
}

3.使用字节流拷贝文件

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyJPG {
	public static void main(String[] args) throws IOException {
		// 创建字节输入和输出流
		FileInputStream fis = new FileInputStream("F:\\a.jpg");
		FileOutputStream fos = new FileOutputStream("F:\\b.jpg");
		
		// 读取图片
		// 定义一个字节数组,用于缓冲区
		byte[] bys = new byte[10];
		// 读取的实际长度
		int len;
		
		while((len = fis.read(bys)) != -1){
			// 代码执行到这里,代表读取成功
			// 写入数据
			fos.write(bys, 0, len);
		}
		
		// 关流
		fos.close();
		fis.close();
	}
}

六.系统流

System.in标准输入流
System.out标准输出流
System.err标准错误流

标准输出流和标准错误流可能出现高并发的问题。有可能位置不同,有可能不换行.

为什么没有关过Scanner???
Scanner里面使用System.in系统输入流,系统输入流是共享的。程序中只有一个系统输入流。当关闭Scanner时,会将Scanner中的参数系统输入流也关闭掉。就会导致整个程序不能再继续使用系统输入流。
以后见到系统流,不要关闭。
系统流都是字节流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值