Java基础之文件字节流

字节流

文本、图片、视频等文件存储时,底层都是以二进制形式保存,即字节存储,所以数据传输时也可以采用字节流。在操作流时,无论使用什么样的流对象,底层数据的传输始终为二进制数据。

java.io.InputStream是所有字节输入流的抽象父类

java.io.OutputStream是所有字节输出流的抽象父类:

在代码中,使用流的基本步骤

  1. 选择合适的IO类,实例化对象
  2. 调用IO流对象中的方法,去完成相应操作
  3. 操作完成后,关闭流(释放资源)

InputStream,OutputStream有很多子类,我们从最简单的一个子类开始。

1)文件输入流

文件字节输入流FileInputStream,用于从文件中读取字节数据。

源码参考:

package java.io;

public class FileInputStream extends InputStream {
	//略...
    
    //通过File对象来创建一个 FileInputStream
    public FileInputStream(File file) throws FileNotFoundException;
    
	//通过文件路径名(字符串)实例化FileInputStream对象
	public FileInputStream(String name) throws FileNotFoundException;
	
	//逐个字节读取,返回值为读取的单个字节
	public int read() throws IOException;
	//小数组读取,将结果存入数组,返回值为读取的字节个数
	public int read(byte b[]) throws IOException;
	//小数组读取,存入数组指定位置,返回值为读取的字节个数
	public int read(byte b[], int off, int len) throws IOException;

	//省略...
}

案例展示:

​ 使用3种read方法,读取文件D:\\test\\a.txt内容,掌握read的用法。a.txt文件内容如下:

在这里插入图片描述

按下图编写测试代码:
在这里插入图片描述

注意:IO操作每个方法都可能产生异常,具体如上图。

关于异常的处理,我们之前学过两种处理方式:

  • 当前方法中声明继续抛出,借助throws实现
  • 自行捕获处理,借助try-catch块实现

我们暂时采用第一种方式来处理异常:

package com.briup.chap11.test;

public class Test024_Read {
	public static void main(String[] args) throws IOException {
		//1.创建流对象【IO流对象 跟 文件进行关联】
		InputStream is = new FileInputStream("D:\\test\\a.txt");
		System.out.println("is: " + is);
		
		//2.读取文件内容
		//	1次读1个字节返回,如果到文件末尾,则返回-1
		// 	int read(); 
		int r = is.read();
		System.out.println("第1个字节:" + r);
		r = is.read();
		System.out.println("第2个字节:" + r);
		r = is.read();
		System.out.println("第3个字节:" + r);
		r = is.read();
		System.out.println("第4个字节:" + r);	//-1
		
		//3.关闭流对象,释放资源
		is.close();
	}
}

//输出结果:
is: java.io.FileInputStream@7852e9221个字节:972个字节:983个字节:994个字节:-1

**注意:**创建FileInputStream对象时,必须传入一个有效文件路径,否则系统自动抛出FileNotFoundException异常。

read方法测试:int read(byte[] arr);

public static void main(String[] args) throws IOException {
    //1.创建流对象【IO流对象 跟 文件进行关联】
    InputStream is = new FileInputStream("D:\\test\\a.txt");
    System.out.println("is: " + is);

    //2.读取文件内容
    // 	int read(byte[] arr); 
    //	读多个字节,放入arr数组,返回成功读取字节数目,
    //	如果到文件末尾,则返回-1
    byte[] arr = new byte[10];
    int len = is.read(arr);
    System.out.println("成功读取字节数目:" + len);

    //遍历数组有效内容
    for(int i = 0; i < len; i++)
        System.out.println(arr[i]);

    System.out.println("------------");

    //再次读取
    len = is.read(arr);
    System.out.println("第二次读取: " + len);	// -1

    //3.关闭流对象,释放资源
    is.close();
}

//输出结果:
is: java.io.FileInputStream@7852e922
成功读取字节数目:3
97
98
99
------------
第二次读取: -1

read方法测试:int read(byte[] arr,int off,int len);

public static void main(String[] args) throws Exception {
    //1.创建流对象
    InputStream is = new FileInputStream("D:\\test\\a.txt");
    System.out.println("is: " + is);

    //2.读取
    // 	读取5个字节往arr中 往后偏移3个位置 放入
    //	如果读取成功,则返回实际读取长度
    //	如果返回-1,则表示读取到文件末尾
    byte[] arr = new byte[10];
    int len = is.read(arr,3,5);	//arr[ , , , a, b, c, ...]

    System.out.println("成功读取: " + len);

    //遍历数组所有内容
    for(int i = 0; i < arr.length; i++)
        System.out.print(arr[i] + "  ");

    //3.关闭资源
    is.close();
}

//输出结果:
is: java.io.FileInputStream@7852e922
成功读取: 3
0  0  0  97  98  99  0  0  0  0 
2)文件输出流

文件字节输出流,FileOutputStream,用于写入字节数据到文件中。

FileOutputStream源码:

package java.io;

public class FileOutputStream extends OutputStream
    //创建文件输出流以写入由指定的 File对象表示的文件。
	public FileOutputStream(File file) throws FileNotFoundException;

    //创建文件输出流以指定的名称写入文件
	public FileOutputStream(String name) throws FileNotFoundException;

    //创建流对象,可配置是否追加
	public FileOutputStream(File file, boolean append) throws FileNotFoundException;

	//写操作方法
	public void write(int b) throws IOException;
	public void write(byte b[]) throws IOException;
	public void write(byte b[], int off, int len) throws IOException;

	//省略...
}

注意事项:

  • 创建输出流对象时传入的文件路径如果不存在,系统会自动创建该文件

  • 如果该文件路径存在,系统默认会清空这个文件中的数据

案例实现:

​ 提前创建好目录src/dir,然后使用文件输出流write字节到src/dir/a.txt中。

package com.briup.chap11.test;

public class Test024_Write {
	public static void main(String[] args) throws Exception {
		//1.关联流对象和文件  
		//	实例化输出流时,目标文件a.txt不存在不会抛异常,系统会自动创建
		//	但src/dir目录必须存在,系统不会自动创建多级目录
		OutputStream os = new FileOutputStream("src/dir/a.txt");
		System.out.println("os: " + os);
		
		//2.逐个字节写数据
		os.write(97);	//a
		os.write(98);	//b
		os.write(99);	//c
		
		//3.关闭资源
		os.close();
	}
	
	public static void main02(String[] args) throws Exception {
		//1.关联流对象和文件  
		OutputStream os = new FileOutputStream("src/dir/a.txt");
		System.out.println("os: " + os);
		
		//2.写字节数组
        String str = "abcd";
		byte[] arr = str.getBytes();
		//将arr所有元素全部写入文件
		//写入 会 覆盖 文件原有内容
		os.write(arr);
		
		//3.关闭资源
		os.close();
	}
	
	public static void main03(String[] args) throws Exception {
		//1.关联流对象和文件  
		OutputStream os = new FileOutputStream("src/dir/a.txt");
		System.out.println("os: " + os);
		
		//2.写字节数组中的一部分数据   '1''2''3''4''5'
		byte[] arr = {49,50,51,52,53,54,55};
		//os.write(arr,0,arr.length);
		
		//从arr[2]开始,获取arr数组的3个字节,即[51,52,53],然后写入a.txt
		//写入 会 覆盖 文件原有内容
		os.write(arr,2,3);
        
        // 写出一个换行, 换行符号转成数组写出
        os.write("\r\n".getBytes());
		
		//3.关闭资源
		os.close();
	}
}

注意:不同操作系统中回车、换行符是不同的

回车和换行:

  • 回车符:回到一行的开头(return)

  • 换行符:下一行(newline)

各系统中的换行:

  • Windows系统里,每行结尾是 回车+换行 ,即\r\n

  • Unix系统里,每行结尾只有 换行 ,即\n

  • Mac系统里,每行结尾是 回车 ,即\r。从 Mac OS X开始与Linux统一。

综合案例:

​ 拷贝src/dir/a.txt内容到src/dir/b.txt中,a.txt内容如下:

hello world
1、确认过眼神,我遇上的人。我策马出征,马蹄声如泪奔。青石板上的月光照进这山城。
我一路的跟,你轮回声,我对你用情极深。 --方文山 《醉赤壁》
2、无关风月 我题序等你回 悬笔一绝 那岸边浪千叠 --方文山 《兰亭序》
3、那画面太美,我不敢看 --方文山 《布拉格广场》
4、你说 想哭就弹琴 想起你就写信情绪来了就不用太安静 --方文山 《想你就写信》

在这里插入图片描述

代码实现:

package com.briup.chap11.test;

public class Test024_Copy {
	public static void main(String[] args) throws Exception {
		//1.关联文件和流对象
		InputStream is = new FileInputStream("src/dir/a.txt");
		OutputStream os = new FileOutputStream("src/dir/b.txt");
		
		//2.拷贝
		//2.1 逐个字节拷贝
//		int r;
//		while((r = is.read()) != -1) {
//			os.write(r);
//		}
		
		//2.2 小数组拷贝,使用最多
		byte[] arr = new byte[8];
		int len;
		while((len = is.read(arr)) != -1) {
			//注意事项:读取多少个字节 就写出多少个字节
			os.write(arr,0,len);
		}
		
		System.out.println("拷贝完成");
		
		//3.关闭资源  
		//注意:先关闭后打开的,后关闭先打开的
		os.close();
		is.close();
	}
}

注意事项:

  • 逐个字节拷贝效率太低,推荐使用小数组拷贝
  • 关闭资源的顺序应该和打开资源顺序相反:先打开的后关闭,后打开的先关闭
  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值