Java 第十三课:Java I/O流

一、流的概念
流是一组有序数据序列,它将数据从一个地方带到另外一个地方。Java中所有的数据都是使用流来读写的。根据流向的不同将流分为输入(Input)流和输出(Output)流两种。Java流功能都封装在java.io包中。
流的分类:
1. 按照流的方向主要分为输入流和输出流。
2. 按照数据单位的不同分为字节流字符流。
3. 按照功能划分为节点流和处理流。

二、输入流

  1. 所有输入流类都是 InputStream 抽象类(字节输入流)和 Reader 抽象类(字符输入流)的子类。其中 InputStream 类是字节输入流的抽象类,是所有字节输入流的父类
    InputStream类的层次i结构图片来自网络。
    InputStream 类中所有方法遇到错误时都会引发 IOException 异常,InputStream类的常用方法:

    1. int read(); //每次读取8个字节的数据,并转换成0~255的整数返回,如果遇到输入流结尾返回-1
    2. int read(byte[]b); //读取若干个字节保存到指定的数组b中,然会读到的字节数,如果遇到流结尾返回-1
    3. int read(byte[], int offset, int len);
    4. void close();
    5. int available(); //返回可以从数据源读取的数据流的位数
    6. skip(long n);
    7. boolean markSupported(); //判断输入流是否可以重复读取,如果可以返回true,否则返回false
    8. void mark(int readLimit); //如果可以重复读取,从刘的当前位置做标记,readLimit指定可以设置标记的子结数
    9. void reset(); //如果可以重复读取,复位到刚才被标记的位置,之后就可以重新去读标记过的数据。
  2. InputStream使用来处理单字节的,但是Java中的字符是Unicode编码,即双字节。当处理字符文本时就很不方便。因此Java提供了Reader类。该类是字符输入流的抽象类,即所有字输入流的实现都是它的子类。
    Reader类层次结构图片来自网络

三、输出流

  1. Java 中所有输出流类都是 OutputStream 抽象类(字节输出流)和 Writer 抽象类(字符输出流)的子类。其中 OutputStream 类是字节输出流的抽象类,是所有字节输出流的父类,

OutputStream类层次结构图片来自网络

OutputStream类是所有字节输出流的超类,用于一二进制的形式将数据写入目标设备,该类是抽象类,不能被实例化。
OutputStream类方法:

  1. int write(b);

  2. int write(byte[]b);

  3. int write(byte[]b, int offset, int len);

  4. close();

  5. flush();

  6. 字符输出流的父类Writer
    Writer类的层次结构图片来自网络

四、字节数组输入输出流

1. 字节数组输入流:	
构造方法:
	1. ByteArraryInputStream(byte[] buf);
	2. ByteArrayInputStream(byte[] buf, int offset, int num);

2. 字节流数组输出流:
	构造方法:
	1. ByteArrayOutputStream();
	2. ByreArrayOutputStream(int size);
	实例:
	public static void myJavaIOTest( ) {
		byte[] inputArray = new byte[]{1, -1, 2, 127, 0};	//java byte的范围[-128, 127]
		//ByteArrayInputStream bais = new ByteArrayInputStream(inputArray, 3, 10);
		ByteArrayInputStream bais = new ByteArrayInputStream(inputArray);
		Integer num = bais.read();	//read()将byte转换成int[0, 255]返回
		while(num != -1) {
			System.out.printf("%d\t", num);
			num = bais.read();
		}
		System.out.println();
		
		byte[] outputArray = new byte[10];
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		baos.write(inputArray, 0, 5);
		System.out.printf("outputArray size:%d\n", baos.size());
		byte[] newOutputArray = baos.toByteArray();
		System.out.println(Arrays.toString(newOutputArray));
	}
	输出结果:
		1	255	2	127	0			//注释1
		outputArray size:5
		[1, -1, 2, 127, 0]
	注释1:
		Java中byte的范围是[-128, 127];
		-1变成了255,负数的二进制形式以补码的形式保存。
		-1的二进制存放形式:
		1的原码是00000001,然后反码为11111110, 然后进行补码操作(末尾位加1),变成11111111。

五、文件输入输出流

1. 文件输入流
构造函数:
	1. FileInputSttream(File file);
	2. FileInputStream(String name);
2. 文件输出流
	构造函数:
	1. FileOutputStream(File file);
	2. FileOutputStream(File file, boolean append);
	3. FileOutputStream(String name);
	4. FileOutputStream(String name, boolean append);	
	注意:append为true表示追加,false表示覆盖从0开始写。
实例:
	public static void javaFileIOTest() {
		Integer val = -1;
		byte[] readBuffer = new byte[1024];
		try {
			FileInputStream fis = new FileInputStream("/home/gchuan/eclipse-workspace/lesson3/a.txt");
			try {
				val = fis.available();		//get file size
				while((val = fis.read(readBuffer)) != -1) {
					System.out.printf("Val = %d\n", val);
					String buffer = new String(readBuffer, 0, val);
					System.out.println(buffer);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			finally {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("======================================");
		File fileOutput = new File("/home/gchuan/eclipse-workspace/lesson3/b.txt");

		try {
			@SuppressWarnings("resource")
			FileOutputStream fos = new FileOutputStream(fileOutput);
			fos.write(readBuffer);
			fos.write(readBuffer, 0, val);
			fos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}

六、字符输入输出流

1. 文件输入流
构造函数:
	1. FileReader(File file);
	2. FileReader(String name);
2. 文件输出流
构造函数:
	1. FileWrite(File file);
	2. FileWrite(File file, boolean append);
	3. FileWrite(String name);
	4. FileWrite(String name, boolean append);	
	注意:append为true表示追加,false表示覆盖从0开始写。
代码参考字节输入输出实例

七、系统流
Java系统流封装在java.lang.System类中,每个Java程序运行时自带3个系统流,即:System.in、System.out、System.err。而且变量in、out、err作用域是public和static的。因此程序不需要引用System对象就可以使用。

	System.in		//标准输入流,默认设备就是键盘
	System.out		//标准输出流,默认设备是控制台
	System.err		//标准错误流,默认设备是控制台
实例:
	public static void javaSystemIOTest() {
		byte[] readBuffer = new byte[1024];
		System.out.println("请输入文字:");
		try {
			System.in.read(readBuffer);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("输入内容:" + (String)(new String(readBuffer)));
	}
	输出结果:
		请输入文字:
		Java 系统IO 输入输出
		输入内容:Java 系统IO 输入输出

八、Java 动态读取
动态读取是指从文件的任意位置访问文件,而不是必须冲开始读取到文件末尾。
动态读取需要用到JavaRandomAccessFile类,该类有一个文件指针用于标识当前流的读写位置,且可以前后移动。

构造方法:
RandomAccessFile(File file, String mode);
RandomAccessFile(String name, String mode);
参数:
	mode:r - 只读 |  rw - 读写
RandomAccessFile类方法:
	1. boolean readBoolean();
	2. byte readByte();
	3. char readChar();
	4. int readInt();
	5. long readLong();
	6. String readLong();
	7. void seek(long offset);
	8. void writeBoolean(boolean value);
	9. void writeByte(int value);
	10. void  writeChar(int value);
	11. void writeInt(int value);
	12. writeLong(long value);
	13. void writeBytes(String str);
	14. void skipBytes(int number);
实例:
	public static void javaRandomAccessTest() {
		int val = -1;
		byte[] buffer = new byte[1024];
		try {
			RandomAccessFile raf = new RandomAccessFile("/home/gchuan/eclipse-workspace/lesson3/c.txt", "rw");
			raf.writeBytes("java randmo access file test.\n");
			/*
			raf.close();
			RandomAccessFile rafr = new RandomAccessFile("/home/gchuan/eclipse-workspace/lesson3/c.txt", "r");
			System.out.printf("file size:%d\n", size);
			while ((val = rafr.read(buffer, 0, 5)) != -1) {
				System.out.println(new String(buffer, 0, val));
			}
			rafr.close();
			*/
			raf.seek(5);
			val = raf.read(buffer, 0, 1024);
			System.out.printf("read return value:%d\n", val);
			System.out.println(new String(buffer, 0, val));
			raf.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
	输出结果:
		read return value:25
		randmo access file test.

猜你喜欢

转载自blog.csdn.net/qq_39440596/article/details/88538172