JAVA IO总结

IO

IO,即输入输出流。这里的输入输出是相对于内存的,比如向一个文件中写东西,实为从内存写到硬盘,则为输出,反之为输入。


流的概念和作用

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。 

 

IO流的分类

根据处理数据类型的不同分为:字符流和字节流

根据数据流向不同分为:输入流和输出流

 

字符流和字节流

字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:

读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

 

输入流和输出流

对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。


一、字符流:

1.FileWriter,FileReader:文件输出流 ,文件输入流


FileWriter 的方法:


FileWriter(String fileName):构造函数,指定需要写入的文件名。


write(String s):将字符串s写入流(所关联的文件)中,先保存在缓冲区(是的你没有看错,FileWriter有一个默认缓冲区,其实Writer类及它的子类都有默认的缓冲区,因为Writer类有flush方法),在flush时或close之前立即写入文件中。


write(char[] ch):[不推荐使用]将字符数组写入流中。


write(char[],offset,len):[推荐使用]将字符数组的一部分写入流中。数据最后一次写时可能没有写满数组,效率提高了一点点。


flush():刷新字符流缓冲区,如果该流已保存缓冲区中各种 write() 方法的所有字符,则立即将它们写入预期目标。


append(char c):将字符续写到文件中。


close():关闭此流,但在之前要调用flush方法。



FileReader的方法:


FileReader(String fileName):构造函数,指定需要读取的文件名。


int read():读取一个字符,返回它的Unicode值的十进制表示。


int read(char[] cbuf):[推荐使用]将字符读入数组。


int read(char[] cbuf,int offset,int len):[不推荐使用]将字符读入数组的一部分。不推荐因为不知道最后一次读数据的长度,无法知道数组使用的长度。


close():关闭流。


IO_01_FileWriterDemo.java

import java.io.FileWriter;
import java.io.IOException;
/**
 *文件字符输出流FileWriter 
 */
public class IO_01_FileWriterDemo {
	//将换行符封装成一个全局常量。
	private static final String LINE_SEPERATOR = System.getProperty("line.separator");
	public static void main(String[] args) throws IOException {
	//文件输出流,从内存中写到硬盘上
		FileWriter fw = new FileWriter("a.txt");
	//可以用带两个参数的构造函数,支持续写,则不覆盖原文件内容
	//	FileWriter fw = new FileWriter("a.txt", true);
	//write会覆盖原文件内容,文件不存在则创建。
	//Windows中的换行字符是\r\n
		fw.write("abcdefg"+LINE_SEPERATOR);
	//向文件中加入
		fw.append('f');
		//必须刷新,将缓冲区的数据写入到硬盘
		fw.flush();
		//close前会自动flush一次该流的缓冲。
	}
}</span>
IO_02_FileReaderDemo.java
import java.io.FileReader;
import java.io.IOException;

public class IO_02_FileReaderDemo {
	public static void main(String[] args) throws IOException {
		
		//第二种方法read(char[])
		FileReader fr = new FileReader("a.txt");
		//使用read(char[])方法读取字符输入流中的数据,返回读取的字符个数,如果读完了则返回-1
		char[] arr= new char[1024];
		int len = fr.read(arr);
		//通过String(char[],offset,count)得到读取的字符串。
		System.out.println(new String(arr,0,len));
		fr.close();
		
		/*
		//第一种方法read()
		FileReader fr = new FileReader("a.txt");
		int num = 0;//输入输出流信息传递的桥梁
		while((num=fr.read()) != -1){
			System.out.println(num);
		}
		*/
	}
}</span>

IO_03_FileReader_FileWriter_Practice.java

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
 * 使用FileReader,FileWriter将a.txt中的内容写入b.txt中 
 */
public class IO_03_FileReader_FileWriter_Practice {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("a.txt");
		FileWriter fw = new FileWriter("b.txt",true);
//创建字符数组作为输入流和输出流信息传递的桥梁,之前的字符ch,之后的BufferedReader,BufferedWrier缓冲区也是这个作用
		char[] arr = new char[1024];
		int len = 0;
		while((len = fr.read(arr)) != -1){
			fw.write(arr,0,len);
		}
		fr.close();
		fw.close();
	}
}</span>

2.BufferedWriter,BufferedReader输出流缓冲区,输入流缓冲区(不是必要的,可以提高效率)


BufferedWriter将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

缓冲区是装饰设计模式的体现:把原来的对象作为参数传构造时进去,对对象的功能进行增强.

装饰设计模式和继承的异同:

都能进行功能拓展,装饰模式比继承要灵活。避免了继承体系臃肿。降低了类于类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常是都属于一个体系中的。在JAVA IO中用了很多增强 如:FileRead中read()方法 只是一个一个字节去读,为了读得更快在BufferedReader就增强了read()方法而产生了reandLine()一行一行的去读.

可以指定缓冲区的大小,或者接受默认的大小。在大多数情况下,默认值就足够大了。

该类提供了 newLine() 方法,它使用平台自己的行分隔符概念,此概念由系统属性line.separator 定义。并非所有平台都使用新行符 ('\n') 来终止各行。因此调用此方法来终止每个输出行要优于直接写入新行符。

通常 Writer 将其输出立即发送到底层字符或字节流。除非要求提示输出,否则建议用 BufferedWriter 包装所有其 write() 操作可能开销很高的 Writer(如 FileWriters 和 OutputStreamWriters)。例如,

 PrintWriter out
   = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
 

将缓冲 PrintWriter 对文件的输出。如果没有缓冲,则每次调用 print() 方法会导致将字符转换为字节,然后立即写入到文件,而这是极其低效的。


BufferedWriter的方法


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


close():关闭此流,但要刷新它


flush():刷新缓冲区


newLine():写入一个换行符。是BufferedWriter独有的方法。


write(String s):写入字符串


write(String s,int off,int len):写入字符串的一部分


write(char[] cbuf):写入字符数组


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


BufferedReader的方法:


BufferedReader(Reader in):创建一个使用默认大小输出缓冲区的缓冲字符输入


int read():读取一个字符


int read(char[] cbuf,int off,int len):读取字符数组的一部分


String readLine():读取一行(以换行符为标志)


IO_04_BufferedWriter.java

import java.io.BufferedWriter;
import java.io.FileWriter;

public class IO_04_BufferedWriter {

	public static void main(String[] args) {
		try {
			FileWriter fw = new FileWriter("a.txt");
			BufferedWriter bufw = new BufferedWriter(fw);
			bufw.write("aaa");
			//最好写一次刷一次
			bufw.flush();
			//写入换行符
			bufw.newLine();
			bufw.flush();
			bufw.write("bbb");
			bufw.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
</span>
IO_05_BufferedReader_readLine.java

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class IO_05_BufferedReader_readLine {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("a.txt");
		BufferedReader br = new BufferedReader(fr);
		String line = null;
		while((line = br.readLine()) != null){
			System.out.println(line);
		}
	}
}
</span>
IO_06_BufferedWriter_BufferedReader_Practice.java
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class IO_06_BufferedWriter_BufferedReader_Practice {

	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("a.txt");
		BufferedReader bufr = new BufferedReader(fr);
		FileWriter fw = new FileWriter("b.txt");
		BufferedWriter bufw = new BufferedWriter(fw);
		String line = null;
		while((line = bufr.readLine()) != null){
			bufw.write(line);
			//想要和a.txt一样则需要每行写入一个换行符
			bufw.newLine();
			bufw.flush();
		}
		bufw.close();
		bufr.close();
	}

}

LineNumberReader可以输出行号,继承自BufferedReader,有两个方法setLineNumber(int i), int getLineNumber();可以设置和获取当前行号.输出带有行号的内容.例如

IO_07_LineNumberReader.java

import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class IO_07_LineNumberReader {

	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("a.txt");
		LineNumberReader lnr = new LineNumberReader(fr);
		String line = null;
		//设置开始的行号
		lnr.setLineNumber(1000);
		while((line = lnr.readLine()) != null){
			System.out.println(lnr.getLineNumber()+":"+line);
		}
		lnr.close();
	}

}
控制台输出:
1001:public class IO_05_BufferedReader_readLine {
1002:	public static void main(String[] args) throws IOException {
1003:		FileReader fr = new FileReader("a.txt");
1004:		BufferedReader br = new BufferedReader(fr);
1005:		String line = null;
1006:		while((line = br.readLine()) != null){
1007:			System.out.println(line);
1008:		}
1009:	}
1010:}

二,字节流

 字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组

FileOutputStream

FileOutputStream的方法

write(byte[]):写入字节数组

write(byte[],int off,int len):写入字节数组的一部分

write(int b):写入Unicode的十进制表示的字符

FileInputStream

FileInputStream的方法

read(int i):读取该字符的Unicode的十进制表示

read(byte[]):读取该字节数组

read(byte[] int off,int len):读取字节数组的一部分

int available():返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数

IO_08_FileOutputStream.java

import java.io.FileOutputStream;
import java.io.IOException;

public class IO_08_FileOutputStream {

	public static void main(String[] args) throws IOException {
		FileOutputStream fos = new FileOutputStream("a.txt");
		fos.write("hahaha".getBytes());
		//字节流直接读取字节,不使用缓冲机制,不需要刷新
		fos.close();
	}

}
IO_09_FileInputStream.java
import java.io.FileInputStream;
import java.io.IOException;

public class IO_09_FileInputStream {

	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("a.txt");
		/*
		//方法一:
		int i = 0;
		while((i = fis.read())!=-1){
			System.out.println((char)i);
		}*/
		
		/*//方法二:available方法返回文件的字节数,可以创建字节数组一次接收,文件较大时慎用.
		byte[] b = new byte[fis.available()];
		fis.read(b);
		System.out.println(new String(b));*/
		
		
		//方法三:建议使用
		byte[] b = new byte[1024];
		int len = 0;
		while((len=fis.read(b))!=-1){
			System.out.println(new String(b,0,len));
		}
	}

}
BufferedOutputStream

BufferedOutputStream的方法:略,类似于BufferedWriter.只是操作的是字节数组


BufferedInputStream

BufferedInputStream的方法:略.类似于BufferedReader.只是操作的是字节数组



IO_10_FileOutputStream_FileInputStream_Practice.java

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class IO_10_FileOutputStream_FileInputStream_Practice {

	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("1.jpg");
		FileOutputStream fos = new FileOutputStream("2.jpg");
		byte[] b = new byte[1024];
		int len = 0;
		while((len=fis.read(b))!=-1){
			fos.write(b,0,len);
		}
		/*//一个一个读取,不要使用这种低效率的方式
		int ch = 0;
		while((ch=fis.read())!=-1){
			fos.write(ch);
		}*/
		fis.close();
		fos.close();
	}

}



IO_11_BufferedOutputStream_BufferedInputStream_Practice.java

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class IO_11_BufferedOutputStream_BufferedInputStream_Practice {

	public static void main(String[] args) throws IOException {
		FileInputStream fis = new FileInputStream("1.jpg");
		FileOutputStream fos = new FileOutputStream("3.jpg");
		BufferedInputStream bufis = new BufferedInputStream(fis);
		BufferedOutputStream bufos = new BufferedOutputStream(fos);
		byte[] b = new byte[1024];
		int len = 0;
		while((len=bufis.read(b))!=-1){
			bufos.write(b,0,len);
			//使用缓冲区write时记得刷新哦~
			bufos.flush();
		}
		bufis.close();
		bufos.close();
	}

}

练习键盘输入:输入一个小写字母组成的字符串,换行后显示大写形式,如果输入over停止读入

使用这种方式虽然可以将InputStream读取的字节流转换成字符串但是太麻烦,可以使用之后介绍的InputStreamReader直接转换为字符流.键盘录入通常使用InputStreamReader

IO_13_readfromKeyboard.java

import java.io.IOException;
import java.io.InputStream;

public class IO_13_readfromKeyboard {

	public static void main(String[] args) throws IOException {
		InputStream in = System.in;
		StringBuffer sb = new StringBuffer();
		int t = 0;
		while ((t = in.read()) != -1) {
			if ((char) t == '\r') {
				continue;
			}
			if ((char) t == '\n') {
				String temp = sb.toString();
				System.out.println(temp.toUpperCase());
				sb.delete(0, sb.length());
				if (temp.equals("over")) {
					break;
				}
			} else {
				sb.append((char) t);
			}
		}
	}

}
字节流转换为字符流的桥梁-----InputStreamReader的作用:从键盘读取时将其转为字符流,以便使用字符流缓冲区操作

IO_14_InputStreamReader.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class IO_14_InputStreamReader {

	public static void main(String[] args) throws IOException {
		//字节流转换为字符流,使用InputStreamReader
		//获取键盘录入,记住下面这句话!
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		String line=null;
		while(!"over".equals(line=bufr.readLine())){
			System.out.println(line);
		}
	}
}
IO_15_OutputStreamWriter.java

字符流转换为字节流------作用:使用BufferedWriter输出到控制台上

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class IO_15_OutputStreamWriter {
	public static void main(String[] args) throws IOException {
//		向控制台输出.字符流变字节流,用OutputStreamWriter,<span style="font-family: Arial, Helvetica, sans-serif;">记住下面这句话!</span>
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
		bufw.write("aaaa哈哈\r\nbbb".toCharArray());
		bufw.newLine();
		bufw.flush();
	}
}

IO_16_InputStramReader_OutputStreamWriter_Practice.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class IO_16_InputStramReader_OutputStreamWriter_Practice {

	public static void main(String[] args) throws IOException {
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
		String line=null;
		while(!"over".equals(line=bufr.readLine())){
			bufw.write(line.toCharArray());
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		bufw.close();
	}

}

小总结:

读取字节流--InputStream--加缓冲区--BufferedInputStream

读取字符流--Reader--加缓冲区--BufferedReader

写入字节流--OutputStream--加缓冲区--BufferedOutputStream
写入字符流--Writer--加缓冲区--BufferedWriter

从键盘读:

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
写入控制台:

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

练习:选择合适的流对象

练习1:将a.txt复制到b.txt中

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));

练习2:将a.txt打印到控制台上

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

练习3:将键盘输入的数据写入a.txt中

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

BufferedWriter bufw = new BufferedWriter(new FileWriter("a.txt"));

练习4:将键盘输入的数据打印到控制台上

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

练习5:将a.txt中的数据按照指定编码表uft-8写入到b.txt中--使用转换流的方法.

IO_17_TransStream_Charset.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class IO_17_TransStream_Charset {

	public static void main(String[] args) throws IOException {
		//5.将a.txt中的数据按照指定编码表uft-8写入到b.txt中
		//FileReader,FileWriter使用的是系统默认的编码表(简体中文则为GBK),不能使用此类
		//转换流有指定编码表的方法,转换流的参数是字节流对象,则为FileOutputStream,FileInputStream
		FileInputStream fis = new FileInputStream("a.txt");
		FileOutputStream fos = new FileOutputStream("b.txt");
		BufferedReader bufr = new BufferedReader(new InputStreamReader(fis,"utf-8"));
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(fos,"utf-8"));
		String line = null;
		while((line=bufr.readLine())!=null){
			bufw.write(line);
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		bufw.close();
	}

}

上面的对象只能操作数据,如何操作文件呢?使用File对象

1.File构造函数和静态属性.

IO_18_File_Separator.java

import java.io.File;

public class IO_18_File_Separator {

	public static void main(String[] args) {
		//构造函数1:建立一个名为a.txt的File对象,该File对象可以表示一个文件或文件夹
		File f1 = new File("a.txt");
		//构造函数2:建立一个名为c:\\a.txt的<span style="font-family: Arial, Helvetica, sans-serif;">File</span><span style="font-family: Arial, Helvetica, sans-serif;">对象</span>
		File f2 = new File("c:\\");
		File f3 = new File(f2, "b.txt");
		//构造函数:建立一个名为c:\\a.txt 的File对象
		File f4 = new File("c:"+File.separator, "c.txt");
		System.out.println(f2);
		System.out.println(f3);
		System.out.println(f4);
		
		//文件分隔符(Unix中是/,Windows中是\),路径分隔符(Unix中是:,Windows中是;)
		System.out.println(File.separator+File.pathSeparator);
	}

}
2.File对象的方法之获取

import java.io.File;
import java.text.DateFormat;
import java.util.Date;

public class IO_19_File_Methods {

	public static void main(String[] args) {
		File f = new File("a.txt");
		//获取名称
		System.out.println(f.getName());
		//获取绝对路径
		System.out.println(f.getAbsolutePath());
		//获取相对路径,即当前文件夹
		System.out.println(f.getPath());
		//获取所占总空间,虚拟机可用空间,可用空间
		System.out.println(f.getTotalSpace()+","+f.getUsableSpace()+","+f.getFreeSpace());
		//获取长度
		System.out.println(f.length());
		//获取上次修改时间
		Date date = new Date(f.lastModified());
		DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG,DateFormat.LONG);
		System.out.println(df.format(date));
	}

}
3.File对象的方法之创建和删除

IO_20_File_Methods2.java

import java.io.File;
import java.io.IOException;

public class IO_20_File_Methods2 {

	public static void main(String[] args) throws IOException {
		//1.文件的创建和删除
		File f = new File("a.txt");
		//createNewFile()创建一个文件,成功返回true,已存在返回false
		System.out.println(f.createNewFile());
		//detele()删除文件
		System.out.println(f.delete());
		
		//2.一个目录(文件夹)的创建和删除
		File dir = new File("aaa");
		//mkdir()创建目录(文件夹),成功返回true,已存在返回false
		System.out.println(dir.mkdir());
		//delete()删除一个空目录(文件夹),不走回收站,如果文件夹不为空,则无法删除.
		System.out.println(dir.delete());
		
		//2.多级目录的创建和删除
		//mkdirs()创建多级目录
		File dir2 = new File("aa/bb/cc/dd/de");
		//创建多级目录
		System.out.println(dir2.mkdirs());
		//删除目录的最后一个文件夹
		System.out.println(dir2.delete());
	}

}
4.File对象的方法之判断,重命名,ListRoots,

IO_21_File_Methods3.java

import java.io.File;

public class IO_21_File_Methods3 {

	public static void main(String[] args) {
		//文件File方法之判断
		File f = new File("a.txt");
		f.mkdir();
		//f.createNewFile();
		//判断文件是否存在,最后先判断是否存在,再判断文件类型是文件还是目录
		System.out.println(f.exists());
		//判断是否是文件
		System.out.println(f.isFile());
		//判断是否是目录
		System.out.println(f.isDirectory());
		
		//重命名
		File f1 = new File("b.txt");
		//在同一个文件夹中则重命名,将b.txt命名为bbb.txt
		System.out.println(f1.renameTo(new File("bbb.txt")));
		//在不同文件夹中则剪切,将b.txt剪切到d:\\bbb.txt
		System.out.println(f1.renameTo(new File("d:\\bbb.txt")));
		
		//listRoots列出可用系统根目录,静态方法
		File[] listRoots = File.listRoots();
		for (File file : listRoots) {
			System.out.println(file);
		}
		
		//list列出该目录下所有文件和文件夹的名称,包括隐藏文件.若访问系统级目录会出异常.目录为空则创建的数组长度为0.
		File f2 = new File("c:\\");//必须是目录,不能是文件
		String[] names = f2.list();
		for (String name : names) {
			System.out.println(name);
		}
	}

}
list方法练习:过滤器

输出d盘下所有扩展名为.txt的文件

IO_22_File_Method_list.java

import java.io.File;
import java.io.FilenameFilter;

public class IO_22_File_Method_list implements FilenameFilter{
	private String suffix;//后缀
	
	public IO_22_File_Method_list(String suffix) {
		super();
		this.suffix = suffix;
	}

	public static void main(String[] args) {
		File f = new File("d:\\");
		//list(FilenameFileter filter)创建接口,实现accept方法,方法中写过滤条件.
		String[] names = f.list(new IO_22_File_Method_list(".txt"));
		for (String name : names) {
			System.out.println(name);
		}
	}

	@Override
	//对文件路径和文件名进行过滤
	public boolean accept(File dir, String name) {
		return name.endsWith(suffix);
	}
}


过滤隐藏文件:使用FileFilter接口

IO_23_File_Method_list2.java

import java.io.File;
import java.io.FileFilter;

public class IO_23_File_Method_list2 implements FileFilter{

	public static void main(String[] args) {
		File f = new File("c:\\");
		File[] files = f.listFiles(new IO_23_File_Method_list2());
		for (File file : files) {
			System.out.println(file);
		}
	}

	@Override
	public boolean accept(File name) {
		return !name.isHidden();
	}

}

Properties对象

IO_24_Properties.java

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.Set;

public class IO_24_Properties {

	public static void main(String[] args) throws IOException {
		/*
		 Map
		  |--HashTable
		     |--Properties
		 Properties集合:用于操作以键值对形式存在的配置文件.
		 特点:1.该集合中的键和值都是字符类型的
		     2.集合中数据可以保存在流中,从流读取
		*/
		Properties p = new Properties();
		//存储元素
		p.setProperty("jhz", "19920811");
		p.setProperty("ztq", "19920221");
		p.setProperty("ddd", "19920421");
		//修改元素
		p.setProperty("ddd", "19990101");
		//遍历元素->使用stringPropertyNames方法返回key的set集合.
		Set<String> propertyNames = p.stringPropertyNames();
		for (String name : propertyNames) {
			System.out.println(name+p.getProperty(name));
		}
		//list方法,一般用于调试
//		p = System.getProperties();
		p.list(System.out);//将p放入输出流中
		
		//从输出流持久化数据到文件中,第一个参数的是使用的输出流,第二个参数是描述,默认使用ISO-8859-1,描述信息不要写中文
		OutputStream os = new FileOutputStream("info.txt");
		p.store(os, "name,birthday");
		
	}
}
IO_25_Properties2.java

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
/**
 * 读取配置文件中jhz的登录次数,并+1后重新保存进配置文件.
 * @author Administrator
 *
 */
public class IO_25_Properties2 {
	public static void main(String[] args) throws IOException {
		Properties p = new Properties();
		FileInputStream fis = new FileInputStream("info.txt");
		//从输出流中读取属性列表ISO8859-1
		p.load(fis);
		//读取并将登录次数加1
		String property = p.getProperty("jhz");
		int value = Integer.parseInt(property)+1;
		p.setProperty("jhz",value+"");
		FileOutputStream fos = new FileOutputStream("info.txt");
		p.store(fos, "name,Logintimes");
		fis.close();
		fos.close();
	}
}
PrintStream打印流:可以直接操作输入流和文件

提供了多种不同数据的print方法,并可以保持数据的原有形式,不抛异常.

当想保持数据原样写入时使用PrintStream最方便

构造函数

PrintStream(String s);

PrintStream(File f);

PrintStream(OutputStream os);

write(int i):此方法向输出流写入一个字节,要写入的是i的八个低位,24个高位将被忽略. 所以i=97和i=609输出的都是a.

print(各种参数):原样打印


IO_26_PrintStream.java

import java.io.IOException;
import java.io.PrintStream;

public class IO_26_PrintStream {

	public static void main(String[] args) throws IOException {
		PrintStream ps = new PrintStream("a.txt");
		ps.write(609);
		ps.write(97);
		
		ps.print(97);
		ps.print("aaa");
		ps.print(1.256);
		ps.close();
		//打印结果aa97aaa1.256
	}

}

PrintWriter:打印流

构造函数:

PrintWriter(String s):

PrintWriter(File f):

PrintWriter(OutputStream os):

PrintWriter(Writer w):


IO_27_PrintWriter.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class IO_27_PrintWriter {

	public static void main(String[] args) throws IOException {
		//为true则自动刷新,不用调用flush
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter pw = new PrintWriter(System.out,true);
		String line=null;
		while(!"over".equals(line=bufr.readLine())){
			pw.println(line);
		}
		pw.close();
	}

}


SequenceStream序列流.对多个流进行合并

SequenceInputStream:

SequenceInputStream(Enumeration<?>InputStream):

read(byte[] b):


IO_28_SequenceInputStream_Enum.java

import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

public class IO_28_SequenceInputStream_Enum {
/**
 * 将1.txt,2.txt,3.txt中的数据写入4.txt中
 * Vector的elements方法可以得到枚举.
 * @param args
 * @throws IOException
 */
	public static void main(String[] args) throws IOException {
		Vector<FileInputStream> inputStreams = new Vector<FileInputStream>();
		inputStreams.add(new FileInputStream("1.txt"));
		inputStreams.add(new FileInputStream("2.txt"));
		inputStreams.add(new FileInputStream("3.txt"));
		Enumeration<FileInputStream> en = inputStreams.elements();
		//SequenceInputStream参数是枚举类型,通过vector.elements获得.
		SequenceInputStream sis = new SequenceInputStream(en);
		BufferedOutputStream bufw = new BufferedOutputStream(new FileOutputStream("4.txt"));
		byte[] b = new byte[1024];
		int len = 0;
		while((len=sis.read(b))!=-1){
			bufw.write(b, 0, len);
			bufw.flush();
		}
		sis.close();
		bufw.close();
	}

}
IO_29_SequenceInputStream_Enum2.java

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;

public class IO_29_SequenceInputStream_Enum2 {

	public static void main(String[] args) throws IOException {
		/**
		 * Vector效率较低,可以使用ArrayList,使用Collections的Enumeration方法获得该集合(ArrayList)的枚举
		 */
		ArrayList<InputStream> al = new ArrayList<InputStream>();
		al.add(new FileInputStream("1.txt"));
		al.add(new FileInputStream("2.txt"));
		al.add(new FileInputStream("3.txt"));
		Enumeration<InputStream> en = Collections.enumeration(al);
		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream("4.txt");
		int len = 0;
		byte[] b = new byte[1024];
		while((len = sis.read(b))!=-1){
			fos.write(b,0,len);
		}
		sis.close();
		fos.close();
	}

}

应用:文件切割器.输入流一个,输出流在每次循环时指定切割成的文件名即可.

IO_30_FileCutter.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class IO_30_FileCutter {

	public static void main(String[] args) throws IOException {
		//参数为切割的的文件路径
		fileCutter(new File("1.txt"));
	}

	private static void fileCutter(File file) throws IOException {
		//切割的文件file
		FileInputStream fis = new FileInputStream(file);
		//按1M为单位切割.
		byte[] b = new byte[1024];
		//保存在哪个文件夹下,不存在该文件夹则创建
		File dir = new File("c:\\Filecutter");
		if(!dir.exists()){
			dir.mkdir();
		}
		int len=0;
		//计数器,用于按顺序记录切割的每一份,便于之后合并.
		int count = 1;
		FileOutputStream fos = null;
		while((len=fis.read(b))!=-1){
			//使用new File(File parent,String child)构造指定切割到的文件夹,保存在C:\Filecutter下;
			fos = new FileOutputStream(new File(dir,(count++)+".part"));
			fos.write(b,0,len);
		}
		//建立配置文件,以保存切割信息(原文件名,切割份数等),保存在C:\Filecutter下
		Properties p = new Properties();
		fos = new FileOutputStream(new File(dir,(count)+".properties"));
		p.setProperty("fileName", file.getName());
		p.setProperty("fileParts", count-1+"");
		p.store(fos, "file properties info");
		//关闭流
		fis.close();
		fos.close();
	}

}


文件合并--使用SequenceInputStream

IO_31_File_Merge.java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;

public class IO_31_File_Merge implements FilenameFilter{

	private static String suffix;
	

	public IO_31_File_Merge(String suffix) {
		super();
		this.suffix = suffix;
	}

	public static void main(String[] args) throws IOException {
		FileMerge(new File("c:\\Filecutter"));   
	}

	private static void FileMerge(File file) throws IOException {
		String[] list = file.list(new IO_31_File_Merge(".properties"));
		String property = list[0];
		FileInputStream fis = new FileInputStream(file+"\\"+property);
		Properties p = new Properties();
		p.load(fis);
		String fileName = p.getProperty("fileName");
		int fileParts = Integer.parseInt(p.getProperty("fileParts"));
		ArrayList<InputStream> al = new ArrayList<InputStream>();
		for (int i = 1; i <= fileParts; i++) {
			al.add(new FileInputStream(new File(file,i+".part")));
		}
		Enumeration<InputStream> en = Collections.enumeration(al);
		SequenceInputStream sis = new SequenceInputStream(en);
		FileOutputStream fos = new FileOutputStream(new File(file,fileName)); 
		byte[] b = new byte[1024];
		int len = 0;
		while((len=sis.read(b))!=-1){
			fos.write(b,0,len);
		}
		sis.close();
		fos.close();
	}

	@Override
	public boolean accept(File dir, String name) {
		return name.endsWith(suffix);
	}

}
对象的序列化 ObjectOutputStream.writeObject()

对象的反序列化 ObjectInputStream.readObject()

序列化是流功能的拓展,所以接收一个InputStream和OutputStream对象.正如缓冲流和转换流,也需要接收对象,都是其他流结合使用的.

IO_32_serializable.java

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class IO_32_serializable{
	public static void main(String[] args) throws IOException, ClassNotFoundException{
		serialize(new IO_33_bean(1,"lj","haha"));
		oppoSerialize("obj.object");
	}

	private static void oppoSerialize(String file) throws IOException, ClassNotFoundException {
		//对象的反序列化.读取使用ObjectOutputStream已经保存在硬盘上的对象
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
		IO_33_bean person = (IO_33_bean) ois.readObject();
		System.out.println(person.getId());//1
		System.out.println(person.getName());//lj
		System.out.println(person.getPassword());//null
		ois.close();
	}

	private static void serialize(IO_33_bean person) throws IOException {
		//对象的序列化:将对象存储到硬盘上延长它的生命周期.该对象必须先实现Serializable接口
				//使用ObjectOutputStream类的writeObject方法存储. 存储文件的扩展名为.object
				ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
				oos.writeObject(person);
				oos.close();
	}

}


需要序列化的对象对应的类---数据库对象和具有特殊数据的对象可以使用序列化保存.并不是所有对象都可以被序列化,如Socket对象就不行

IO_33_bean.java

import java.io.Serializable;

public class IO_33_bean implements Serializable{
	/**
	 * 序列化强烈建议加入UID,以判断.object文件与类文件是不是同一个.只要id一样,就可以反序列化,
	 * 否则可能出现InvalidClassException异常,该id的访问修饰符ACCESS MODIFIER可以为任意.
	 * 静态属性不在堆中,不能进行序列化.不想被序列化的属性可以用transient标识为瞬态的,则不被存储.
	 */
	
	private static final long serialVersionUID = 1L;
	private int id;
	private String name;
	private transient String password;
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

	public IO_33_bean(int id, String name, String password) {
		super();
		this.id = id;
		this.name = name;
		this.password = password;
	}
	
}
随机访问文件对象RandomAccessFile

IO_34_RandomAccessFile.java

import java.io.IOException;
import java.io.RandomAccessFile;

public class IO_34_RandomAccessFile {
	/*RandomAccessFile
	 * 1.不是既能读,又能写.其实内部封装了字节输入输出流.
	 * 2.内部维护了一个byte数组,并用一个指针,通过seek方法设置指针位置.通过getFilePointer方法获取指针位置.
	 * 3.与流对象存取不同,它可以从任意位置存取,多线程方式有些操作就是用的该类,应用比如视频断点续传.
	 */
	public static void main(String[] args) throws IOException {
		readFile();
		writeFile();
	}

	private static void writeFile() throws IOException {
		RandomAccessFile raf = new RandomAccessFile("random.txt", "rw");
		raf.write("张三".getBytes());//2个中文占4个字节
		raf.writeInt(99);//使用4个字节存储int对象
		System.out.println(raf.getFilePointer());//8
		raf.seek(2*8);//从第16个字节开始写
		raf.write("李刚".getBytes());
		raf.writeInt(100);
		//记事本解析为:张三   c        李刚   d
		//数据c和d没错,因为记事本用GBK解析了
		raf.close();
	}

	private static void readFile() throws IOException {
		RandomAccessFile raf = new RandomAccessFile("random.txt", "rw");
		byte[] b = new byte[8];
		raf.read(b);
		System.out.println(new String(b));//张三   c
		System.out.println(raf.getFilePointer());//8
		raf.seek(16);
		raf.read(b);
		System.out.println(new String(b));//李刚   d
	}

}
管道流--常用于多线程--输出的内容只能有自己获取

IO_35_PipedInputStream_PipedOutputStream.java

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class IO_35_PipedInputStream_PipedOutputStream {
	/**
	 * 管道流,输出流写的数据只能输入流读.需要连接输入流和输出流.使用PipedInputStream的connect方法
	 * 一般使用多线程执行,否则可能造成死锁.
	 */
	public static void main(String[] args) throws IOException {
		PipedOutputStream pos = new PipedOutputStream();
		PipedInputStream pis = new PipedInputStream();
		pis.connect(pos);
		Input input = new Input(pis);
		Output output = new Output(pos);
		Thread t1 = new Thread(input);
		Thread t2 = new Thread(output);
		t1.start();
		t2.start();
	}
}
class Input implements Runnable{
	private PipedInputStream pis;
	
	public Input(PipedInputStream pis) {
		this.pis = pis;
	}

	@Override
	public void run() {
		byte[] b = new byte[1024];
		try {
			int len = pis.read(b);
			System.out.println(new String(b,0,len));//泥濠啊大哥
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}
class Output implements Runnable{
	private PipedOutputStream pos;
	public Output(PipedOutputStream pos) {
		this.pos = pos;
	}
	@Override
	public void run() {
		try {
			pos.write("泥濠啊大哥".getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
}
DataInputStream,DataOutputStream操作基本数据类型,构造函数接收流字节参数

在存取基本数据类型时使用.

IO_36_DataInputStream_DateOutputStream.java

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class IO_36_DataInputStream_DateOutputStream {

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

	private static void write() throws IOException {
		DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
		dos.writeUTF("66666哈哈");
		dos.writeInt(999);
	}

	private static void read() throws IOException {
		DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
		byte[] b = new byte[1024];
		int len = dis.read(b);
		System.out.println(new String(b,0,len));//wirteUTF存储的只有readUTF可以取出来
		dis.close();
	}

}

操作数组的流:源或者目的是[内存]时使用该流.

操作字节数组ByteArrayInputStream,ByteArrayOutputStream

操作字符数组ChaArrayReader,CharArrayWriter,  

操作字符串数组StringReader,StringWriter


IO_37_ByteArrayInputStream_ByteArrayOutputStream.java

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

public class IO_37_ByteArrayInputStream_ByteArrayOutputStream {

	public static void main(String[] args) {
		ByteArrayInputStream bis = new ByteArrayInputStream("哈哈".getBytes());
//ByteOutputStream内部维护了一个数组,缓冲区随输入的写入自动增长,使用toString方法可以将缓冲区里的内容转换为字符串.
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		int i = 0;
		while((i=bis.read())!=-1){
			bos.write(i);
		}
		System.out.println(bos.toString());//哈哈
	}

}










  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值