黑马程序员_IO流

------- android培训java培训、java学习型技术博客、期待与您交流! ----------

IO流

1、其他重要类


System
out:标准输出,默认是控制台。
in:标准输入,默认是控制台
err:标准错误输出流,默认是控制台
setIn:可以改变输入设备
setOut:可以改变输出设备
System类不能实例化。
可以描述系统环境:
getProperties();
setProperty();
setProperties();
getProperty("os.name");
stringPropertiesName();
可以在启动jvm时加载系统信息。

Properties
是Hashtable子类,
该集合中存储的都是字符串。没有泛型定义.
String getProperty(String key)  用指定的键在此属性列表中搜索属性。
void list(PrintStream out) 将属性列表输出到指定的输出流。
void load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。
Object setProperty(String key, String value)  调用 Hashtable 的方法 put。

Runtime类(单例):没有提供构造函数,不可以new对象。
static Runtime getRuntime();获得Runtime对象。
exec();//执行cmd命令
Process类:进程类 Runtime类exec方法返回该类。

Date类:时间操作类
DateFormat类:
SimpleDateFormat类:
日期和时间模式:
y 年
M 月
d 日
h 时
m 分
s 秒
E 星期中的天数 已经本地化了
如:

import java.util.*;
import java.text.*;
class DateDemo 
{
	public static void main(String[] args) 
	{
		Date d = new Date();
		System.out.println(d);//打印的时间看不懂,希望有些格式。

		//将模式封装到SimpleDateformat对象中。
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日E hh:mm:ss");
		
		//调用format方法让模式格式化指定Date对象。

		String time = sdf.format(d);

		System.out.println("time="+time);

		long l = System.currentTimeMillis();

		Date d1 = new Date(l);

		System.out.println("d1:"+d1);


	}
}

Calender类:
获取年:Calender.get(Calender.YEAR);返回int
add(Calender.YEAR,4);
练习:

import java.util.*;

/*
两个练习:
1,获取任意年的二月有多少天。
	思路:根据指定年设置一个时间就是 
	c.set(year,2,1)//某一年的3月1日。
	c.add(Calenar.DAY_OF_MONTH,-1);//3月1日,往前推一天,就是2月最后一天。

2,获取昨天的现在这个时刻。
	c.add(Calenar.DAY_OF_MONTH,-1);
*/
class  CalendarDemo2
{
	public static void main(String[] args) 
	{

		Calendar c = Calendar.getInstance();

		//c.set(2012,2,23);

		c.add(Calendar.DAY_OF_MONTH,-18);
		
		printCalendar(c);
	}

	public static void printCalendar(Calendar c)
	{
		String[] mons = {"一月","二月","三月","四月"
					,"五月","六月","七月","八月"
					,"九月","十月","十一月","十二月"};


		String[] weeks = {
						"","星期日","星期一","星期二","星期三","星期四","星期五","星期六",
							};		
		int index = c.get(Calendar.MONTH);

		int index1 = c.get(Calendar.DAY_OF_WEEK);

		sop(c.get(Calendar.YEAR)+"年");
		//sop((c.get(Calendar.MONTH)+1)+"月");
		sop(mons[index]);
		sop(c.get(Calendar.DAY_OF_MONTH)+"日");
		//sop("星期"+c.get(Calendar.DAY_OF_WEEK));
		sop(weeks[index1]);
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}

Math类:
abs:绝对值
ceil:返回大于指定数据的最小整数
floor:返回小于指定数据的最大整数
round:四舍五入
pow:a^b a的b次方
random:返回伪随机数
Random类:随机类
nextInt();
练习:

/*
练习。给定一个小数。
保留该小数的后两位。

选作。可以考虑,保留时进行四舍五入。

*/
import java.util.*;

class  MathDemo
{
	public static void main(String[] args) 
	{
		
		/*
		Random r = new Random();
		for(int x=0; x<10; x++)
		{
			//int d = (int)(Math.random()*10+1);
			int d = r.nextInt(10)+1;
			sop(d);
		}
		*/
		saveTwo(12.3456,3,true);//12.34
	}

	public static void saveTwo(double d,int scale,boolean isRound)
	{
		
		double base = Math.pow(10,scale);


		double num = isRound?Math.round(d*base)/base:((int)(d*base))/base;

		sop("num="+num);



		/*
		double d1 = d*100;
		sop("d1="+d1);
		d1 = d1+0.5;
		double d2 = (int)d1;
		sop("d2="+d2);
		double d3 = d2/100;
		sop("d3="+d3);

		*/
	}

	public static void show()
	{
		double d = Math.ceil(16.34);//ceil返回大于指定数据的最小整数。
		double d1 = Math.floor(12.34);//floor返回小于指定数据的最大整数。

		long l = Math.round(12.54);//四舍五入
		sop("d="+d);
		sop("d1="+d1);
		sop("l="+l);

		double d2 = Math.pow(2,3);
		sop("d2="+d2);
	}
	public static void sop(Object obj)
	{
		
		System.out.println(obj);
	}
}

2、IO(Input Output)流


输入流、输出流
字节流基类:
InputStream OutputStream
字符流基类:
Reader Writer

IO流图结构:

图 2-1

字符流特点:
FileWriter

import java.io.*;
class  FileWriterDemo
{
	public static void main(String[] args) throws IOException
	{
		//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
		//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
		//其实该步就是在明确数据要存放的目的地。
		FileWriter fw = new FileWriter("demo.txt");

		//调用write方法,将字符串写入到流中。
		fw.write("abcde");

		//刷新流对象中的缓冲中的数据。
		//将数据刷到目的地中。
		//fw.flush();


		//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
		//将数据刷到目的地中。
		//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
		fw.close();
	}
}

IOException异常处理方式:

/*
IO异常的处理方式。
*/
import java.io.*;

class  FileWriterDemo2
{
	public static void main(String[] args) 
	{
		FileWriter fw = null;
		try
		{
			fw = new FileWriter("demo.txt");
			fw.write("abcdefg");

		}
		catch (IOException e)
		{
			System.out.println("catch:"+e.toString());
		}
		finally
		{
			try
			{
				if(fw!=null)
					fw.close();				
			}
			catch (IOException e)
			{
				System.out.println(e.toString());
			}
			
		}		

	}
}

文件的续写:
文件已经存在:
FileWriter(文件,true);//传递一个true参数,代表不覆盖文件,并对已有文件的末尾进行续写。

/*
演示对已有文件的数据续写。
*/
import java.io.*;
class  FileWriterDemo3
{
	public static void main(String[] args) throws IOException
	{

		//传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。
		FileWriter fw = new FileWriter("demo.txt",true);

		fw.write("nihao\r\nxiexie");

		fw.close();
	}
}


文本文件读取方式:
1、FileReader类
read():方法一次读取一个字符,而且会自动往下读。
返回-1则代表读取完毕。
2、通过字符数组进行读取:
read(char chs[]);
如:

import java.io.*;

class  FileReaderDemo
{
	public static void main(String[] args) throws IOException
	{
		//创建一个文件读取流对象,和指定名称的文件相关联。
		//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
		FileReader fr = new FileReader("demo.txt");

		//调用读取流对象的read方法。
		//read():一次读一个字符。而且会自动往下读。
		
		int ch = 0;

		while((ch=fr.read())!=-1)
		{
			System.out.print((char)ch);
		}
		fr.close();

	}
}

/*
第二种方式:通过字符数组进行读取。
*/

import java.io.*;

class FileReaderDemo2 
{
	public static void main(String[] args) throws IOException
	{
		FileReader fr = new FileReader("demo.txt");
		

		//定义一个字符数组。用于存储读到字符。
		//该read(char[])返回的是读到字符个数。
		char[] buf = new char[1024];

		int num = 0;
		while((num=fr.read(buf))!=-1)
		{
			System.out.println(new String(buf,0,num));
		}
		

		fr.close();
	}
}

Reader类:
int read() 读取单个字符。
int read(char[] cbuf) 将字符读入数组。
abstract int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
int read(CharBuffer target) 试图将字符读入指定的字符缓冲区。
long skip(long n) 跳过字符。
Writer类:
Writer append(char c) 将指定字符添加到此 writer。
void write(char[] cbuf)  写入字符数组。
abstract  void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
void write(int c) 写入单个字符。
void write(String str) 写入字符串。
void write(String str, int off, int len)  写入字符串的某一部分。
abstract  void flush()  刷新该流的缓冲。

复制:

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class XuXie {

	public static void main(String args[]) throws IOException{
		FileWriter fw = new FileWriter("C:\\demo.txt");
		FileReader fr = new FileReader("c:\\rajesh.txt");
		char[] buf = new  char[1024];
		int num = 0;
		while((num=fr.read(buf))!=-1){
			//复制
			fw.write(buf, 0, num);
			//打印在控制台上
			System.out.print(new String(buf,0,num));
		}
		fr.close();
		fw.close();	
	}
}

字符流的缓冲区:提高了对数据的读写效率。
BufferedWriter
newLine();跨平台换行;
BufferedReader
readLine();没有返回行终止字符,只返回有效字符。
缓冲区的出现时为了提高流的操作效率而出现的。
所以在创建缓冲区之前,必须要先有流对象。

练习:通过缓冲区复制一个.txt文件。

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

public class BufferedDemo {

	public static void main(String[] args) throws IOException{
		BufferedReader bur = new BufferedReader(new FileReader("c:\\rajesh.txt"));
		BufferedWriter buw = new BufferedWriter(new FileWriter("c:\\22_copy.txt"));
		
		String line = null;
		while((line=bur.readLine())!=null){
			buw.write(line);
			buw.newLine();
			buw.flush();
		}
		bur.close();
		buw.close();
	}

}


原理:图解

编写自己的readLine方法:

class MyBufferedReader extends Reader{

	private Reader r;
	MyBufferedReader(Reader r){
		this.r = r;
	}
	//自定义readLine方法。
	public String myReadLine() throws IOException{
		//定义一个临时容器。原BufferReader封装的是字符数组。
		//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
		StringBuilder sb = new StringBuilder();
		int ch = 0;
		while((ch=r.read())!=-1){
			if(ch=='\r')
				continue;
			if(ch=='\n')
				return sb.toString();
			sb.append((char)ch);
		}
		if(sb.length()!=0){
			return sb.toString();
		}
		return null;
	}
	@Override
	public int read(char[] cbuf, int off, int len) throws IOException {
		return r.read();
	}
	@Override
	public void close() throws IOException {
		r.close();
	}

 

装饰设计模式:就是对已有的对象的功能进行增强。
使用场景:
1、当我们需要为某个现有的对象,动态的增加一个新的功能或职责时,可以考虑使用装饰模式。
2、适应于某个对象的职责经常发生变化或者经常需要动态的增加职责,避免因为这种为了适应这样的变化,而增加继承子类扩展的方式,因为
这种方式为 造成,子类膨胀的速度过快,难以控制。

装饰和继承的区别:
装饰模式比继承要灵活。避免了继承体系臃肿。
而且降低了类于类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
所以装饰类和被装饰类通常是都属于一个体系中的。

BufferedReader的子类:
LineNumberReader:可以跟踪行号的缓冲字符输入流。
练习:模拟一个带行号的装饰类

package cn.itcast.test;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class MyLineNumberDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws IOException{
		MyLineNumberReader mr = new MyLineNumberReader(new FileReader("c:\\OutlookExpressLog1.txt"));
		String line = null;
		mr.setLineNumber(100);
		while((line=mr.myReadLine())!=null){
			System.out.println(mr.getLineNumber()+" "+line);
		}
		mr.close();
	}

}

class MyLineNumberReader extends MyBufferedReader{

	private int lineNumber;
	MyLineNumberReader(Reader r) {
		super(r);
	}
	public String myReadLine() throws IOException{
		lineNumber++;
		 return super.myReadLine();	
	}
	public int getLineNumber() {
		return lineNumber;
	}
	public void setLineNumber(int lineNumber) {
		this.lineNumber = lineNumber;
	}
	
}

 

字节流
InputStream
int available() 返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。
abstract  int read()  从输入流中读取数据的下一个字节。
int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
int read(byte[] b, int off, int len) 将输入流中最多 len 个数据字节读入 byte 数组。
OutputStream
void write(byte[] b)  将 b.length 个字节从指定的 byte 数组写入此输出流。
void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract  void write(int b) 将指定的字节写入此输出流。

基本操作与字符流类相同,但它不仅可以操作字符,还可以操作其他媒体文件。
字节流File读写操作.
FileOutputStream和FileInputStream
getBytes();方法。
FileInputStream
available();获取字符个数。

FileInputStream fis = null;
try {
	fis = new FileInputStream("c:\\rajesh.txt");
	byte[] bys = new byte[fis.available()];//定义一个刚好的缓冲区,避免循环。
	fis.read(bys);
	System.out.println(new String(bys));
} catch (IOException e) {
	e.printStackTrace();
}finally{
	 if(fis!=null){
		try {
			fis.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		}
	}
}


复制图片:

/*
复制一个图片
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。

*/

import java.io.*;
class  CopyPic
{
	public static void main(String[] args) 
	{
		FileOutputStream fos = null;
		FileInputStream fis = null;
		try
		{
			fos = new FileOutputStream("c:\\2.bmp");
			fis = new FileInputStream("c:\\1.bmp");

			byte[] buf = new byte[1024];

			int len = 0;

			while((len=fis.read(buf))!=-1)
			{
				fos.write(buf,0,len);
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("复制文件失败");
		}
		finally
		{
			try
			{
				if(fis!=null)
					fis.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("读取关闭失败");
			}
			try
			{
				if(fos!=null)
					fos.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("写入关闭失败");
			}
		}
	}
}

 

自定义缓存区
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int.
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面补了24个0,变成了int类型的数值。
 11111111 11111111 11111111 11111111                       
&00000000 00000000 00000000 11111111
------------------------------------
 00000000 00000000 00000000 11111111
而在写入数据时,只写该int类型数据的最低8位。

import java.io.*;

class MyBufferedInputStream
{
	private InputStream in;

	private byte[] buf = new byte[1024*4];
		
	private int pos = 0,count = 0;
	
	MyBufferedInputStream(InputStream in)
	{
		this.in = in;
	}

	//一次读一个字节,从缓冲区(字节数组)获取。
	public int myRead()throws IOException
	{
		//通过in对象读取硬盘上数据,并存储buf中。
		if(count==0)
		{
			count = in.read(buf);
			if(count<0)
				return -1;
			pos = 0;
			byte b = buf[pos];

			count--;
			pos++;
			return b&255;//强制提升
		}
		else if(count>0)
		{
			byte b = buf[pos];

			count--;
			pos++;
			return b&0xff;
		}
		return -1;

	}
	public void myClose()throws IOException
	{
		in.close();
	}
}

 

read方法在提升,write方法在强转。
读取键盘录入:
\r 13 \n 10;
mp3复制,通过缓冲区。

/*
演示mp3的复制。通过缓冲区。
BufferedOutputStream
BufferedInputStream


*/
import java.io.*;
class  CopyMp3
{
	public static void main(String[] args) throws IOException
	{
		long start = System.currentTimeMillis();
		copy_2();
		long end = System.currentTimeMillis();

		System.out.println((end-start)+"毫秒");
	}

	public static void copy_2()throws IOException
	{
		MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("c:\\9.mp3"));//通过自定义的缓冲区读取流
		BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\3.mp3"));
		
		int by = 0;

		//System.out.println("第一个字节:"+bufis.myRead());

		while((by=bufis.myRead())!=-1)
		{
			bufos.write(by);
		}

		bufos.close();
		bufis.myClose();
	}

	//通过字节流的缓冲区完成复制。
	public static void copy_1()throws IOException
	{
		BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
		BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
		
		int by = 0;

		while((by=bufis.read())!=-1)
		{
			bufos.write(by);
		}

		bufos.close();
		bufis.close();

		
	}
}


字节流转换字符流
转换流
InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
可以选择编码表读取
键盘录入:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

字符流转换字节流
OutputStreamWriter 可以指定编码表
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("1.txt"),"utf-8"));

通过三个明确来确定使用哪个流对象。
1,明确源和目的。
 源:输入流。InputStream  Reader
 目的:输出流。OutputStream  Writer。
2,操作的数据是否是纯文本。
 是:字符流。
 不是:字节流。

3,当体系明确后,在明确要使用哪个具体的对象。
 通过设备来进行区分:
 源设备:内存,硬盘。键盘
 目的设备:内存,硬盘,控制台。

异常的日志信息
printStackTrace(PrintStream ps);
系统信息
Properties类
Properties是hashtable的子类。
也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串。

是集合中和IO技术相结合的集合容器。

该对象的特点:可以用于键值对形式的配置文件。

那么在加载数据时,需要数据有固定格式:键=值。
---------------------------------------
File类
用来将文件或者文件夹封装成对象

构造函数
File(File parent, String child)
File(String pathname)
File(String parent, String child)
File(URI uri)

File.separator 分隔符

常见方法:
File类常见方法:
1,创建。
 boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
      和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。

 boolean mkdir():创建文件夹。
 boolean mkdirs():创建多级文件夹。
2,删除。
 boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回false。
 void deleteOnExit();在程序退出时删除指定文件。
3,判断。
 boolean exists() :文件是否存在.
 isFile():
 isDirectory();
 isHidden();
 isAbsolute();

4,获取信息。
 getName():
 getPath():
 getParent():
 getAbsolutePath()
 long lastModified()
 long length()

判断文件对象是否是文件或者目的时,必须先判断该文件对象封装的内容是否存在。
通过exists判断。
list 返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
listRoot 列出可用的文件系统根。
listFiles(FileFilter filter)或者(FilenameFilter filter) --重要
FilenameFilter文件名过滤
递归
递归函数即自调用函数,在函数体内部直接或间接地自己调用自己,即函数的嵌套调用是函数本身。
练习:

package cn.itcast.test;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class FileListDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		File dir = new File("f:\\example");
		List<File> list = new ArrayList<File>();
		fileToList(dir,list);
		System.out.println(list.size());
		String fileName = "c:\\demo.txt";
		writeToList(list,fileName);
	}
	public static void fileToList(File dir,List<File> list){
		File[] files = dir.listFiles();
		for(File file : files){
			if(file.isDirectory()){
				list.add(file);
				fileToList(file,list);
			}else{
				list.add(file);
			}
		}
	}
	
	public static void writeToList(List<File> list,String fileName){
		BufferedWriter buw = null;
		try {
			buw = new BufferedWriter(new FileWriter(fileName));
			for(File f:list){
				buw.write(f.getAbsolutePath());
				buw.newLine();
				buw.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(buw!=null){
				try {
					buw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

 

内存溢出
效率不高
删除一个带内容的目录

public static void deleteDir(File dir){
	File[] files = dir.listFiles();
	for(File file : files){
		if(file.isDirectory()){
			deleteDir(file);
		}
		file.delete();
	}
	dir.delete();
}


Properties
具有Map集合特点
是集合和IO技术结合的集合容器
可以用于键值对形式的配置文件。
新方法
load(InputStream is);
load(Reader r);
list(OutputStream os);
store();
练习:计数器

/*
用于记录应用程序运行次数。
如果使用次数已到,那么给出注册提示。

很容易想到的是:计数器。
可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。
可是随着该应用程序的退出,该计数器也在内存中消失了。

下一次在启动该程序,又重新开始从0计数。
这样不是我们想要的。

程序即使结束,该计数器的值也存在。
下次程序启动在会先加载该计数器的值并加1后在重新存储起来。

所以要建立一个配置文件。用于记录该软件的使用次数。

该配置文件使用键值对的形式。
这样便于阅读数据,并操作数据。

键值对数据是map集合。
数据是以文件形式存储,使用io技术。
那么map+io -->properties.

配置文件可以实现应用程序数据的共享。
*/
import java.io.*;
import java.util.*;
class  RunCount
{
	public static void main(String[] args) throws IOException
	{
		Properties prop = new Properties();

		File file = new File("count.ini");
		if(!file.exists())
			file.createNewFile();
		
		FileInputStream fis = new FileInputStream(file);

		prop.load(fis);
		

		int count = 0;
		String value = prop.getProperty("time");
		
		if(value!=null)
		{
			count = Integer.parseInt(value);
			if(count>=5)
			{
				System.out.println("您好,使用次数已到,拿钱!");
				return ;
			}

		}

		count++;

		prop.setProperty("time",count+"");

		FileOutputStream fos = new FileOutputStream(file);

		prop.store(fos,"");

		fos.close();
		fis.close();
		
	}
}


打印流
PrintWriter 可以自动刷新 字符打印流
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream
4,字符输出流,Writer。
PrintWriter(OutputStream out, boolean autoFlush)
PrintStream
字节打印流
构造函数可以接收的参数类型:
1,file对象。File
2,字符串路径。String
3,字节输出流。OutputStream
PrintStream(OutputStream out, boolean autoFlush)

序列流
SequenceInputStream
可以将多个流拼接成一个流
练习:

import java.io.*;
import java.util.*;
class SequenceDemo 
{
	public static void main(String[] args) throws IOException
	{

		Vector<FileInputStream> v = new Vector<FileInputStream>();
		
		v.add(new FileInputStream("c:\\1.txt"));
		v.add(new FileInputStream("c:\\2.txt"));
		v.add(new FileInputStream("c:\\3.txt"));

		Enumeration<FileInputStream> en = v.elements();
		//接收枚举类型
		SequenceInputStream sis = new SequenceInputStream(en);

		FileOutputStream fos = new FileOutputStream("c:\\4.txt");

		byte[] buf = new byte[1024];

		int len =0;
		while((len=sis.read(buf))!=-1)
		{
			fos.write(buf,0,len);
		}

		fos.close();
		sis.close();
	}
}

 

List转换为枚举

ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();

for(int x=1; x<=3; x++)
{
	al.add(new FileInputStream("c:\\splitfiles\\"+x+".part"));
}

final Iterator<FileInputStream> it = al.iterator();

Enumeration<FileInputStream> en = new Enumeration<FileInputStream>()
{
	public boolean hasMoreElements()
	{
		return it.hasNext();
	}
	public FileInputStream nextElement()
	{
		return it.next();
	}
};


切割文件

public static void splitFile()throws IOException
{
	FileInputStream fis =  new FileInputStream("c:\\1.bmp");

	FileOutputStream fos = null;


	byte[] buf = new byte[1024*1024];

	int len = 0;
	int count = 1;
	while((len=fis.read(buf))!=-1)
	{
		fos = new FileOutputStream("c:\\splitfiles\\"+(count++)+".part");
		fos.write(buf,0,len);
		fos.close();
	}
		
	fis.close();	
}


对象的序列化
ObjectInputStream
ObjectOutputStream

将堆内存上的对象存入硬盘上。
持久化存储
对象的持久化
可以操作基本数据类型
想要实现序列化需要实现Serializable接口
静态不能被序列化。
关键字:transient 也不能被序列化

管道流
PipedInputStream
PipedOutputStream

不建议使用单线程,因为容易死锁。

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

public class PipedStreamDemo {

	public static void main(String[] args) throws IOException {
		PipedInputStream pis = new PipedInputStream();
		PipedOutputStream pos = new PipedOutputStream();
		pis.connect(pos);
		Read r = new Read(pis);
		Write w = new Write(pos);
		new Thread(r).start();
		new Thread(w).start();
	}

}
class Read implements Runnable{

	private PipedInputStream pis;
	Read(PipedInputStream pis){
		this.pis = pis;
	}
	@Override
	public void run() {
		byte[] buf = new byte[1024];
		int num = 0;
		try {
			while((num=pis.read(buf))!=-1){
				System.out.println(new String(buf,0,num));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(pis!=null){
				try {
					pis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}	
}
class Write implements Runnable{

	private PipedOutputStream pos;
	Write(PipedOutputStream pos){
		this.pos = pos;
	}
	@Override
	public void run() {
		try {
			pos.write("asfjdsaklfads".getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(pos!=null){
				try {
					pos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
}

 

随机访问文件中的内容
RandomAccessFile
直接继承Object
具备读和写的功能。
getFilePointer:获取指针位置
seek改变指针位置。
该类只能操作文件。
mode值:
r 只读,不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
rw 读写,操作的文件不存在,会自动创建。如果存则不会覆盖。

通过调整指针,随机访问任意数据
skipBytes:只能往前跳

可以随机位置上写。
可以实现数据的分段写入

IO包中的其他类
DataInputStream DataOutputStream
可以操作基本数据类型的流对象
writeUTF();

ByteArrayInputStream ByteArrayOutputStream
包含内部缓冲区
不涉及底层资源操作。
用流的读写思想来操作数组。
由于没有用到系统资源,所以不用进行close关闭。
在流操作规律讲解时:
源设备,
 键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:
 控制台 System.out,硬盘FileStream,内存 ArrayStream。

writeTo(InputStream in);

StringReader StringWriter

字符编码:

转换流:

编码:字符串变成字节数组
String-->byte[]; str.getBytes(charsetName);
解码:字节数组变成字符串
byte[]-->String; new String(byte[],charsetName);
联通例子:
utf-8编码格式:
1110
10
10

110
10

0

------- android培训java培训、 java学习型技术博客、期待与您交流! ----------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值