Java学习之IO流

Java学习之IO流

IO流
	|--字节流
		|--字节输入流
			InputStream
				int read():一次读取一个字节
				int read(byte[] bys):一次读取一个字节数组
			
				|--FileInputStream
				|--BufferedInputStream
		|--字节输出流
			OutputStream
				void write(int by):一次写一个字节
				void write(byte[] bys,int index,int len):一次写一个字节数组的一部分
				
				|--FileOutputStream
				|--BufferedOutputStream
	|--字符流
		|--字符输入流
			Reader
				int read():一次读取一个字符
				int read(char[] chs):一次读取一个字符数组
				
				|--InputStreamReader
					|--FileReader
				|--BufferedReader
					String readLine():一次读取一个字符串
		|--字符输出流
			Writer
				void write(int ch):一次写一个字符
				void write(char[] chs,int index,int len):一次写一个字符数组的一部分
				
				|--OutputStreamWriter
					|--FileWriter
				|--BufferedWriter
					void newLine():写一个换行符
					
					void write(String line):一次写一个字符串

File类

我们要想实现IO的操作,就必须知道硬盘上文件的表现形式。而Java就提供了一个类File供我们使用。

构造方法

  • File(String pathname):根据一个路径得到File对象
  • File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
  • File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象
public class FileDemo {
	public static void main(String[] args) {
		// File(String pathname):根据一个路径得到File对象
		// 把e:\\demo\\a.txt封装成一个File对象
		File file = new File("E:\\demo\\a.txt");

		// File(String parent, String child):根据一个目录和一个子文件/目录得到File对象
		File file2 = new File("E:\\demo", "a.txt");

		// File(File parent, String child):根据一个父File对象和一个子文件/目录得到File对象
		File file3 = new File("e:\\demo");
		File file4 = new File(file3, "a.txt");

		// 以上三种方式其实效果一样
	}
}

功能

创建功能:
  • public boolean createNewFile():创建文件 如果存在这样的文件,就不创建了
  • public boolean mkdir():创建文件夹 如果存在这样的文件夹,就不创建了
  • public boolean mkdirs():创建文件夹,如果父文件夹不存在,会帮你创建出来
 		File file = new File("D:\\file");
        System.out.println("mkdir "+file.mkdir());
        File file1 = new File(file,"a.txt");
        System.out.println("creat: "+file1.createNewFile());
删除功能
  • public boolean delete()
重命名

如果路径名相同,就是改名。

如果路径名不同,就是改名并剪切。

  • public boolean renameTo(File dest)
判断功能
  • public boolean isDirectory():判断是否是目录
  • public boolean isFile():判断是否是文件
  • public boolean exists():判断是否存在
  • public boolean canRead():判断是否可读
  • public boolean canWrite():判断是否可写
  • public boolean isHidden():判断是否隐藏
获取功能
  • public String getAbsolutePath():获取绝对路径
  • public String getPath():获取相对路径
  • public String getName():获取名称
  • public long length():获取长度。字节数
  • public long lastModified():获取最后一次的修改时间,毫秒值
  • public String[] list():获取指定目录下的所有文件或者文件夹的名称数组
  • public File[] listFiles():获取指定目录下的所有文件或者文件夹的File数组
文件名称过滤

要想实现这个效果,就必须学习一个接口:文件名称过滤器

  • public String[] list(FilenameFilter filter)
  • public File[] listFiles(FilenameFilter filter)
public class FileDemo2 {
	public static void main(String[] args) {
		// 封装e判断目录
		File file = new File("e:\\");

		// 获取该目录下所有文件或者文件夹的String数组
		// public String[] list(FilenameFilter filter)
		String[] strArray = file.list(new FilenameFilter() {
			@Override
			public boolean accept(File dir, String name) {
				return new File(dir, name).isFile() && name.endsWith(".jpg");
			}
		});

		// 遍历
		for (String s : strArray) {
			System.out.println(s);
		}
	}
}

IO流的分类

流向:

​ 输入流 读取数据

​ 输出流 写出数据

数据类型:

​ 字节流

​ 字节输入流 读取数据 InputStream

​ 字节输出流 写出数据 OutputStream

字符流

​ 字符输入流 读取数据 Reader

​ 字符输出流 写出数据 Writer

字节流

输出流

OutputStream具体类为FileOutputStream类

操作步骤
  1. 创建字节输出流对象
  2. 写数据
  3. 释放资源
构造方法
  • FileOutputStream(File file)
  • FileOutputStream(String name)
输出方法
  • public void write(int b):写一个字节
  • public void write(byte[] b):写一个字节数组
  • public void write(byte[] b,int off,int len):写一个字节数组的一部分
public class FileOutputStreamDemo {
	public static void main(String[] args) throws IOException {
		// 创建字节输出流对象
		// FileOutputStream(File file)
		// File file = new File("fos.txt");
		// FileOutputStream fos = new FileOutputStream(file);
		// FileOutputStream(String name)
		FileOutputStream fos = new FileOutputStream("fos.txt");
		/*
		 * 创建字节输出流对象了做了几件事情:
		 * A:调用系统功能去创建文件
		 * B:创建fos对象
		 * C:把fos对象指向这个文件
		 */
		
		//写数据
		fos.write("hello,IO".getBytes());
		fos.write("java".getBytes());
		
		//释放资源
		//关闭此文件输出流并释放与此流有关的所有系统资源。
		fos.close();
		/*
		 * 为什么一定要close()呢?
		 * A:让流对象变成垃圾,这样就可以被垃圾回收器回收了
		 * B:通知系统去释放跟该文件相关的资源
		 */
		//java.io.IOException: Stream Closed
		//fos.write("java".getBytes());
	}
}

输入流

InputStream具体类为FileInputStream类

操作步骤
  • A:创建字节输入流对象
  • B:调用read()方法读取数据,并把数据显示在控制台
  • C:释放资源
输入方法
  • int read():一次读取一个字节 (汉字乱码)

    public class FileInputDemo {
        public static void main(String[] args) throws IOException {
            FileInputStream fis = new FileInputStream("xin.txt");
            int by = 0;
            while ((by = fis.read())!=-1){
                System.out.print((char)by);
            }
            fis.close();
        }
    }
    
  • int read(byte[] b):一次读取一个字节数组 (汉字正常)

public class FileInputDemo {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("xin.txt");
        byte[] bys = new byte[1024];
        int len = 0;
        while ((len = fis.read(bys)) != -1) {
            System.out.print(new String(bys, 0, len));
        }

        // 释放资源
        fis.close();
    }
}

复制文件

​ 数据源:从哪里来

a.txt – 读取数据 – FileInputStream

​ 目的地:到哪里去

b.txt – 写数据 – FileOutputStream

//一个字节一个字节
public class CopyFileDemo {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		FileInputStream fis = new FileInputStream("a.txt");
		// 封装目的地
		FileOutputStream fos = new FileOutputStream("b.txt");

		int by = 0;
		while ((by = fis.read()) != -1) {
			fos.write(by);
		}

		// 释放资源(先关谁都行)
		fos.close();
		fis.close();
	}
}
//字节数组
public class CopyFileDemo {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		FileInputStream fis = new FileInputStream("c:\\a.txt");
		FileOutputStream fos = new FileOutputStream("d:\\b.txt");

		// 复制数据
		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = fis.read(bys)) != -1) {
			fos.write(bys, 0, len);
		}

		// 释放资源
		fos.close();
		fis.close();
	}
}

缓冲区类

通过定义数组的方式确实比以前一次读取一个字节的方式快很多,所以,看来有一个缓冲区还是非常好的。

既然是这样的话,那么,java开始在设计的时候,它也考虑到了这个问题,就专门提供了带缓冲区的字节类。

这种类被称为:缓冲区类(高效类)

写数据:BufferedOutputStream

读数据:BufferedInputStream

构造方法可以指定缓冲区的大小,但是我们一般用不上,因为默认缓冲区大小就足够了。

为什么不传递一个具体的文件或者文件路径,而是传递一个OutputStream对象呢?

原因很简单,字节缓冲区流仅仅提供缓冲区,为高效而设计的。但是真正的读写操作还得靠基本的流对象实现。

public class BufferedOutputStreamDemo {
	public static void main(String[] args) throws IOException {
		// 简单写法
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream("bos.txt"));
		// 写数据
		bos.write("hello".getBytes());

		// 释放资源
		bos.close();
	}
}

public class BufferedInputStreamDemo {
	public static void main(String[] args) throws IOException {
		// BufferedInputStream(InputStream in)
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
				"bos.txt"));

		// 读取数据
		// int by = 0;
		// while ((by = bis.read()) != -1) {
		// System.out.print((char) by);
		// }
		// System.out.println("---------");

		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = bis.read(bys)) != -1) {
			System.out.print(new String(bys, 0, len));
		}

		// 释放资源
		bis.close();
	}
}
 

字符流

简介

  • 字节流操作中文数据不是特别的方便,所以就出现了转换流。
    转换流的作用就是把字节流转换字符流来使用。
  • 转换流其实是一个字符流
    字符流 = 字节流 + 编码表
  • 编码表
    就是由字符和对应的数值组成的一张表
    常见的编码表
    ASCII
    ISO-8859-1
    GB2312
    GBK
    GB18030
    UTF-8
    字符串中的编码问题
    编码
    String – byte[]
    解码
    byte[] – String
//之前使用字节流可能会出现的问题
public class FileTnputStreamDemo {
    public static void main(String[] args) throws IOException {
        // 创建字节输入流对象
        FileInputStream fis = new FileInputStream("a.txt");

         //读取数据,此处不能打印出中文来,因为中文占两个字节,会出现乱码
         int by = 0;
         while ((by = fis.read()) != -1) {
         System.out.print((char) by);
         }

//        byte[] bys = new byte[1024];
//        int len = 0;
//        while ((len = fis.read(bys)) != -1) {
//            System.out.print(new String(bys, 0, len));
//        }

        // 释放资源
        fis.close();
    }
}
分类
	Reader
		|--InputStreamReader
			|--FileReader
		|--BufferedReader
	Writer
		|--OutputStreamWriter
			|--FileWriter
		|--BufferedWriter

编码问题

编码解码的格式要一致,我们才能看懂

  • 编码:把看得懂的变成看不懂的

    String – byte[]

  • 解码:把看不懂的变成看得懂的

    byte[] – String

方法
  • String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组
  • byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组

输出流

构造方法
  • OutputStreamWriter(OutputStream out):根据默认编码把字节流的数据转换为字符流
  • OutputStreamWriter(OutputStream out,String charsetName):根据指定编码把字节流数据转换为字符流
public class OutputStreamWriterDemo {
	public static void main(String[] args) throws IOException {
		// 创建对象
		// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
		// "osw.txt")); // 默认GBK
		// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
		// "osw.txt"), "GBK"); // 指定GBK
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
				"osw.txt"), "UTF-8"); // 指定UTF-8
		// 写数据
		osw.write("中国");

		// 释放资源
		osw.close();
	}
}

常用方法
  • public void write(int c):写一个字符
  • public void write(char[] cbuf):写一个字符数组
  • public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
  • public void write(String str):写一个字符串
  • public void write(String str,int off,int len):写一个字符串的一部分

close()关闭流对象,但是先刷新一次缓冲区。关闭之后,流对象不可以继续再使用了。

flush()仅仅刷新缓冲区,刷新之后,流对象还可以继续使用。

public class OutputStreamWriterDemo {
	public static void main(String[] args) throws IOException {
		// 创建对象
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
				"osw2.txt"));

		// 写数据
		// public void write(int c):写一个字符
		// osw.write('a');
		// osw.write(97);
		// 为什么数据没有进去呢?
		// 原因是:字符 = 2字节
		// 文件中数据存储的基本单位是字节。
		// void flush()

		// public void write(char[] cbuf):写一个字符数组
		// char[] chs = {'a','b','c','d','e'};
		// osw.write(chs);

		// public void write(char[] cbuf,int off,int len):写一个字符数组的一部分
		// osw.write(chs,1,3);

		// public void write(String str):写一个字符串
		// osw.write("我爱林青霞");

		// public void write(String str,int off,int len):写一个字符串的一部分
		osw.write("我爱林青霞", 2, 3);

		// 刷新缓冲区
		osw.flush();
		// osw.write("我爱林青霞", 2, 3);

		// 释放资源
		osw.close();
		// java.io.IOException: Stream closed
		// osw.write("我爱林青霞", 2, 3);
	}
}

输入流

构造方法
  • InputStreamReader(InputStream is):用默认的编码读取数据
  • InputStreamReader(InputStream is,String charsetName):用指定的编码读取数据
public class InputStreamReaderDemo {
	public static void main(String[] args) throws IOException {
		// 创建对象
		// InputStreamReader isr = new InputStreamReader(new FileInputStream(
		// "osw.txt"));

		// InputStreamReader isr = new InputStreamReader(new FileInputStream(
		// "osw.txt"), "GBK");

		InputStreamReader isr = new InputStreamReader(new FileInputStream(
				"osw.txt"), "UTF-8");

		// 读取数据
		// 一次读取一个字符
		int ch = 0;
		while ((ch = isr.read()) != -1) {
			System.out.print((char) ch);
		}

		// 释放资源
		isr.close();
	}
}
常用方法
  • int read():一次读取一个字符
  • int read(char[] chs):一次读取一个字符数组
public class InputStreamReaderDemo {
	public static void main(String[] args) throws IOException {
		// 创建对象
		InputStreamReader isr = new InputStreamReader(new FileInputStream(
				"StringDemo.java"));

		// 一次读取一个字符
		// int ch = 0;
		// while ((ch = isr.read()) != -1) {
		// System.out.print((char) ch);
		// }

		// 一次读取一个字符数组
		char[] chs = new char[1024];
		int len = 0;
		while ((len = isr.read(chs)) != -1) {
			System.out.print(new String(chs, 0, len));
		}

		// 释放资源
		isr.close();
	}
}

缓冲区类

字符流为了高效读写,也提供了对应的字符缓冲流。

BufferedWriter:字符缓冲输出流

BufferedReader:字符缓冲输入流

BufferedWriter:字符缓冲输出流
  • 将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
  • 可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。
public class BufferedWriterDemo {
	public static void main(String[] args) throws IOException {
		// BufferedWriter(Writer out)
		// BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
		// new FileOutputStream("bw.txt")));

		BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));

		bw.write("hello");
		bw.write("world");
		bw.write("java");
		bw.flush();

		bw.close();
	}
}
BufferedReader:字符缓冲输入流

BufferedReader(Reader in)

public class BufferedReaderDemo {
	public static void main(String[] args) throws IOException {
		// 创建字符缓冲输入流对象
		BufferedReader br = new BufferedReader(new FileReader("bw.txt"));

		// 方式1
		// int ch = 0;
		// while ((ch = br.read()) != -1) {
		// System.out.print((char) ch);
		// }

		// 方式2
		char[] chs = new char[1024];
		int len = 0;
		while ((len = br.read(chs)) != -1) {
			System.out.print(new String(chs, 0, len));
		}

		// 释放资源
		br.close();
	}
}
特殊用法

BufferedWriter:

​ public void newLine():根据系统来决定换行符

BufferedReader:

​ public String readLine():一次读取一行数据

​ 包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null

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

	private static void read() throws IOException {
		// 创建字符缓冲输入流对象
		BufferedReader br = new BufferedReader(new FileReader("bw2.txt"));

		// public String readLine():一次读取一行数据
		// String line = br.readLine();
		// System.out.println(line);
		// line = br.readLine();
		// System.out.println(line);

		// 最终版代码
		String line = null;
		while ((line = br.readLine()) != null) {
			System.out.println(line);
		}
		
		//释放资源
		br.close();
	}

	private static void write() throws IOException {
		// 创建字符缓冲输出流对象
		BufferedWriter bw = new BufferedWriter(new FileWriter("bw2.txt"));
		for (int x = 0; x < 10; x++) {
			bw.write("hello" + x);
			// bw.write("\r\n");
			bw.newLine();
			bw.flush();
		}
		bw.close();
	}

}

复制文件

采用字符转换流

数据源:

a.txt – 读取数据 – 字符转换流 – InputStreamReader

目的地:

b.txt – 写出数据 – 字符转换流 – OutputStreamWriter

public class CopyFileDemo {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		InputStreamReader isr = new InputStreamReader(new FileInputStream(
				"a.txt"));
		// 封装目的地
		OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
				"b.txt"));

		// 读写数据
		// 方式1
		// int ch = 0;
		// while ((ch = isr.read()) != -1) {
		// osw.write(ch);
		// }

		// 方式2
		char[] chs = new char[1024];
		int len = 0;
		while ((len = isr.read(chs)) != -1) {
			osw.write(chs, 0, len);
			// osw.flush();
		}

		// 释放资源
		osw.close();
		isr.close();
	}
}
采用封装类FileReader,FileWriter

由于我们常见的操作都是使用本地默认编码,所以,不用指定编码。

而转换流的名称有点长,所以,Java就提供了其子类供我们使用。

OutputStreamWriter = FileOutputStream + 编码表(GBK)

FileWriter = FileOutputStream + 编码表(GBK)

数据源:

a.txt – 读取数据 – 字符转换流 – InputStreamReader – FileReader

目的地:

a.txt – 写出数据 – 字符转换流 – OutputStreamWriter – FileWriter

  1. 第一种和上面一样
  2. 第二种是已经封装好的
public class CopyFileDemo3 {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		FileReader fr = new FileReader("c:\\a.txt");
		// 封装目的地
		FileWriter fw = new FileWriter("d:\\b.txt");

		// 读写数据
		// int ch = 0;
		int ch;
		while ((ch = fr.read()) != -1) {
			fw.write(ch);
		}
		
		//释放资源
		fw.close();
		fr.close();
	}
}
采用缓冲区

数据源:

​ a.txt – 读取数据 – 字符转换流 – InputStreamReader – FileReader – BufferedReader

目的地:

​ b.txt – 写出数据 – 字符转换流 – OutputStreamWriter – FileWriter – BufferedWriter

public class CopyFileDemo {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		BufferedReader br = new BufferedReader(new FileReader("a.txt"));
		// 封装目的地
		BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

		// 两种方式其中的一种一次读写一个字符数组
		char[] chs = new char[1024];
		int len = 0;
		while ((len = br.read(chs)) != -1) {
			bw.write(chs, 0, len);
			bw.flush();
		}

		// 释放资源
		bw.close();
		br.close();
	}
}
public class CopyFileDemo {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		BufferedReader br = new BufferedReader(new FileReader("a.txt"));
		// 封装目的地
		BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

		// 两种方式其中的一种一次读写一个字符数组
		char[] chs = new char[1024];
		int len = 0;
		while ((len = br.read(chs)) != -1) {
			bw.write(chs, 0, len);
			bw.flush();
		}

		// 释放资源
		bw.close();
		br.close();
	}
}

数据操作流

可以操作基本类型的数据

  • 数据输入流:DataInputStream

    DataInputStream(InputStream in)

  • 数据输出流:DataOutputStream

    DataOutputStream(OutputStream out)

public class DataStreamDemo {
	public static void main(String[] args) throws IOException {
		// 写
		// write();

		// 读
		read();
	}

	private static void read() throws IOException {
		// DataInputStream(InputStream in)
		// 创建数据输入流对象
		DataInputStream dis = new DataInputStream(
				new FileInputStream("dos.txt"));

		// 读数据
		byte b = dis.readByte();
		short s = dis.readShort();
		int i = dis.readInt();
		long l = dis.readLong();
		float f = dis.readFloat();
		double d = dis.readDouble();
		char c = dis.readChar();
		boolean bb = dis.readBoolean();

		// 释放资源
		dis.close();

		System.out.println(b);
		System.out.println(s);
		System.out.println(i);
		System.out.println(l);
		System.out.println(f);
		System.out.println(d);
		System.out.println(c);
		System.out.println(bb);
	}

	private static void write() throws IOException {
		// DataOutputStream(OutputStream out)
		// 创建数据输出流对象
		DataOutputStream dos = new DataOutputStream(new FileOutputStream(
				"dos.txt"));

		// 写数据了
		dos.writeByte(10);
		dos.writeShort(100);
		dos.writeInt(1000);
		dos.writeLong(10000);
		dos.writeFloat(12.34F);
		dos.writeDouble(12.56);
		dos.writeChar('a');
		dos.writeBoolean(true);

		// 释放资源
		dos.close();
	}
}

内存操作流

有些时候我们操作完毕后,未必需要产生一个文件,就可以使用内存操作流。

  • 字节数组:

    ​ ByteArrayInputStream

    ​ ByteArrayOutputStream

  • 字符数组:

    ​ CharArrayReader

    ​ CharArrayWriter

  • 字符串:

    ​ StringReader

    ​ StringWriter

    public class ByteArrayStreamDemo {
    	public static void main(String[] args) throws IOException {
    		// 写数据
    		// ByteArrayOutputStream()
    		ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
    		// 写数据
    		for (int x = 0; x < 10; x++) {
    			baos.write(("hello" + x).getBytes());
    		}
    
    		// 释放资源
    		// 通过查看源码我们知道这里什么都没做,所以根本需要close()
    		// baos.close();
    
    		// public byte[] toByteArray()
    		byte[] bys = baos.toByteArray();
    
    		// 读数据
    		// ByteArrayInputStream(byte[] buf)
    		ByteArrayInputStream bais = new ByteArrayInputStream(bys);
    
    		int by = 0;
    		while ((by = bais.read()) != -1) {
    			System.out.print((char) by);
    		}
    
    		// bais.close();
    	}
    }
    

    打印流

    只有写数据的,没有读取数据。只能操作目的地,不能操作数据源。

    可以操作任意类型的数据。

    如果启动了自动刷新,能够自动刷新。

    该流是可以直接操作文本文件的。

public class PrintWriterDemo {
	public static void main(String[] args) throws IOException {
		// 作为Writer的子类使用
		PrintWriter pw = new PrintWriter("pw.txt");

		pw.write("hello");
		pw.write("world");
		pw.write("java");
		
		pw.close();
	}
}

自动刷新

PrintWriter pw = new PrintWriter(new FileWriter(“pw2.txt”), true);

还是应该调用println()的方法才可以

  • 这个时候不仅仅自动刷新了,还实现了数据的换行。

    println()

    其实等价于于:

    bw.write();

    bw.newLine();

    bw.flush();

public class PrintWriterDemo2 {
	public static void main(String[] args) throws IOException {
		// 创建打印流对象
		// PrintWriter pw = new PrintWriter("pw2.txt");
		PrintWriter pw = new PrintWriter(new FileWriter("pw2.txt"), true);

		// write()是搞不定的,怎么办呢?
		// 我们就应该看看它的新方法
		// pw.print(true);
		// pw.print(100);
		// pw.print("hello");

		pw.println("hello");
		pw.println(true);
		pw.println(100);

		pw.close();
	}
}

标准输入输出流

System类中的两个成员变量

  • public static final InputStream in “标准”输入流。
  • public static final PrintStream out “标准”输出流。

使用方式

InputStream is = System.in;

PrintStream ps = System.out;

随机访问流

RandomAccessFile类不属于流,是Object类的子类。

但它融合了InputStream和OutputStream的功能。

支持对文件的随机访问读取和写入。

public RandomAccessFile(String name,String mode):第一个参数是文件路径,第二个参数是操作文件的模式。

  •  模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据 
    
  •  可以按照文件指针的位置写数据和读数据,获取和改变文件指针的位置
    

合并流

把多个输入流的数据写到一个输出流中。

构造方法

  • SequenceInputStream(InputStream s1, InputStream s2)
  • SequenceInputStream(Enumeration<? extends InputStream> e)
public class SequenceInputStreamDemo2 {
	public static void main(String[] args) throws IOException {
		// 需求:把下面的三个文件的内容复制到Copy.java中
		// ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java

		// SequenceInputStream(Enumeration e)
		// 通过简单的回顾我们知道了Enumeration是Vector中的一个方法的返回值类型。
		// Enumeration<E> elements()
		Vector<InputStream> v = new Vector<InputStream>();
		InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
		InputStream s2 = new FileInputStream("CopyFileDemo.java");
		InputStream s3 = new FileInputStream("DataStreamDemo.java");
		v.add(s1);
		v.add(s2);
		v.add(s3);
		Enumeration<InputStream> en = v.elements();
		SequenceInputStream sis = new SequenceInputStream(en);
		BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream("Copy.java"));

		// 如何写读写呢,其实很简单,你就按照以前怎么读写,现在还是怎么读写
		byte[] bys = new byte[1024];
		int len = 0;
		while ((len = sis.read(bys)) != -1) {
			bos.write(bys, 0, len);
		}

		bos.close();
		sis.close();
	}
}

序列化流

序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 – 流数据(ObjectOutputStream)

反序列化流:把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 – 对象(ObjectInputStream)

public class ObjectStreamDemo {
	public static void main(String[] args) throws IOException,
			ClassNotFoundException {
		// 由于我们要对对象进行序列化,所以我们先自定义一个类
		// 序列化数据其实就是把对象写到文本文件
		// write();

		read();
	}

	private static void read() throws IOException, ClassNotFoundException {
		// 创建反序列化对象
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(
				"oos.txt"));

		// 还原对象
		Object obj = ois.readObject();

		// 释放资源
		ois.close();

		// 输出对象
		System.out.println(obj);
	}

	private static void write() throws IOException {
		// 创建序列化流对象
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
				"oos.txt"));

		// 创建对象
		Person p = new Person("林青霞", 27);

		// public final void writeObject(Object obj)
		oos.writeObject(p);

		// 释放资源
		oos.close();
	}
}




public class Person implements Serializable {
	private static final long serialVersionUID = -2071565876962058344L;

	private String name;

	// private int age;

	private transient int age;

	// int age;

	public Person() {
		super();
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
}

注意

类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。

我们在实际开发中,可能还需要使用以前写过的数据,不能重新写入。原因是因为它们的id值不匹配。每次修改java文件的内容的时候,class文件的id值都会发生改变。所以我们自动生成一个uid就可以了

使用transient关键字声明不需要序列化的成员变量

Properties

Properties:属性集合类。是一个可以和IO流相结合使用的集合类。

  • Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
  • 是Hashtable的子类,说明是一个Map集合。
特有功能

public Object setProperty(String key,String value) 添加元素
public String getProperty(String key) 获取元素
public Set stringPropertyNames() 获取所有键的集合

public class PropertiesDemo2 {
	public static void main(String[] args) {
		// 创建集合对象
		Properties prop = new Properties();

		// 添加元素
		prop.setProperty("张三", "30");
		prop.setProperty("李四", "40");
		prop.setProperty("王五", "50");

		// public Set<String> stringPropertyNames():获取所有的键的集合
		Set<String> set = prop.stringPropertyNames();
		for (String key : set) {
			String value = prop.getProperty(key);
			System.out.println(key + "---" + value);
		}
	}
}
和IO流结合的方法

把键值对形式的文本文件内容加载到集合中
public void load(Reader reader)
public void load(InputStream inStream)

把集合中的数据存储到文本文件中
public void store(Writer writer,String comments)
public void store(OutputStream out,String comments)

public class PropertiesDemo3 {
	public static void main(String[] args) throws IOException {
		// myLoad();

		myStore();
	}

	private static void myStore() throws IOException {
		// 创建集合对象
		Properties prop = new Properties();

		prop.setProperty("林青霞", "27");
		prop.setProperty("武鑫", "30");
		prop.setProperty("刘晓曲", "18");
		
		//public void store(Writer writer,String comments):把集合中的数据存储到文件
		Writer w = new FileWriter("name.txt");
		prop.store(w, "helloworld");
		w.close();
	}

	private static void myLoad() throws IOException {
		Properties prop = new Properties();

		// public void load(Reader reader):把文件中的数据读取到集合中
		// 注意:这个文件的数据必须是键值对形式
		Reader r = new FileReader("prop.txt");
		prop.load(r);
		r.close();

		System.out.println("prop:" + prop);
	}
}

NIO

nio包在JDK4出现,提供了IO流的操作效率。

Path:路径
Paths:通过静态方法返回一个路径 public static Path get(URI uri)
Files:提供了常见的功能
复制文本文件 public static long copy(Path source,OutputStream out):复制文件
把集合中的数据写到文本文件 public static Path write(Path path,Iterable<? extends CharSequence> lines,Charset cs,OpenOption… options)

public class NIODemo {
	public static void main(String[] args) throws IOException {
		// public static long copy(Path source,OutputStream out)
		// Files.copy(Paths.get("ByteArrayStreamDemo.java"), new
		// FileOutputStream(
		// "Copy.java"));

		ArrayList<String> array = new ArrayList<String>();
		array.add("hello");
		array.add("world");
		array.add("java");
		Files.write(Paths.get("array.txt"), array, Charset.forName("GBK"));
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值