Java I/O流——面向字节的输入/输出流(超级详细)

目录

前言

流的概念

I/O设备与文件

面向字节的输入流

InputStream类

类InputStream的子类的使用

文件输入流(FileInputStream)

文件输入流(FileInputStream)实例

字节数组输入流(ByteArrayInputStream)

字节数组输入流(ByteArrayInputStream)实例

数据输入流(DataInputStream)

数据输入流(DataInputStream)实例

面向字节的输出流

文件输出流(FileOutputStream)

文件输出流(FileOutputStream)实例

字节数组输出流(ByteArrayOutputStream)

字节数组输出流(ByteArrayOutputStream)实例

数据输出流类(DataOutputStream)

数据流类(DataOutputStream)实例

最后


前言

Java不是在语言层面上对输入/输出提供支持,而是将这个任务交由类库来完成,这样类库可以充分、灵活地运用各种输入/输出技术。输入/输出是程序与用户之间沟通的桥梁,程序从外界获得数据称为输入,程序将运算结果等信息传递给外界称为输出,Java的输入、输出是以流的方式来进行处理的,那么什么是流,流是怎样来处理输入、输出的呢,今天我们来学习Java中的输入/输出流。

流的概念

在Java中,把一组有序的数据序列称为流,流系列中的数据有未经加工的原始二进制数据,也有经过特定包装过滤处理的格式数据。

流式输入、输出特点是数据的获得和发送均沿数据序列顺序进行。

输出流是向存储介质或数据通道中写入数据,而输入流是从存储介质或数据通道中读取数据,如下图所示:

123123

流的特性:

  • 先进先出:最先用输出流写入存储介质的数据最先被输入流读取到;
  • 顺序存取:写入和读取流数据均按顺序逐个字节进行,不能随机访问中间的数据;
  • 只读或只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能。

Java API提供了两套流来处理输入/输出来满足不同性质的输入/输出需要:

  • 面向字节的流:数据的处理是以字节为基本单位;
  • 面向字符的流:用于字符数据的处理。

注意:为了满足字符的国际化表示要求,Java的字符编码是采用16位表示一个字符的Unicode码,而普通的文本文件中采用的是8位的ASCII码。

Java系统定义了以下3个可以直接使用的流对象:

  • 标准输入(System.in):InputStream类型,通常代表键盘输入;
  • 标准输出(System.out):PrintStream类型,通常写往显示器;
  • 标准错误输出(System.err):PrintStream类型,通常写往显示器。

在Java中使用字节流和字符流的步骤基本相同,以输出流为例:

  1. 创建一个与数据源相关的流对象;
  2. 利用流对象的方法往流写入数据;
  3. 执行close()方法关闭流。

I/O设备与文件

计算机外部设备分为两类:存储设备与输入/输出设备。

  • 存储设备:包括硬盘、软盘、光盘等,数据以文件的形式进行组织;
  • 输入/输出设备:输入设备(键盘、鼠标、扫描仪等)和输出设备(显示器、打印机、绘图仪等),从数据操作的角度,文件内容可以是字节的序列;

根据数据的组织方式,文件可以分为文本文件和二进制文件。

  • 文本文件:存放的是ASCII码(或其他编码)表示的字符;
  • 二进制文件:具有特定结果的字节数据。

面向字节的输入流

InputStream类

在java.io包中,InputStream类表示字节输入流,它是抽象类,不能实例化,其作用是用来表示那些从不同数据源产生输入的类。

面向字节的输入流类都是类InputStream的子类,如下图:

1111111

类InputStream定义了以下方法:

  • public int read():读一个字节,返回读到字节的int表示方式,读到流的未尾时返回-1;
  • public int read(byte b[]):读多个字节数组,返回结果为读到的实际字节个数,当输入流中无数据可读时返回-1;
  • public int read(byte[] b,int off,int count):从输入流读count个字节到字节数组,数据从数组的off处开始存放,当输入流中无数据可读时返回-1;
  • public long skip(long n):指针跳过n个字节,定位输入位置指针的方法;
  • public void mark():在当前位置指针处做一标记;
  • public void reset():将位置指针返回标记处;
  • publicvoid close():关闭流。

数据的读取通常是按照顺序逐个字节进行访问,在某些特殊情况下,要重复处理某个字节可通过mark()加标记,以后用reset()返回该标记处再处理。

类InputStream的子类的使用

类InputStream的主要子类及功能如下表:

类名构造方法的主要参数功能描述

ByteArrayInputStream

字节数组以程序中的一个字节组作为输入源,通常用于对字节数组中的数据进行转换
FileInputStream类File的对象或字符串表示的文件名以文件作为数据源,用于实现对磁盘文件中数据的读取
PipedInputStreamPipedOutputStream的对象与另一输出管道相连,读取写入输出管道中的数据,用于程序中线程间通信
FilterInputStreamInputStream的对象用于装饰另一输入流以提供对输入数据的附加处理功能
SequeueInputStream一系列InputStream的对象将两个其他流首尾相接,合并为一个完整的输入流
ObjectInputStreamInputStream的对象用于从输入流读取串行化对象,可实现轻量级对象持久性

类FilterInputStream的常见子类及功能

类名功能描述
BufferedInputStream为所装饰的输入流提供缓存区的功能,以提高输入数据的效率
DataInputStream为所装饰的输入流提供数据转换功能,可从数据源读取各种基本类型的数据
LineNumberInputStream为文本文件输入流附加行号
PushbackInputStream提供回压数据的功能,可以多次读取同样数据

文件输入流(FileInputStream)

FileInputStream类用于从二进制文件读取数据,它的对象可以用关键字 new 来创建,构造方法为:

  • FileInputStream(File file):打开一个到实际文件的连接来创建文件输入流,该文件通过文件系统的File对象指定;
  • FileInputStream(String name):打开一个到实际文件的连接来创建文件输入流,该文件通过文件系统的路径名name指定。

文件输入流(FileInputStream)实例

例如:在屏幕上显示文件内容:

import java.io.*;
public class first {
	public static void main(String[] args) throws Exception{
		try {
			FileInputStream file=new FileInputStream("e:/新建文本文档.txt");    //创建一个FileInputStream类实例对象file
			int byteRead=file.read();            //创建一个byteRead变量存储读一个字节
			while(byteRead!=-1) {                //如果返回值不是-1则继续执行file的读操作
				System.out.print((char)byteRead);    //将int类型转换为char类型并输出
				byteRead=file.read();    
			}
		}catch(ArrayIndexOutOfBoundsException e) {        //访问数组元素下标越界的异常
			System.out.println("要一个文件名作为命令行参数!");
		}catch(FileNotFoundException e) {                 //访问文件不存在的异常
			System.out.println("文件不存在");
		}catch(IOException e) {}                          //输入输出异常
	}
}

注意:读到文件结尾时read方法返回-1,编程时可以利用该特点来组织循环,从文件的第一个字节一直读到最后一个字节。

字节数组输入流(ByteArrayInputStream)

ByteArrayInputStream类从内存的字节数组中读取数据(数据源是一个字节数组),它本身采用适配器设计模式,把字节数组转换为输入流类型,使程序能对字节数组进行读操作。

字节数组输入流(ByteArrayInputStream)实例

使用ByteArrayInputStream类读取数组中的字节

import java.io.*;
public class first {
	public static void main(String[] args) throws Exception{
		String str="123456789qwerty";        //创建一个字符串变量
		byte[]strBuf=str.getBytes();         //把字符串转换为字节数组
		ByteArrayInputStream bais=new ByteArrayInputStream(strBuf);    //创建一个字节数组流对象
		int data=bais.read();                 //从字节数组输入流读取字节
		while(data!=-1) {
			char upper=Character.toUpperCase((char)data);    //小写转换为大写
			System.out.print(upper+" ");
			data=bais.read();                 //读取字节
		}
		bais.close();                         //关闭字节数组输入流
	}
}

运行结果为:

1 2 3 4 5 6 7 8 9 Q W E R T Y 

数据输入流(DataInputStream)

DataInputStream类的所有读方法都以“read”开头,具体如下:

  • readByte():从输入流中读取1个字节,把它转换为byte类型的数据;
  • readFloat():从输入流中读取4个字节,把它转换为float类型的数据;
  • readLong():从输入流中读取8个字节,把它转换为Long类型的数据;
  • readUTF():从输入流中读取若干字节,把它转换为UTF-8编码的字符串。

我们发现在数据输出流(DataOutputStream)实例中写入的文件,会发现是一些乱码,原因是在于该文件中的数据不是文本格式的数据,要读取其中的数据需要以输入流的方式访问文件,用DataInputStream的readInt方法读取对应数据。

数据输入流(DataInputStream)实例

import java.io.*;
public class first {
	public static void main(String[] args) throws Exception{
		try {
			FileInputStream file=new FileInputStream("d:/x.txt");
			DataInputStream in=new DataInputStream(file);
			while(true) {
				int n1=in.readInt();
				int n2=in.readInt();
				System.out.println(n1+","+n2);
			}
		}catch(EOFException e) {}
		catch(IOException e) {}
	}
}

运行结果为:

11,13
17,19
29,31
41,43
59,61
71,73

面向字节的输出流

面向字节的输出流都是类OutputStream的后代类,如下图:

132543

类OutputStream是一个抽象类,含一套所有输出流均需要的方法:

  • public void write(int b):将参数b的低字节写入输出流;
  • public void write(byte b[]):将字节数组全部写入输出流;
  • public void write(byte b[],int off,int count):将字节数组从off处开始的count个字节数据写入输出流;
  • public void flush():强制将缓冲区数据写入输出流对应的外设;
  • public void close():关闭输出流。

文件输出流(FileOutputStream)

FileOutputStream类用于向二进制文件写入数据,构造方法为:

  • FileOutputStream(String name ,boolean append):创建一个向指定名字的文件中写入数据的流,若第二个参数为true,则以添加方式写入字节,文件中原有的内容不会被清除;
  • FileOutputStream(File file,boolean):创建一个向指定File对象表示的文件中写入数据流,若第二个参数为true,则将字节写入文件末尾而不是文件开始处。

文件输出流(FileOutputStream)实例

使用文件输出流将100~200之间能被3整除的数写到文本文件中,要求每10个数一行

import java.io.*;
public class first {
	public static void main(String[] args) throws Exception{
		int n,num,i=0;
		try {
			FileOutputStream fos=new FileOutputStream("D:/t.txt",true);
			for(n=100;n<=200;n++) {
				if(n%3==0) {
					i++;
					String str=String.valueOf(n);
					String str1=str+" ";
					byte[]buff=str1.getBytes();
					fos.write(buff);
					if(i%10==0) {
						str="\r\n";
						byte[]buf=str.getBytes();
						fos.write(buf);
					}
				}
			}
			fos.close();
		}catch(FileNotFoundException e1) {
			System.out.println(e1);
		}catch(IOException e2) {
			System.out.println(e2);
		}
	}
}

运行结果为:

1231231

字节数组输出流(ByteArrayOutputStream)

ByteArrayOutputStream类向内存的字节数组写入数据,它也采用了适配器设计模式,把字节数组类型转换为输出流类型,使程序能对字节数组进行写操作。其构造方法为:

  • ByteArrayOutputStream():创建一个新的字节数组输出流;
  • ByteArrayOutputStream(int size):创建指定大小缓冲区的字节数组输出流。

字节数组输出流(ByteArrayOutputStream)实例

import java.io.*;
public class first {
	public static void main(String[] args) throws Exception{
		ByteArrayOutputStream baos=new ByteArrayOutputStream();
		String s="Welcome to java";
		byte[]buf=s.getBytes();
		baos.write(buf);
		System.out.println(baos.toString());
		byte[]b=baos.toByteArray();
		for(int i=0;i<b.length;i++) {
			System.out.print((char)b[i]);
		}
	}
}

运行结果为:

Welcome to java
Welcome to java

数据输出流类(DataOutputStream)

类DataOutputStream实现各种基本类型数据的输出处理,它实现了DataOutput接口,在该接口中定义了基本类型数据的输出方法。

DataOutputStream类的所有方法都以“write”开头,具体如下:

  • writeByte():向输出流中写入byte类型的数据;
  • writeLong():向输出流中写入Long类型的数据;
  • writeFloat():向输出流中写入float类型的数据;
  • writeUTF():向输出流中写入UTF-8编码的数据。

其中,writeBytes、writeChars、writeUTF这3个方法均是以字符串作为参数,但它们的数据写入结果不同,writeBytes是按字节写入数据,它会丢弃掉字符的高8位,所以,不适合处理汉字。writeChars是按字符写入数据。writeUTF是按UTF-8字符编码写入数据。

数据流类(DataOutputStream)实例

找出10~100之间的所有姐妹素数,写入文件中。所谓姐妹素数,是指相邻两个奇数均为素数。

import java.io.*;
public class first {
	public static boolean isPrime(int n) {
		for(int k=2;k<=Math.sqrt(n);k++) {
			if(n%k==0)
				return false;
		}
		return true;
	}
	public static void main(String[] args) throws Exception{
		try {
			FileOutputStream file=new FileOutputStream("D:/x.txt");
			DataOutputStream out=new DataOutputStream(file);
			for(int n=11;n<100;n+=2) {               
				if(isPrime(n)&&isPrime(n+2)) {         //两个相邻奇数是否为素数
					out.writeInt(n);                   //将素数写入文件
					out.writeInt(n+2);
				}
			}
			out.close();
		}catch(IOException e) {}
	}
}

运行结果为:

213123

最后

好了,关于Java  I/O流——面向字节的输入/输出流的知识学到这里,谢谢观看!!!

我们下篇文章再见!!!

成功不是将来才有的,而是从决定去做的那一刻起,持续累积而成。

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白巧克力LIN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值