Java学习笔记-Day27 Java IO流(一) 非流式部分



一、Java IO

1、IO的层次


Java IO主要包括三个部分:

(1)流式部分:IO的主体部分。

(2)非流式部分:主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor类等等。

(3)其他类:文件读取部分的类与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。

注意:这里的IO指的是BIO,即阻塞IO。

2、java.io包


java.io包是JDK内置的包,其中包含一系列对文件和目录的属性进行操作,对文件进行读写操作的类。程序中如果要使用到该包中的类,对文件或流进行操作,则必须显式地声明如下语句:

import java.io.*;

java.io包是Java中最传统的IO操作,在利用io包的输入流工具(InputStream、Reader)进行数据读取操作时,如果无法读取到需要的内容,将会导致执行读取数据操作的线程陷入阻塞状态。因此,在进行流的写入和读取时要尤为小心,保证数据读取的数量和顺序的准确性,否则可能导致程序执行异常。

二、非流式部分

1、File类


File类(java.io.File)的对象是一个表示文件和目录的路径。在程序中,一个File类的对象可以代表一个文件或目录。

当创建一个File对象后,就可以利用它来对文件或目录的属性进行操作,如:文件名、最后修改日期、文件大小等等。

需要注意的是,File对象并不能直接对文件内容进行读写操作,只能查看文件的属性。实例化File类时,如果该File类的对象表示的目录或文件不存在,是不会创建该对象表示的目录或文件。如果想创建该对象表示的目录或文件,就需要调用该File对象的 createNewFile()mkdir() / mkdirs() 方法。

1.1、构造方法

File(String pathname):通过将给定的路径名的字符串转换为抽象路径名来创建新的 File实例。

1.2、路径名的表达

由于在Java中 \ 符号是转义字符,如果使用 \ 作为路径分割符,则实际需要编写 \\,有一个更好的替代方法是使用Unix系统中常用的 / 作为路径分割符。

绝对路径:路径名以盘符开头,从磁盘的根目录开始。如:C:\\Windows\\addins

相对路径:路径名以 /\\ 开头,则相对路径的根为 当前项目所在 磁盘的根目录 。如:\\14.txt。不以 /\\ 开头,则相对路径的根为 项目的根目录,如:14.txt

1.3、部分方法

(1)boolean canExecute():测试程序是否可以执行此File对象表示的文件。如果返回值为true,表示能执行,如果返回值为false,表示不能执行。

(2)boolean canRead():测试程序是否可以读取由此File对象表示的文件。如果返回值为true,表示能读取,如果返回值为false,表示不能读取。

(3)boolean canWrite():测试程序是否可以修改由此File对象表示的文件。如果返回值为true,表示能写,如果返回值为false,表示不能写(只读)。

(4)boolean createNewFile() :当且仅当具有该名称的文件尚不存在时,会创建一个由该抽象路径名命名的新的空文件。

(5)boolean delete():删除由此抽象路径名表示的File对象。

(6)String getAbsolutePath():返回此File对象的绝对路径名的字符串。

(7)boolean isDirectory():测试此File对象是否为目录。

(8)boolean isFile():测试此File对象是否为文件。

(9)long lastModified():返回此File对象表示的文件上次修改的时间,返回值为毫秒值。

(10)long length():返回由此File对象表示的文件的长度,单位为字节。

(11)boolean mkdir():创建由此File对象命名的目录。

(12)boolean mkdirs():创建由此File对象命名的目录,包括任何必需但不存在的父目录。

(13)File[] listFiles():返回一个File类型的数组,该数组包含由此File对象表示的目录中的文件和目录的File对象。如果被文件的File对象调用或者没有访问权限,则会返回null。

1.4、遍历所有目录下的文件


如果想要遍历所有目录下的文件,可以使用递归遍历。

/**
 * 经典面试题: 遍历目录下的文件(逐级遍历)
 */
public class TestFile03 {
	public static void main(String[] args) throws IOException {
		// 使用路径名字符串创建一个File对象
		File file = new File("C:\\Users");
		// 调用showFiles方法
		showFiles(file);
	}

	/**
	 * showFiles方法
	 */
	public static void showFiles(File file) {	
		//返回一个File类型的数组,表示由此File对象表示的目录中所有子文件和子目录
		File[] files = file.listFiles();
		// 没有访问权限,则会返回null
		if (files != null) {
			// 遍历目录下的文件和子目录
			for (File f : files) {
				if (f.isFile()) {
					//输出绝对路径名
					System.out.println(f.getAbsolutePath());
				} else {
					// 递归调用
					showFiles(f);
				}
			}
		}
	}
}

2、RandomAccessFile


RandomAccessFile 既可以读取文件内容,也可以向文件输出数据。RandomAccessFile 支持随机访问的方式,可以直接跳转到文件的任意地方来读写数据。

由于RandomAccessFile可以自由访问文件的任意位置,所以如果需要访问文件的部分内容,而不是把文件从头读到尾,使用RandomAccessFile将是更好的选择。

2.1、构造方法

(1)RandomAccessFile(File file, String mode):创建一个随机访问文件流,从File参数指定的文件中读取或者写入数据。

(2)RandomAccessFile(String name, String mode):创建一个随机访问文件流,从String参数指定的文件中读取或者写入数据。

构造方法的第二个参数mode:
① “r” : 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
② “rw”: 打开以便读取和写入。
③ “rws”: 打开以便读取和写入。相对于 “rw”,“rws” 还要求对“文件的内容”或“元数据”的每个更新都同步写入到基础存储设备。
④ “rwd” : 打开以便读取和写入,相对于 “rw”,“rwd” 还要求对“文件的内容”的每个更新都同步写入到基础存储设备。

2.2、关于指针位置的方法

(1)long getFilePointer():返回此文件中的当前偏移量(文件指针的位置)。

(2)void seek(long pos):设置文件指针偏移,从该文件的开头测量,发生下一次读取或写入。

2.3、读的部分方法 readXxx()

(1)boolean readBoolean():从此文件读取一个 boolean 。

(2)byte readByte():从此文件中读取一个带符号的byte。

(3)char readChar():从此文件中读取一个字符。

(4)double readDouble():从此文件读取 double 。

(5)float readFloat():从此文件读取一个 float 。

2.4、写的部分方法 writeXxx()

(1)void writeDouble(double v):使用Double类的doubleToLongBits方法将double参数转换成 long,然后将该 long值到作为一个8字节的数量、高字节写入到该文件,。

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

(3)void writeInt(int v):将 int写入文件为4个字节,高字节 int 。

(4)void writeLong(long v):将 long写入文件为8个字节,高字节为先。

(5)void writeShort(int v):将 short写入文件作为2个字节,高字节优先。

2.5、字符串的写入方法

  • 字符串的写入方法

(1)void writeBytes(String s):将字符串作为字节序列写入文件。

(2)void writeChars(String s):将字符串作为字符序列写入文件。

(3)void writeUTF(String str):以机器无关的方式使用 modified UTF-8编码将字符串写入文件。

RandomAccessFile 类中写入字符串的三个方法是实现了 DataOutput接口而具有的。writeBytes 是以一串有序的字节将字符串写入文件,每一个字符都是以其高八位写入的。writeChars 是以一串有序的字符写入字符串,每一个字符都由两个字节组成。writeUTF 是使用modified UTF-8 编码以一种与机器无关的方式写入字符串数据,具体有其自己的写入规则。

对于使用 RandomAccessFile 类写入、读出字符串,建议大家统一标准:

写入时使用 writeBytes 方法,将字符串以有序字节的形式写入文件,读取时,根据之前写入的字符串长度,通过循环读取每一个字节,然后将其构造成字符串。但是有中文字符的时候,不建议使用,因为会产生乱码。JAVA中的char是16位的,一个char存储一个中文字符,直接用writeBytes方法转换会变为8位,直接导致高8位丢失。从而导致中文乱码。

public class TestRandomAccess03 {
	public static void main(String[] args) throws IOException {
		write();
		read();
	}

	//中文会出现乱码
	public static void read() throws IOException {
		RandomAccessFile fa = new RandomAccessFile("E://infomation.txt", "r");
		// 设置指针位置
		fa.seek(0);
		System.out.println("point="+fa.getFilePointer());
		byte[] b3 = new byte[7];
		fa.read(b3);
		System.out.println("b3="+new String(b3));
		//7
		System.out.println("point="+fa.getFilePointer());
		
		// 设置指针位置
		fa.seek(7);
		System.out.println("point="+fa.getFilePointer());
		byte[] b4 = new byte[8];
		fa.read(b4);
		System.out.println("b3="+new String(b4));
		//15
		System.out.println("point="+fa.getFilePointer());

		fa.close();
	}

	// writeBytes(String s):将字符串作为字节序列写入文件。
	// 指针计算的是字符
	public static void write() throws IOException {
		RandomAccessFile fa = new RandomAccessFile("E://infomation.txt", "rw");
		
		System.out.println("point="+fa.getFilePointer());
		fa.writeBytes("hello爪哇");
		
		System.out.println("point="+fa.getFilePointer());
		fa.writeBytes("helloTom");
		
		System.out.println("point="+fa.getFilePointer());

		fa.close();
	}
}

2.6、统一使用的字符串写入读出方法


字符串写入方法

void write(byte[] b):从指定的字节数组写入 b.length个字节到该文件,从当前文件指针开始。

字符串读出方法

int read(byte[] b):从该文件读取最多 b.length字节的数据到字节数组 。

  • 使用字符串写入读出方法的代码
ublic class TestRandomAccess04 {
	public static void main(String[] args) throws IOException {
		write();
		read();
	}

	// read(byte[] b):从该文件读取最多 b.length字节的数据到字节数组。
	// 指针计算的是 字节
	public static void read() throws IOException {
		RandomAccessFile fa = new RandomAccessFile("E://infomation.txt", "r");

		System.out.println("point="+fa.getFilePointer());
		byte[] b = new byte[17];
		System.out.println(fa.read(b));
		System.out.println("b="+new String(b));
		
		fa.close();
		
	}

	// write(byte[] b):从指定的字节数组写入 b.length个字节到该文件,从当前文件指针开始。
	// 指针计算的是 字节
	public static void write() throws IOException {
		RandomAccessFile fa = new RandomAccessFile("E://infomation.txt", "rw");
		//0
		System.out.println("point="+fa.getFilePointer());	
		fa.write("hello爪哇".getBytes());
		//9
		System.out.println("point="+fa.getFilePointer());
		fa.write("helloTom".getBytes());
		//17
		System.out.println("point="+fa.getFilePointer());

		fa.close();
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值