IO流

本文主要介绍Java的IO流,用于数据持久化存储和文件系统数据读取。阐述了IO流的概念、分类,包括按数据流向和类型的分类。对比了字节流和字符流的区别及选取原则,还详细介绍了字节流、字符流及其缓冲流的常用类、构造方法、成员方法和注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IO流

针对于数据的持久化存储,或是从文件系统中读取数据: Java提供了IO流(输入输出流),将数据从内存写入文件系统做到持久化或是从文件系统中读取数据。

IO流概述

在程序中所有的数据都是以流的方式进行传输或保存的,程序通过输入流读取数据;当程序需要将一些数据长期保存起来的时候使用输出流完成。

注意

1.但凡是对数据的操作,Java都是通过流的方式来操作的。

2.程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。

3.IO流可以做到数据的持久化,但是IO流本质上是用来处理本地文件系统以及不同设备之间的数据传输。

IO流分类

按照数据流向

输入流:从外界(键盘、网络、文件…)读取数据到内存

输出流:用于将程序中的数据写出到外界(显示器、文件…)

按照数据类型

字节流:主要用来处理字节或二进制对象。

字节输入流(InputStream)

字节输出流 (OutputStream)

字符流:主要用来处理字符、字符数组或字符串。

字符输入流(Reader)

字符输出流(Writer

字节流和字符流的区别和选取

字节流和字符流的区别

1.读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

2.处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据(文本文件 txt json html css js .xml )。

选取:只要是处理纯文本数据,就优先考虑使用字符流,除此之外都使用字节流。

IO流继承体系结构图

1557056157334

字节流

FileOutputStream
FileOutputStream常用构造方法

nFileOutputStream(String name) 创建一个向name文件中写数据的输出文件流

nFileOutputStream(File file) 创建一个向file文件中写数据的输出文件流

nFileOutputStream(File file, boolean append) 创建一个向file文件中追加数据的输出文件流

FileOutputStream常用成员方法

npublic void write(int b) 写一个字节

npublic void write(byte[] b) 写一个字节数组

npublic void write(byte[] b,int off,int len) 写一个字节数组的一部分

nvoid close() 关闭此文件输出流并释放与此流有关的所有系统资源

注意事项:

1、数据写入完成后记得调用close()方法关闭流对象

2、数据追加写入要使用构造方法:

​ FileOutputStream(File file, boolean append)

3、不同的系统针对不同的换行符号识别是不一样的

​ 例如:windows识别的换行符是\r\n,Linux识别的换行符是\n等等。

​ 常见的一些高级记事本,是可以识别任意换行符号的。

4、数据写入中存在两个异常需要处理FileNotFoundException,IOException。

public static void main(String[] args) {
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("title", "静夜思");
		map.put("author", "李白");
		List<String> list = new ArrayList<>();
		list.add("窗前明月光");
		list.add("疑似地上霜");
		list.add("举头望明月");
		list.add("低头思故乡");
		map.put("poem", list);

		try(FileOutputStream fos = new FileOutputStream("H:/poem.txt");//这样写不用手动关闭流,比较方便
				Scanner input = new Scanner(System.in);) {
			
			fos.write(((String)map.get("title")).getBytes());
			fos.write("\r\n".getBytes());
			fos.flush();				//手动调用flush()方法,强制刷出缓冲池中的数据
			fos.write(((String)map.get("author")).getBytes());
			fos.write("\r\n".getBytes());
			fos.flush();
			
			@SuppressWarnings("unchecked")
			List<String> poemList = (List<String>) map.get("poem");
			for (String poem : poemList) {
				fos.write((poem + "\r\n").getBytes() );
				fos.flush();
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} 
		
		System.out.println("over");
		
	}
FileInputStream

FileInputStream的常用构造方法

FileInputStream(File file) 创建一个从file读取数据的输入流

FileInputStream(String name) 创建一个从name文件读取数据的输入流

FileInputStream的常用成员方法

int read() 一次读取一个字节返回的是字节对应的int

int read(byte[] b) 一次读取一个字节数组返回的是字节数组的长度

int read(byte[] b, int off, int len) 一次读取一个字节数组的一部分

void close() 关闭此文件输入流并释放与此流有关的所有系统资源

public static void main(String[] args){		
		byte[] by = new byte[8192];//定义一个byte数组
		int b = 0;
		try(FileInputStream is = new FileInputStream("aaa/bbb/test.mp4");
            //原MP4文件的相对路径
				FileOutputStream os = new FileOutputStream("newTest.mp4");) {
            //写入的目标文件newTest.mp4
			
			while((b = is.read(by))!=-1) {
				os.write(by);  //利用字节数组把视频复制到newTest.mp4
				os.flush();
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}

}
字节缓冲流

java考虑到流读写效率的提升所以为我们提供了字节缓冲流。

字节缓冲输出流:BufferedOutputStream
字节缓冲输入流:BufferedInputStream

    public static void main(String[] args) {
            long start = System.currentTimeMillis();
            copy2("D:\\视频\\猜猜这里面是有什么.mp4", "点开看看.mp4"); 
            long end = System.currentTimeMillis();
            System.out.println("本次复制花费了" + (end - start) + "毫秒");

        }

        // 一次性读取一个字节拷贝一个字节的方式
            public static void copy(String srcFileName, String descFileName) {
                try (FileInputStream fis = new FileInputStream(srcFileName);
                        FileOutputStream fos = new FileOutputStream(descFileName)) {

                    int by = 0;
                    while ((by = fis.read()) != -1) {
                        fos.write(by);
                        fos.flush();
                    }

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }

            }

            // 一次性读取一个字节数组的方式拷贝
            public static void copy2(String srcFileName, String descFileName) {
                try (FileInputStream fis = new FileInputStream(srcFileName);
                        FileOutputStream fos = new FileOutputStream(descFileName)) {

                    byte[] bys = new byte[1024];
                    int len = 0;

                    while ((len = fis.read(bys)) != -1) {
                        fos.write(bys, 0, len);
                        fos.flush();
                    }

                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }

            }

            public static void copy3(String srcFileName, String descFileName) {
                try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFileName));
                        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(descFileName))) {
                    byte[] bys = new byte[1024];
                    int len = 0;

                    while ((len = bis.read(bys)) != -1) {
                        bos.write(bys, 0, len);
                        bos.flush();
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }

            }

字符流

字节流虽然作为万能流,但是在对字符进行处理的时候不是很方便,可能因为某些人为的操作出现乱码现象,所以Java就提供了字符流

OutputStreamWriter

OutputStreamWriter:是转换流,是字符流通向字节流的桥梁,可使用指定的charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认字符集编码。

OutputStreamWriter构造方法

OutputStreamWriter(OutputStream out) 创建使用默认字符编码的字符输出转换流

OutputStreamWriter(OutputStream out, Charset cs) 创建使用cs字符集的字符输出转换流

OutputStreamWriter(OutputStream out, CharsetEncoder enc) 创建使用enc字符集编码器的

OutputStreamWriter(OutputStream out, String charsetName) 创建使用指定字符集的

OutputStreamWriter的成员方法

public void write(int c) 写一个字符

public void write(char[] cbuf) 写一个字符数组

public void write(char[] cbuf,int off,int len) 写一个字符数组的一部分

public void write(String str) 写一个字符串

public void write(String str,int off,int len) 写一个字符串的一部分

void close() 关闭流对象

void flush() 清空缓存

InputStreamReader

InputStreamReader构造方法

InputStreamReader(InputStream in) 创建一个使用默认字符集的输入转换流。

InputStreamReader(InputStream in, Charset cs) 创建使用给定字符集的输入转换流。

InputStreamReader(InputStream in, CharsetDecoder dec) 创建使用给定字符集解码器输入转换流。

InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的输入转换流 。

InputStreamReader方法

void close() 关闭该流并释放与之关联的所有资源。

String getEncoding() 返回此流使用的字符编码的名称。

int read() 读取单个字符。

int read(char[] cbuf, int offset, int length) 将字符读入数组中的某一部分。

boolean ready() 判断此流是否已经准备好用于读取。


	public static void main(String[] args) {
		try(InputStreamReader r = new InputStreamReader(new FileInputStream("newss.txt"));
				OutputStreamWriter w = new OutputStreamWriter(new FileOutputStream("testchario.txt"));) {
			int len =0;
			char[] chs = new char[1024];
			while((len = r.read(chs))!=-1) {
				w.write(chs, 0, len);
				w.flush();
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}

FileReader和FileWriter

lFileWriter:用来写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个OutputStreamWriter。

lFileReader:用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。

构造方法类似FileInputStream和FileOutputStream

成员方法完全继承自父类OutputStreamWriter和InputStreamReader

public static void main(String[] args) {
		copyFile2("fr.txt", "fw2.txt");
	}

	public static void copyFile(String srcFileName, String descFileName) {
		try (FileReader fr = new FileReader(srcFileName); 
				FileWriter fw = new FileWriter(descFileName);) {
			// 一次性读取一个字符
			int ch = 0;
			while ((ch = fr.read()) != -1) {
				fw.write(ch);
				fw.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
	
	public static void copyFile2(String srcFileName, String descFileName) {
		try (FileReader fr = new FileReader(srcFileName); 
				FileWriter fw = new FileWriter(descFileName);) {
			// 一次性读取一个字符数组
			int len = 0;
			char[] chs = new char[1024];
			
			while ((len = fr.read(chs)) != -1) {
				fw.write(chs, 0, len);
				fw.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
字符缓冲流

1.类似于字节流的BufferedOutputStream和BufferedInputStream,字符流同样存在字符字符缓冲流

同理,字符缓冲流也是为了提高字符流的效率。

2.BufferedWriter和BufferedReader继承自Writer和Reader,所以具备原有的读取方法,但是还存在自己特有的方法。

特有的方法

BufferedWriter:void newLine()

BufferedReader:String readLine()

public static void main(String[] args) throws Exception {
		// write();
		// read();
		copyFile("ByteIODemo01.java", "good.txt");
	}

	public static void copyFile(String srcFileName, String descFileName) {
		try (BufferedReader br = new BufferedReader(new FileReader(srcFileName));
				BufferedWriter bw = new BufferedWriter(new FileWriter(descFileName))) {

			// 一次性读取一行
			String line = null;
			while ((line = br.readLine()) != null) {
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private static void read() throws Exception {
		BufferedReader br = new BufferedReader(new FileReader("br.txt"));

		String line = null;
		while ((line = br.readLine()) != null) {
			System.out.println(line);
		}

		br.close();
	}

	private static void write() throws Exception {
		BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

		bw.write("Hello");
		bw.newLine();
		bw.flush();
		bw.write("World");
		bw.newLine();
		bw.flush();
		bw.close();
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值