Java学习笔记-Day28 Java IO流(二) 流式部分



一、流(Stream)的分类


如果需要将Java中能够表达所有数据缓存在内存中(包括字符类型或二进制类型),最适宜于使用的数据类型是:byte[],原因是Java中所有的数据类型占据的空间都是byte型的整数倍数。

(1)根据流动方向的不同,流分为 输入流输出流

  • 输入流(读):内存读取磁盘的数据。
  • 输出流(写):内存的数据写入到磁盘。

(2)对于输入流和输出流,由于传输格式的不同,又分为 字节流字符流

  • 字节流:是指8位的通用字节流,以字节为基本单位,在java.io包中,对于字节流进行操作的类大部分继承于字节输入流类(InputStream)和字节输出流类(OutputStream)。

  • 字符流:是指16位的Unicode字符流,以字符(两个字节)为基本单位,非常适合处理字符串和文本,对于字符流进行操作的类大部分继承于字符输入流类(Reader)和字符输出流类(Writer)。

二、字节流

1、OutputStream(字节输出流)


OutputStream类(java.io.OutputStream)是一个抽象类,提供了Java向流中以字节为单位写入数据的公开接口,大部分字节输出流都继承自OutputStream抽象类。

  • 部分方法

(1)void flush():刷新此输出流,并强制写出任何缓冲的输出字节。

(2)void close():先会刷新此输出流,再关闭此输出流,并释放与此流相关联的任何系统资源。

(3)void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。

(4)void write(byte[] b, int off, int len):将指定的字节数组从偏移 off开始,写入 len个字节到此输出流。

(5)abstract void write(int b):将指定的字节写入此输出流。

2、InputStream(字节输入流)


InputStream类(java.io.InputStream )是一个抽象类,提供了Java中从流中以字节为单位读取数据的公开接口,大部分字节输入流都继承自InputStream抽象类。

  • 部分方法

(1)int available():返回从该输入流中可以读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。

(2)void close():关闭此输入流,并释放与流相关联的任何系统资源。

(3)void mark(int readlimit):标记此输入流中的当前位置。

(4)void reset():将此流重新定位到上次在此输入流上调用 mark方法时的位置。

(5)boolean markSupported():测试这个输入流是否支持 mark和 reset方法。

(6)abstract int read():从输入流读取数据的下一个字节。

(7)int read(byte[] b):从输入流读取一些字节数,并将它们存储到缓冲区 b 。

(8)int read(byte[] b, int off, int len):从输入流读取最多 len字节的数据到一个字节数组。

(9)long skip(long n):跳过并丢弃来自此输入流的 n字节数据。

3、FileOutputStream(文件输出流 / 原始字节输出流)


FileOutputStream(文件输出流)继承于OutputStream抽象类,是进行文件内容写操作的最基本类工具,FileOutputStream能够将内存中的数据输出到文件中。

FileOutputStream是用于将数据写入 File 或 FileDescriptor 的输出流。文件是否可用或能否可以被创建取决于基础平台。有些平台一次只允许一个 FileOutputStream(或其他文件写入对象)打开文件进行写入。在这种情况下,如果所涉及的文件已经打开,则此类中的构造方法将失败。

FileOutputStream 用于写入诸如图像数据之类的原始字节的流。如果是要将字符流输出到文件,请使用 FileWriter。

  • 构造方法

(1)FileOutputStream(File file) throws FileNotFoundException:使用File对象创建文件输出流对象,如果文件打开失败,将抛出FileNotFoundException异常。

(2)FileOutputStream(File file, boolean append) throws FileNotFoundException:使用File对象创建文件输出流对象,并由参数append指定是否追加文件内容,true为追加,false为不追加(将会直接删除以前的文件内容)。如果文件存在但是是一个目录而不是常规文件,不存在但不能创建,或者由于任何其他原因无法打开,那么抛出一个FileNotFoundException 异常。

(3)FileOutputStream(String name) throws FileNotFoundException:直接使用文件名或路径创建文件输出流对象,如果文件打开失败,将抛出FileNotFoundException异常。

(4)FileOutputStream(String name, boolean append) throws FileNotFoundException:直接使用文件名或路径创建文件输出流对象,并由参数append指定是否追加,true为追加,false为不追加(将会直接删除以前的文件内容)。如果文件存在但是是一个目录而不是常规文件,不存在但不能创建,或者由于任何其他原因无法打开,那么抛出一个FileNotFoundException 异常。

  • 部分方法

(1)void close():关闭此文件输出流,并释放与此流有关的所有系统资源。

(2)protected void finalize():清理到文件的连接,并确保在不再引用此文件输出流时调用此流的 close 方法。

(3)FileChannel getChannel():返回与此文件输出流有关的唯一 FileChannel 对象。

(4)FileDescriptor getFD():返回与此流有关的文件描述符。

(5)void write(byte[] b):将 b.length 个字节从指定 byte 数组写入此文件输出流中。

(6)void write(byte[] b, int off, int len):将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。

(7)void write(int b):将指定字节写入此文件输出流。

4、FileInputStream(文件输入流 / 原始字节输入流)


FileInputStream(文件输入流 )继承于InputStream抽象类,是进行文件内容读操作的最基本类工具,FileOutputStream能够获取文件中的数据。

FileInputStream 用于读取诸如图像数据之类的原始字节的流。要从文件中读取字符流,请使用 FileReader。

  • 构造方法

(1)FileInputStream(File file):通过打开与实际文件的连接创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。

(2)FileInputStream(FileDescriptor fdObj):创建 FileInputStream通过使用文件描述符 fdObj ,其表示在文件系统中的现有连接到一个实际的文件。

(3)FileInputStream(String name):通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。

  • 部分方法

(1)int available():返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。

(2)void close():关闭此文件输入流并释放与流相关联的任何系统资源。

(3)protected void finalize():确保当这个文件输入流的 close方法没有更多的引用时被调用。

(4)FileChannel getChannel():返回与此文件输入流相关联的唯一的FileChannel对象。

(5)FileDescriptor getFD():返回表示与此 FileInputStream正在使用的文件系统中实际文件的连接的 FileDescriptor对象。

(6)int read():从该输入流读取一个字节的数据。

(7)int read(byte[] b):从该输入流读取最多 b.length个字节的数据为字节数组。

(8)int read(byte[] b, int off, int len):从该输入流读取最多 len字节的数据为字节数组。

(9)long skip(long n):跳过并从输入流中丢弃 n字节的数据。

5、DataOutputStream(数据输出流)


DataOutputStream(数据输出流)可以使程序以便携的方式将Java基本数据类型和字符串类型的数据写入到输出流。

写入文件的是字节类型的数据,Java的基本数据类型都有自己的字节大小,如:int类型的字节大小为 4 byte、float类型的字节大小为 4 byte等。字符串的字节大小不固定。

  • 构造方法

(1)DataOutputStream(OutputStream out):创建一个新的数据输出流,以将数据写入指定的底层输出流。

  • 部分方法

(1)void writeUTF(String str):使用修改的UTF-8编码以机器无关的方式将字符串写入基础输出流。

(2)void writeDouble(double v):使用类 Double 的 doubleToLongBits 方法将double参数转换成 long ,然后该 long 值作为8字节的数量、高字节写入基础输出流。

(3)void writeFloat(float v):使用类 Float 的 floatToIntBits 方法将float参数转换成 int ,然后该 int值作为一个4字节的数量、高字节写入基础输出流。

(4)void writeInt(int v):将 int作为四字节,高位字节写入底层输出流。

(5)void writeLong(long v):将 long写入底层输出流,为8字节,高字节为首。

(6)void writeShort(int v):将 short写入底层输出流作为两个字节,高字节优先。

(7)void write(int b):将指定的字节(参数 b的低8位)写入底层输出流。

  • 写入数据到文件中(抛出异常的代码)
public class TestOutputStream {
	public static void main(String[] args) throws IOException {
		
		FileOutputStream fos = new FileOutputStream("E://a.txt");
		DataOutputStream dos = new DataOutputStream(fos);
		int i = 100;
		double d = 200.0;
		float f = 300f;
		String name = "小明";
		String addr = "中国";
		
		dos.writeInt(i);
		dos.writeDouble(d);
		dos.writeFloat(f);
		
		dos.close();
		fos.close();
	}
}
  • 写入数据到文件中(使用try/catch/finally语句处理异常的代码)
public class TestOutputStream {
	public static void main(String[] args) {
		FileOutputStream fos = null;
		DataOutputStream dos = null;
		try {
			fos = new FileOutputStream("E://a.txt");
			dos = new DataOutputStream(fos);
			int i = 100;
			String name = "小明";
			String addr = "中国";

			dos.writeInt(i);
			dos.writeUTF(name);
			dos.writeUTF(addr);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (dos != null) {
					dos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				if (fos != null) {
					fos.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}
}

6、DataInputStream(数据输入流)


程序可以使用DataInputStream(数据输入流)直接读取输入流中Java基本数据类型和字符串类型的数据。

注意:数据的数据类型的读取顺序要与写入顺序一致,不一致的话会抛出 EOFException 异常。

EOFException 是End Of File Exception,当输入过程中意外到达文件或流的末尾时,抛出此异常。

  • 构造方法

(1)DataInputStream(InputStream in):创建使用指定的底层InputStream的DataInputStream。

  • 部分方法

(1)String readUTF():读取已使用 修改的 UTF-8格式编码的字符串。

(2)int readInt():读取四个输入字节并返回一个 int值。

(3)double readDouble():读取八个输入字节并返回一个 double值。

(4)float readFloat():读取四个输入字节并返回一个 float值。

(5)boolean readBoolean():读取一个输入字节,并返回 true如果该字节不为零, false如果该字节是零。

(6)byte readByte():读取并返回一个输入字节。

(7)char readChar():读取两个输入字节并返回一个 char值。

(8)int read(byte[] b):从包含的输入流中读取一些字节数,并将它们存储到缓冲区数组 b 。

(9)int read(byte[] b, int off, int len):从包含的输入流读取最多 len个字节的数据为字节数组。

  • 读取文件中的数据(抛出异常的代码)
public class TestInputStream {
	public static void main(String[] args) throws IOException {
		
		FileInputStream fis = new FileInputStream("E://a.txt");
		DataInputStream dis = new DataInputStream(fis);
		
		String addr = dis.readUTF();
		int i = dis.readInt();
		String name = dis.readUTF();
		
		
		System.out.println("i="+i);
		System.out.println("name="+name);
		System.out.println("addr="+addr);
		
		dis.close();
		fis.close();
	}
}

  • 读取文件中的数据(使用try/catch/finally语句处理异常的代码)
public class TestInputStream {
	public static void main(String[] args) {
		FileInputStream fis = null;
		DataInputStream dis = null;
		try {
			fis = new FileInputStream("E://a.txt");
			dis = new DataInputStream(fis);

			int i = dis.readInt();
			String name = dis.readUTF();
			String addr = dis.readUTF();

			System.out.println("i=" + i);
			System.out.println("name=" + name);
			System.out.println("addr=" + addr);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				
				if (dis != null) {
					dis.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
			try {
				
				if (fis != null) {
					fis.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

三、文件的复制


通过FileOutPutStream与FileInputStream,实现简单的文件复制操作。

因为要复制的文件的文件类型不确定,所以使用字节流来操作。

文件复制的操作:通过FileInPutStream(文件输入流)读取某个文件的字节数据,并存入内存中,再通过FileOutPutStream(文件输出流)将内存中的字节数据写入目标文件中。

public class CopyFile {
	public static void main(String[] args) {
		copy("D://a.txt","E://b.txt");

	}
	public static void copy(String srcpath,String destpath) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			fis = new FileInputStream(srcpath);
			fos = new FileOutputStream(destpath);
			
			int len=0;
			byte[] b = new byte[1024];
			
			if((len = fis.read(b)) != -1) {
				fos.write(b, 0, len);
			}
			System.out.println("文件复制成功!");
		}catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				if(fis != null) {
					fis.close();
				}
				
				if(fos != null) {
					fos.close();
				}
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

四、字符流


虽然FileInputStream类和FileOutputStream类可以高效率地读写文件,但对于Unicode编码的文件,我们需要自行将读取到的字节数据根据编码规则还原为字符串,因此使用它们有可能出现乱码。考虑到Java是跨平台的语言,要经常操作Unicode编码的文件,使用基于以字符为读写的基本单元的字符流来操作文件是有必要的。以字符为单位进行数据输出的工具继承自Writer抽象类,以字符为单位进行数据输入的工具继承自Reader抽象类。

1、Writer(字符输出流)


Writer类(java.io.Writer )和OutputStream类一样也提供了统一的往流中写入数据的方法,和OutputStream不同的是,写入数据的单位由字节变成了字符。

  • 部分方法

(1)Writer append(char c):将指定的字符附加到此Writer对象。

(2)Writer append(CharSequence csq):将指定的字符序列附加到此Writer对象。

(3)Writer append(CharSequence csq, int start, int end):将指定字符序列的子序列附加到此Writer对象。

(4)abstract void close():关闭流,先刷新。

(5)abstract void flush():刷新流。

(6)void write(char[] cbuf):写入一个字符数组。

(7)abstract void write(char[] cbuf, int off, int len):写入字符数组的一部分。

(8)void write(int c):写入一个字符。

(9)void write(String str):写入一个字符串。

(10)void write(String str, int off, int len):写入一个字符串的一部分。

2、Reader(字符输入流)


以字符为单位进行数据读取的工具继承自Reader,Reader会将读取到的数据按照标准的规则转换为Java字符串对象。

Reader类(java.io.Reader)也提供的统一读取数据的方法,和InputStream不同,实际开发时更多的是调用不同Reader提供的特殊读取方法。

  • 部分方法

(1)abstract void close():关闭流,并释放与之相关联的任何系统资源。

(2)void mark(int readAheadLimit):标记流中的当前位置。

(3)void reset():重置流。

(4)boolean markSupported():告诉这个流是否支持mark()操作。

(5)int read():读一个字符。

(6)int read(char[] cbuf):将字符读入数组。

(7)abstract int read(char[] cbuf, int off, int len):将字符读入数组的一部分。

(8)int read(CharBuffer target):尝试将字符读入指定的字符缓冲区。

(9)boolean ready():告诉这个流是否准备好被读取。

(10)long skip(long n):跳过字符。

3、FileReader(文件读取流)


FileReader类(java.io.FileReader)称为文件读取流,允许以字符流的形式对文件进行读操作。与FileWriter相似,该类将从文件中逐个地读取字符,效率比较低下,因此一般也将该类对象包装到缓冲流(BufferedReader)中进行操作。

*构造方法

(1)FileReader(File file) throws FileNotFoundException:使用File对象创建文件读取流对象,如果文件打开失败,将抛出FileNotFoundException异常。

(2)FileReader(String name) throws FileNotFoundException:使用文件名或路径创建文件读取流对象,如果文件打开失败,将抛出FileNotFoundException异常。

		//1、创建FileReader对象
		FileReader fr = new FileReader("C:\\information.txt");		
		//2、创建File对象,用来获取文件的长度
		File file = new File("C:\\information.txt");
		//3、创建一个长度为 文件长度 的字符数组
		char[] c = new char[(int) file.length()];
		System.out.println((int) file.length());
		//4、使用FileReader对象的read方法读取文件内容,存入字符数组,返回字符个数
		int num = fr.read(c);
		System.out.println(num);//num是字符个数
		System.out.println(c);

注意:文件中字符的字节大小:中文字符为2字节,数字字符和英文字符为1字节。

4、FileWriter(文件写入流)


FileWriter类(java.io.FileWriter )称为文件写入流,以字符流的形式对文件进行写操作。FileWriter将逐个向文件写入字符,效率比较低下,因此一般将该类对象包装到缓冲流(BufferedWriter)中进行操作。

  • 构造方法

(1)FileWriter(File file) throws IOException:使用File对象创建文件写入流对象,如果文件打开失败,将抛出IOException异常,必须处理异常。

(2)FileWriter(File file, boolean append) throws IOException:使用File对象创建文件写入流对象,并由参数append指定是否追加。如果文件打开失败,将抛出IOException异常,必须处理异常。

(3)FileWriter(String name) throws IOException:直接使用文件名或路径创建文件写入流对象。如果文件打开失败,将抛出IOException异常,必须处理异常。

(4)FileWriter(String name, boolean append) throws IOException:直接使用文件名或路径创建文件写入流对象,并由参数append指定是否追加。如果文件打开失败,将抛出IOException异常,必须处理异常。

  • 将数据写入文件
		//1、创建FileWriter对象
		FileWriter fw = new FileWriter("C:\\information.txt");
		//2、调用writer方法完成写的动作
		fw.write("abcd1234");
		//3、刷新流,数据才能进入文件
		fw.flush();
		//4、关闭流,也会默认刷新流
		fw.close();
  • 在文件的内容后增添数据
		//1、创建FileWriter对象
		FileWriter fw = new FileWriter("C:\\information.txt",true);
		//2、调用append方法完成添加的动作
		fw.append("\r\n刚添加的数据");
		//3、关闭流,也会默认刷新流
		fw.close();

注意:调用write()或者append()方法,只是将数据写到内存中,需要通过flush()方法或者close()方法,将内存中的数据写到文件中。在流使用结束后,一定要记得关闭流。\r\n是文件中的换行。

5、BufferedReader(缓冲读取流)


BufferedReader类(java.io.BufferedReader)拥有8192字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取。

  • 构造方法

(1)BufferedReader(Reader in):创建使用默认大小的输入缓冲区的缓冲字符输入流。

(2)BufferedReader(Reader in, int sz):创建使用指定大小的输入缓冲区的缓冲字符输入流。

  • 部分方法

String readLine():一次性读取一行文本(以换行符\n、回车符\r区分),如果读取到流的末尾,无法读取更多的数据,则返回null。

		//1、创建FileReader对象
		FileReader fr = new FileReader("D:\\information.txt");			
		//2、创建BufferedReader对象,FileReader对象作为参数
		BufferedReader br = new BufferedReader(fr);
		//3、创建字符串变量s
		String s = null;
		//4、使用BufferedReader对象的readLine方法读取一行字符,赋值给字符串变量s
		while((s = br.readLine())!=null) {
			System.out.println(s);
		}
		//5、关闭BufferedReader流
		br.close();	
		//6、关闭FileReader流
		fr.close();

6、BufferedWriter(缓冲写入流)


BufferedWriter类(java.io.BufferedWriter)拥有8192字符的缓冲区。使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。

  • 构造方法

(1)BufferedWriter(Writer out):创建使用默认大小的输出缓冲区的缓冲字符输出流。

(2)BufferedWriter(Writer out, int sz):创建一个新的缓冲字符输出流,使用给定大小的输出缓冲区。

  • 部分方法

(1)void write(char[] cbuf, int off, int len):写入字符数组的一部分。

(2)void write(int c):写一个字符。

(3)void write(String s, int off, int len):写一个字符串的一部分。

		//1、创建FileWriter对象
		FileWriter fw = new FileWriter("D:\\information.txt");			
		//2、创建BufferedWriter对象,FileWriter对象作为参数
		BufferedWriter bw = new BufferedWriter(fw);
		//3、调用BufferedWriter对象的write方法
		bw.write("abcd123456");
		//4、关闭BufferedWriter流
		bw.close();	
		//5、关闭FileWriter流
		fw.close();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值