`
milimili
  • 浏览: 3192 次
社区版块
存档分类
最新评论

Java IO

阅读更多
第一讲     什么是IO? IO分类?
1、何为流:流是JAVA中的一个重要机制,通过流我们能自由地控制文件,内存,IO设备的数据输入和输出。
2、Java中流的体系:Java用于操作流的对象都在java.io包中。
3、流的分类
1)按流的方向分为:输入流和输出流
2)按流处理数据单位的不同分为:字节流和字符流
3)按流的功能不同分为:节点流和处理流
4、IO流的四大抽象类:
字符流:Reader、Writer
字节流:InputStream、OutputStream


第二讲    Reader、Writer字符流
一、字符流
    字符流使用系统默认的编码表处理文字数据。
二、Reader、Writer本身是抽象类、是所有字符输入流、输出流的父类。其定义了所有字符流的标准、和一些必须具有的基本方法。

三、字符流的读写
1、Writer流步骤(会发生IOException异常,所以在整个步骤中,需要对IO异常进行try处理。)
1)创建FileWriter对象。构造方法可以接收String路径、File对象作为参数。FileWriter(String fileName) 创建对象时必须要明确被操作的文件。若目录下如果已有同名文件,则覆盖。不想覆盖原文件,可以用FileWriter(String fileName, boolean append) 构造方法。如果指定的位置不存在,就会发生IOException异常。
2)调用write方法,将数据写入到流中。
3)调用flush()方法,刷新该流的缓冲,将数据刷新到目的地中。flush()方法调用OS功能完成数据的书写,使用系统资源后,一定要关闭资源。
4)调用close()方法,关闭流资源。关闭前会刷新一次内部的缓冲数据到目的文件中。
2、Reader流步骤
1)创建对象关联指定文件。若指定文件不存在,会发生异常FileNotFoundException。
2)read()或者 read(char[] cbuf)。读单个字符或通过字符数组进行读取。
3)close()关闭流资源。
/* 
 DEMO:示例FileWriter、FileReader操作步骤
 功能:文本文件的拷贝
 需求:文本文件复制 
 步骤: 
 1、在e盘创建一个文件。用于存储c盘文件中的数据。 
 2、定义读取流和c盘文件关联。 
 3、通过不断的读写完成数据存储。 
 4、关闭资源。 
 */
import java.io.*;

class ReaderWriterCopy {
	public static void main(String[] args) {
		
		copy_singleCharReeadWrite();
//		copy_arrayCharReadWrite();
	}

	// 一个字符一个字符复制,每个字符的读写都会调用OS系统资源
	public static void copy_singleCharReeadWrite() {
		FileWriter fw = null;
		FileReader fr = null;
		try {
			// 关联读取和写入的文件
			fw = new FileWriter("E:\\IO_COPY.TXT");
			fr = new FileReader("E:\\IO.TXT");
			int ch = 0;
			while ((ch = fr.read()) != -1) {
				fw.write(ch);// 每个字符的读写都会调用OS系统资源
			}
		} catch (IOException e) {
			throw new RuntimeException("读写失败");
		} finally {
			if (fr != null)
				try {
					fr.close();
				} catch (IOException e) {
					throw new RuntimeException("关闭FileReader失败");
				}
			if (fw != null)
				try {
					fw.close();
				} catch (IOException e) {
					throw new RuntimeException("关闭FileWriter失败");
				}
		}
	}

	// 每次读写1024字节进行复制
	public static void copy_arrayCharReadWrite() {
		FileWriter fw = null;
		FileReader fr = null;
		try {
			// 关联读取和写入的文件
			fw = new FileWriter("E:\\IO_COPY.TXT");
			fr = new FileReader("E:\\IO.TXT");
			char[] arr = new char[1024];
			int len = 0;
			while ((len = fr.read(arr)) != -1) {
				fw.write(arr, 0, len);// 每次读写len个字节
			}
		} catch (IOException e) {
			throw new RuntimeException("读写失败");
		} finally {
			try {
				if (fr != null)
					fr.close();
			} catch (IOException e) {
				throw new RuntimeException("关闭FileReader失败");
			} finally {
				if (fw != null)
					try {
						fw.close();
					} catch (IOException e) {
						throw new RuntimeException("关闭FileWriter失败");
					}
			}
		}
	}
}  


四、BufferedReader和BufferedWriter
1、目的:提高效率。缓冲各个字符,从而实现字符、数组和行的高效读写。 
2、原理:封装了数组,将数据存入,再一次性取出。
3、BufferedWriter的步骤:
         1)创建一个FileWriter 对象。
         FileWriter fw=new FileWriter("a.txt");
         2)为了提高字符写入流效率。加入缓冲技术。
BufferedWriter bufw =new BufferedWriter(fw);
         3)调用write方法写入数据到指定文件
         如:bufw.write("aaabbbccc");
         刷新缓冲区 bufw.flush();
         4)关闭缓冲区,就是关闭缓冲区中的流对象。
         如: bufw.close();
常用方法:数据换行。bufw.newLine();
4、BufferedReader的步骤:       
        1)创建一个FileReader 对象。
        如: FileReader fr=new FileReader("a.txt");
        2)为了提高效率。加入缓冲技术。
        如: BufferedReader bufr=new BufferedReader(fr);
        3)调用readLine方法按行读取
        如: String s=bufr.readLine();
        4)关闭流资源
        如: bufr.close();、
常用方法:readLine方法,返回null时表示读到文件末尾。

/* 
 DEMO:练习BufferedReader、BufferedWriter
 功能:复制一个文本文件。
 */
import java.io.*;

class ReaderWriteCopy {
	public static void main(String[] args) {
		BufferedWriter bfw = null;
		BufferedReader bfr = null;
		try {
			bfr = new BufferedReader(new FileReader("io.txt"));
			bfw = new BufferedWriter(new FileWriter("io_copy.txt"));
			// 按行取出
			String line = null;
			while ((line = bfr.readLine()) != null) {
				bfw.write(line);
				bfw.newLine();
				bfw.flush();// 别忘记flush
			}

		} catch (IOException e) {
			throw new RuntimeException("文件copy失败");
		} finally {
			if (bfw != null)
				try {
					bfw.close();// 关闭
				} catch (IOException e) {
					throw new RuntimeException("写入流关闭失败");
				}
			if (bfr != null)
				try {
					bfr.close();// 关闭读取流
				} catch (IOException e) {
					throw new RuntimeException("读取流关闭失败");
				}
		}
	}
}


5、自定义BufferedReader:
原理:
   根据BufferedReader类中readLine()的原理,自定义一个类中包含相同功能的方法
步骤:
a、初始化自定义的类,加入流对象。
b、定义一个临时容器,原BufferedReader封装的是字符数组,此类中可定义一个StringBuilder的容器,最终可实现字符串的提取。
/* 
需求:模拟BufferedReader写一个自己的MyBufferedReader 实现readLine方法
 */
import java.io.*;

class MyBufferedReader extends Reader {
	private Reader r;// 持有一个流对象
	MyBufferedReader(Reader r) {
		this.r = r;
	}

	// 按行读取
	public String myReadLine() throws IOException {
		// 创建一个容器,用来存储一行的字符
		StringBuilder sb = new StringBuilder();
		// 一个字符一个字符读取
		int ch = 0;
		while((ch = r.read()) != -1) {
			if (ch == '\r')// 如果遇到换行符,则继续
				continue;
			if (ch == '\n')// 如果遇到回车符,表示该行读取完毕
				return sb.toString();
			else
				sb.append((char) ch);// 将该行的字符添加到容器
		}
		if (sb.length() != 0)// 如果读取结束,容器中还有字符,则返回元素
			return sb.toString();
		return null;
	}

	// 复写父类中的抽象方法
	public int read(char[] cbuf, int off, int len) throws IOException {
		return r.read(cbuf, off, len);
	}

	// 复写父类的close方法
	public void close() throws IOException {
		r.close();
	}
}

// 测试MyBufferedReader
class MyBufferedReaderDemo {
	public static void main(String[] args) {
		MyBufferedReader mbr = null;
		try {
			mbr = new MyBufferedReader(new FileReader("E:\\io.txt"));
			String line = null; 
			while((line = mbr.myReadLine()) != null) {
				System.out.println(line);
			}
		} catch (IOException e) {
			throw new RuntimeException("读取数据失败");
		} finally {
			try {
				if (mbr != null)
					mbr.close();
			} catch (IOException e) {
				throw new RuntimeException("MyBufferedReader失败");
			}
		}
	}
}


6、LineNumberReader
BufferedReader中有个直接的子类LineNumberReader,其中有特有的方法获取和设置行号:
setLineNumber();//设置初始行号
getLineNumber();//获取行号
import java.io.*;
/* 
需求:利用LineNumberReader的特有方法去设置和获取文件中数据的行号 
*/  
class  LineNumberReaderDemo  
{  
    public static void main(String[] args)   
    {  
        LineNumberReader lnr=null;  
        try  
        {  
            lnr=new LineNumberReader(new FileReader("io.txt")); 
            lnr.setLineNumber(100);//设置开始行号  
            String line=null;
            while((line=lnr.readLine())!=null)  
            {  
                System.out.println(lnr.getLineNumber()+":"+line); 
            }  
        }  
        catch (IOException e)  
        {  
            throw new RuntimeException("读取数据失败");  
        }  
        finally  
        {  
            try  
            {  
                if(lnr!=null)  
                    lnr.close();  
            }  
            catch (IOException e)  
            {  
                throw new RuntimeException("读取流关闭失败");  
            }  
        }     
    }  
}  


四、装饰设计模式
1、目的
        对已有对象进行功能增强。可定义类,将已有对象传入,基于已有对象的功能,并提供加强功能。自定义的该类称之为装饰类。
2、特点
        装饰类通常都会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
3、装饰和继承的区别:
        1)装饰模式比继承要灵活。避免了继承体系的臃肿,且降低了类与类之间的关系。
        2)装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰的类通常都是属于一个体系。
        3)从继承结构转为组合结构。
注:在定义类的时候,不要以继承为主;可通过装饰设计模式进行增强类功能。灵活性较强,当装饰类中的功能不适合,可再使用被装饰类的功能。
示例:上面讲到的MyBufferedReader的例子就是最好的装饰设计模式的例子。
----------------------------------------------------------------------------------
第三讲     字节流
一、InputStream、OutputStream
1、字符流只能操作纯文本文件,字节流可以操作文本、多媒体等各种文件。
2、字节流对象可直接将数据写入到文件中,字符流操作数据要在字节和字符之间进行转换,字节流直接操作字节,所以不需要flush操作。
3、InputStream特有方法:int available();//返回文件中的字节个数

二、BufferedInputStream、BufferedOutputStream
1、目的:     提高读写效率。
2、特点:
        read():会将字节byte型值提升为int型值
        write():会将int型强转为byte型,即保留二进制数(&0xff)的最后八位。

三、自定义读取字节流缓冲区
需求:根据字节流缓冲区的原理,自定义一个字节流缓冲区。
注意:
1、字节流的读一个字节的read方法为什么返回值类型不是byte,而是int?
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1;-1是读取结束的标志。数据还没有读完,返回-1。为了避免这种情况将读到的字节进行int类型的提升。并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。而在写入数据时,只写该int类型数据的最低8位。byte类型的-1提升为int类型时还是-1。原因:因为在8个1前面补的全是1导致的,如果在8个1前面补0,即可以保留原字节数据不变,又可以避免-1的出现。将byte型数据&0xff即255即可。

import java.io.*;
/**
 *	DEMO:练习FileInputStream/FileOutputStream/BufferedInputStream/BufferedOutputStream
 *	功能:复制Mp3文件
 *  自己实现MyBufferedInputStream:
 *  用byte[]数组缓存,用count记录缓存数量,用pos记录下标
 **/


import java.io.*;

class CopyMp3 {
	public static void main(String[] args) {
//		用一个7M的mp3文件测试不同方法复制速度
//		long start = System.currentTimeMillis();
//		//测试FileInputStream、FileOutputStream复制
//		singleByteCopy();//用时46312毫秒
//		long end = System.currentTimeMillis();
//		sop(end - start);
		
		
//		long start = System.currentTimeMillis();
//		byteArrayCopy();//用时62毫秒
//		long end = System.currentTimeMillis();
//		sop(end - start);
		
//		long start = System.currentTimeMillis();
//		buffCopy();//用时406毫秒
//		long end = System.currentTimeMillis();
//		sop(end - start);
		
		long start = System.currentTimeMillis();
		testMyBufferedInputStream();//用时265毫秒
		long end = System.currentTimeMillis();
		sop(end - start);

	}

	public static void sop(Object o) {
		System.out.println(o);
	}
	
	// 一个个字节进行复制
	public static void singleByteCopy() {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			// 关联要复制的文件
			fis = new FileInputStream("e:\\io\\d.mp3");
			// 指定复制的路径
			fos = new FileOutputStream("e:\\io\\dsingle.mp3");
			int b = 0;
			while((b=fis.read())!=-1){
				fos.write(b);;
			}

		} catch (IOException e) {
			throw new RuntimeException("复制失败");
		} finally {
			try {
				if (fis != null)
					fis.close();// 关闭输入字节流
			} catch (IOException e) {
				throw new RuntimeException("FileInputStream关闭失败");
			}
			try {
				if (fos != null)
					fos.close();// 关闭输出字节流
			} catch (IOException e) {
				throw new RuntimeException("FileOutputStream关闭失败");
			}
		}	
		
	}

	// 使用读数组方式进行复制
	public static void byteArrayCopy() {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		try {
			// 关联要复制的文件
			fis = new FileInputStream("e:\\io\\d.mp3");
			// 指定复制的路径
			fos = new FileOutputStream("e:\\io\\darraycopy.mp3");
			// 利用数组的读取方式
			byte[] b = new byte[1024];
			int len = 0;
			while ((len = fis.read(b)) != -1)
			{
				fos.write(b, 0, len);
			}
		} catch (IOException e) {
			throw new RuntimeException("复制失败");
		} finally {
			try {
				if (fis != null)
					fis.close();// 关闭
			} catch (IOException e) {
				throw new RuntimeException("FileInputStream关闭失败");
			}
			try {
				if (fos != null)
					fos.close();// 关闭
			} catch (IOException e) {
				throw new RuntimeException("FileOutputStream关闭失败");
			}
		}
	}

	public static void  buffCopy() {
		BufferedInputStream bfis = null;
		BufferedOutputStream bfos = null;
		try {
			bfis = new BufferedInputStream(new FileInputStream("e:\\io\\d.mp3"));
			bfos = new BufferedOutputStream(new FileOutputStream("e:\\io\\buffcopy.mp3"));
			int ch = 0;
			while ((ch = bfis.read()) != -1) {
				bfos.write(ch);
			}
		} catch (IOException e) {
			throw new RuntimeException("读取数据失败");
		} finally {
			if (bfis != null)
				try {
					bfis.close();
				} catch (IOException e) {
					throw new RuntimeException("bfis关闭失败");
				}
			if (bfos != null)
				try {
					bfos.close();
				} catch (IOException e) {
					throw new RuntimeException("bfos关闭失败");
				}

		}

	}

	public static void testMyBufferedInputStream() {
		MyBufferedInputStream bfis = null;
		BufferedOutputStream bfos = null;
		try {
			bfis = new MyBufferedInputStream(new FileInputStream("E:\\IO\\d.mp3"));
			bfos = new BufferedOutputStream(new FileOutputStream("E:\\IO\\d_myBuff.mp3"));
			int ch = 0;
			System.out.println("first number:" + bfis.myRead());
			while ((ch = bfis.myRead()) != -1) {
				bfos.write(ch);
			}
		} catch (IOException e) {
			throw new RuntimeException("读取数据失败");
		} finally {
			if (bfis != null)
				try {
					bfis.myClose();
				} catch (IOException e) {
					throw new RuntimeException("bfis关闭失败");
				}
			if (bfos != null)
				try {
					bfos.close();
				} catch (IOException e) {
					throw new RuntimeException("bfos关闭失败");
				}

		}

	}

}
/**
 * 自定义模仿理解BufferedInputStream的原理
 * 每次调用OS系统资源,将1024个字节数据存入数组
 *
 */
class MyBufferedInputStream {
	private InputStream in;

	MyBufferedInputStream(InputStream in) {
		this.in = in;
	}

	int count = 0, pos = 0;
	byte[] b = new byte[1024];//字节缓冲区

	public int myRead() throws IOException {
		if (count == 0) {//count记录缓冲区剩余字节数量
			count = in.read(b);//读入字节到byte数组b,用count记录读入的字节数
			pos = 0;
			if (count == -1) {//读入的byte时返回的是-1,标志着文件中数据已经全部读完
				return -1;
			}
			byte by = b[pos];//每返回一个字节,缓冲区字节数目--,指针++
			count--;
			pos++;
			return (by)&0xff;
		} else if (count > 0) {//缓冲区还有字节数据,依次取用
			byte by = b[pos];
			count--;
			pos++;
			return (by)&0xff;//byte类型提升为int类型,字节数增加,前三个字节被补1,原字节数据改变。  
							 //通过与上0xff,将byte类型提升为int类型同时前三个字节补0,最后一个字节数据不变。
							 //在输出字节流写入数据时,只写该int类型数据的最低8位。  
		}
		return -1;

	}

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

	}

}

__________________________________________________________________
第四讲     流操作规律
一、键盘录入
1、System.in与out
        System.in:标准输入设备,键盘。类型是InputStream.
        Ssytem.out:标准的输出设备,控制台。类型是PrintStream是OutputStream的子类FilterOutputStream的子类。
2、整行录入
       当使用System.in进行键盘录入时,只能一个字节一个字节录入。为了提高效率,可以自定义一个数组将一行字节进行存储。当一行录入完毕,再处理整行数据。这就是
BufferedReader类中readLine()的原理。
3、转换流
3.1   InputStreamReader将字节流通向字符流
       a、获取键盘录入对象。
              InputStream in=System.in;
       b、将字节流对象转成字符流对象,使用转换流。
              InputStreamReaderisr=new InputStreamReader(in);
       c、为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
              BufferedReaderbr=new BufferedReader(isr);
       //键盘录入最常见写法
              BufferedReaderin=new BufferedReader(new InputStreamReader(System.in));
3.2   OutputStreamWriter字符流通向字节流
       步骤和InputStreamReader转换流一样。
/* 
需求:将键盘录入的数据,显示在控制台,当输入over时,表示结束 
源:键盘录入。 
目的:控制台。 
 
*/  
import java.io.*;  
class Demo   
{  
    public static void main(String[] args)throws IOException  
    {  
        //获取键盘录入对象。  
        //InputStream in=System.in;  
        //将字节流对象转成字符流对象,使用转换流。  
        //InputStreamReader isr=new InputStreamReader(in);  
        //为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader  
        //BufferedReader br=new BufferedReader(isr);  
  
        //键盘录入最常见写法  
        BufferedReader in=new BufferedReader(new InputStreamReader(System.in));  
  
        //字符流通向字节流  
        BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(System.out));  
  
        String s=null;  
        while((s=in.readLine())!=null)  
        {  
            if("over".equals(s))  
                break;  
            bw.write(s.toUpperCase());//写入数据  
            bw.newLine();//换行  
            bw.flush();//刷新  
              
        }  
        bw.close();//关闭流资源  
        in.close();  
    }  
}  


二、确定用哪种流对象
4.三步完成:
4.1     明确源和目的。
        源:输入流。InputStream  Reader
        目的:输出流。OutputStream  Writer
4.2     操作的数据是否是纯文本。
        是:字符流
        否:字节流
4.3     当体系明确后,再明确要使用哪个具体的对象。通过设备来进行区分:
        源设备:内存,硬盘,键盘
        目的设备:内存,硬盘,控制台
5、规律体现
5.1 将一个文本文件中数据存储到另一个文件中。复制文件。
        1)源:因为是源,所以使用读取流:InputStream和Reader
             明确体系:是否操作文本:是,Reader
              明确设备:Reader体系中可以操作文件的对象是FileReader
              是否需要提高效率:是,加入Reader体系中缓冲区 BufferedReader.
              FileReader fr = new FileReader("a.txt");
              BufferedReader bufr = new BufferedReader(fr);
        2)目的:输出流:OutputStream和Writer
             明确体系:是否操作文本:是,Writer
              明确设备:Writer体系中可以操作文件的对象FileWriter。
              是否需要提高效率:是,加入Writer体系中缓冲区 BufferedWriter
              FileWriter fw = new FileWriter("b.txt");
              BufferedWriter bufw = new BufferedWriter(fw);
练习:将一个图片文件中数据存储到另一个文件中。复制文件。要按照以上格式自己完成三个明确。
        1)源:输入流,InputStream和Reader
            是否是文本?否,InputStream
            源设备:硬盘上的一个文件。InputSteam体系中可以操作文件的对象是FileInputSteam
            是否需要提供效率:是,BufferedInputStream
              BufferedInputSteambis=new BufferedInputStream(newFileInputStream("c:/users/asus/desktop/1.jpg"));
        2)目的:输出流,OutputStream和Writer
             是否是文本?否,OutputStream
             源设备:硬盘上的文件,FileOutputStream
             是否需要提高效率:是,加入BufferedOutputStream
               BufferedOutputStreambos=newBufferedOutputStream(newFileOutputStream("c:/users/asus/desktop/2.jpg"));
5.2 需求:将键盘录入的数据保存到一个文件中。
        1)源:InputStream和Reader
              是不是纯文本?是,Reader
              设备:键盘。对应的对象是System.in。——为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。所以既然明确了Reader,那么就将System.in转换成

Reader。用Reader体系中转换流,InputStreamReader
              InputStreamReaderisr = new InputStreamReader(System.in);
             需要提高效率吗?需要,BufferedReader
             BufferedReaderbufr = new BufferedReader(isr);
       2)目的:OutputStream  Writer
             是否是存文本?是!Writer。
             设备:硬盘。一个文件。使用 FileWriter。
             FileWriter fw = newFileWriter("c.txt");
           需要提高效率吗?需要。
            BufferedWriter bufw = new BufferedWriter(fw);
5.3   扩展:想要把录入的数据按照指定的编码表(UTF-8)(默认编码表是GBK),将数据存到文件中。
        目的:OutputStream  Writer
        是否是存文本?是!Writer。
        设备:硬盘上的一个文件。使用 FileWriter。——但是FileWriter是使用的默认编码表:GBK。而存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。所以要使用的对象是OutputStreamWriter。
        该转换流对象要接收一个字节输出流,而且还可以操作的文件的字节输出流:FileOutputStream
        OutputStreamWriter osw =new OutputStreamWriter(newFileOutputStream("d.txt"),"UTF-8");
        需要高效吗?需要,BufferedWriter
        BufferedWriter bufw = new BufferedWriter(osw);
记住:
       转换流什么使用?
       字符和字节之间的桥梁。通常,涉及到字符编码转换时,需要用到转换流。
练习:将一个文本数据打印在控制台上。要按照以上格式自己完成三个明确。
        1)源:InputStream、Reader
            是文本?是:Reader
            设备:硬盘。上的文件:FileReader
            是否需要提高效率?是:BufferedReader
             BufferedReader br=new BufferedReader(newFileReader("1.txt"));
       2)目的:OutputStream Writer
            是文本?是:Writer
            设备:控制台。对应对象System.out。由于System.out对应的是字节流,所以利用OutputSteamWriter转换流
            是否提高效率?是:BufferedWriter
              BufferedWriter bw =new BufferedWriter(newOutputStreamWriter(system.out));
/* 
2、需求:想把键盘录入的数据存储到一个文件中。 
源:键盘 
目的:文件 
把录入的数据按照指定的编码表(UTF-8),将数据存到文件中。 
 
 
3、需求:想要将一个文件的数据打印在控制台上。 
源:文件 
目的:控制台 
 
 
*/  
import java.io.*;  
class  Demo
{  
    public static void main(String[] args)throws IOException  
    {  
          
        //键盘录入  
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));  
  
        //存入文件中,按照指定的编码表(UTF-8)   
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream("readin1.txt"),"UTF-8"));  
  
        String line=null;  
        while((line=br.readLine())!=null)  
        {  
            if("over".equals(line))  
                break;  
            bw.write(line);  
            bw.newLine();  
            bw.flush();  
        }  
          
        /* 
        //录入文件数据 
        BufferedReader br=new BufferedReader(new InputStreamReader(new FileInputStream("TransStreamDemo2.java"))); 
 
        //显示在控制台 
        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out)); 
 
        String line=null; 
        while((line=br.readLine())!=null) 
        { 
            if("over".equals(line)) 
                break; 
            bw.write(line); 
            bw.newLine(); 
            bw.flush(); 
        } 
        */  
    }  
} 


/**
 * 异常的日志信息
 * 当程序在执行的时候,出现的问题是不希望直接打印给用户看的,
 * 是需要作为文件存储起来,方便程序员查看,并及时调整的。
 * 可以创建一个PrintStream对象,传给System.setOut(),修改输出流设备  
 */
import java.io.*;  
import java.text.*;  
import java.util.*;  
class  Demo  
{  
    public static void main(String[] args)   
    {  
        try  
        {  
            int[] arr =new int[2];  
            System.out.println(arr[3]);  
  
        }  
        catch (Exception e)  
        {  
            try  
            {  
                Date d=new Date();//创建时间对象  
            //时间模块格式对象  
            SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");  
                String s=sdf.format(d);    
                PrintStream ps=new PrintStream("d:\\info.log");//打印流对象  
                System.setOut(ps);//修改输出流设备.通过System类的setIn,setOut方法可以对默认设备进行改变  
                ps.println(s);//输出时间  
                  
            }  
            catch (IOException ex)  
            {  
                throw new RuntimeException("文件创建失败");  
            }  
            e.printStackTrace(System.out);//将异常信息输出指定输出流  
        }  
    }  
}  


//将系统属性信息保存到指定文本中  
import java.util.*;    
import java.io.*;    

class Demo     
{    
 public static void main(String[] args)     
 {     
     PrintStream ps = null;    
     try    
     {    
        //获取系统信息:    
        Properties pop = System.getProperties();    
        //创建输出流对象,将输出流中数据存入指定文件中    
        ps = new PrintStream("d:\\systeminfo.txt");    
        //将属性列表输出到指定的输出流    
        pop.list(ps);    
     }    
     catch (Exception e)    
     {    
          throw new RuntimeException("获取系统信息失败。");    
     }    
  }    
}  
 


---------------------------------------------------------------------
第一讲     File类
一、概述
1、File类:文件和目录路径名的抽象表现形式
2、特点:
        1)用来将文件或目录封装成对象
        2)方便于对文件与目录的属性信息进行操作
        3)File类的实例是不可变的;也就是说,一旦创建,File 对象表示的抽象路径名将永不改变
        4)File对象可以作为参数传递给流的构造函数

二、File对象创建
方式一:     
             File f =new File("a.txt");
        将a.txt封装成File对象。可以将已有的和未出现的文件或者文件夹封装成对象。
方式二:
            File f2=newFile("c:\\abc","b.txt");
        将文件所在目录路径和文件一起传入,指定文件路径。
方式三:
            File d=new File("c:\\abc");
             File f3=new File(d,"c.txt");
        将文件目录路径封装成对象。再创建文件对象。降低了文件于父目录的关联性。
小知识:
        File.separator表示目录分隔符,可以跨平台使用。相当于路径中的“\”(双斜杠\\在windows中表示表示转义后的分隔符,但是在linux系统中就不是)。

三、File类的常见方法
1、创建
        boolean createNewFile();
        //在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立就创建文件。而且文件已经存在,会覆盖。
        boolean mkdir();//创建文件夹,只能创建一级文件夹
例:
        File dir=new File("abc");
        dir.mkdir();//创建abc这个文件夹
        boolean mkdirs();//创建多级文件夹
2、删除
        boolean delete();
        //删除文件或目录。文件存在,返回true;文件不存在或者正在被执行,返回false。   
        void deleteOnExit();//在程序退出时删除指定文件
3、判断
        boolean canExecute();//是否是可执行文件
        boolean exists();//文件是否存在
        boolean isFile();//是否是文件
        boolean isDirectory();//是否是文件夹
        boolean isHidden();//是否是隐藏文件
        boolean isAbsolute();//文件是否是绝对路径
记住:在判断文件对象是否是文件或者目录时,必须要判断该文件对象封装的内容是否存在。通过exists判断。
4、获取信息
        String getName();//获取文件名
        String getPath();
        //获取文件的相对路径(即创建的对象传入的参数是什么就获取到什么)
        String getParent();
        //获取文件父目录。返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。
        String getAbsolutePath();//获取文件的绝对路径     
        long lastModified();//返回文件最后一次被修改的时间
        long length();//返回文件长度
5、列出文件及文件过滤
        static File[] listRoots();//列出可用的文件系统根目录,即系统盘符
        String[] list();
        //列出当前目录下所有文件,包括隐藏。调用list方法的file对象必须是封装了一个目录。该目录还必须存在。
        String[] list(FilenameFilter filter);
        //返回一个字符串数组,获取目录中满足指定过滤器的文件或目录。
        //FilenameFilter:文件名过滤器,是一个接口,其中包含一个方法,accept(Filedir,String name),返回的是boolean型,对不符合条件的文件过滤掉。
        File[] listFiles();//返回一个抽象路径名数组,获取当前文件夹下的所有文件和文件夹
        File[] ListFiles(FilenameFilterfilter);//返回抽象路径名数组,获取目录中满足指定过滤器的文件或目录。
/* 
练习:用String[] list(FilenameFilter filter)方法获取一个目录下所有的.java文件,其他文件不要。 
思路:1、FilenameFilter是一个过滤器接口,用匿名内部类传入filter对象 
      2、复写FilenameFilter接口的accept(File file,String name)方法,并判断name是否是java文件 
      3、遍历String类型数组 
*/  
  
import java.io.*;  
class  GetJavaFile  
{  
    public static void main(String[] args)   
    {  
        File file=new File("E:\\Java Study\\Practice\\day07");  
        getJavaFile(file);  
    }  
    //获取一个目录下所有的.java文件方法  
    public static void getJavaFile(File dir)  
    {  
        //传入FilenameFilter匿名内部类子类对象,并复写accept方法  
        String[] javaFile=dir.list(new FilenameFilter()  
        {  
            public boolean accept(File dir,String name)  
            {  
                return name.endsWith(".java");//判断文件名是否是以.java结尾  
            }  
        });  
  
        System.out.println("len:"+javaFile.length);  
        //遍历数组  
        for (String s : javaFile )  
        {  
            System.out.println(s);  
        }  
    }  
}  


四、递归
1、定义
       当函数内每一次循环还可以调用本功能来实现,也就是函数自身调用自身。这种表现形式,或者编程手法,称为递归。
2、递归注意事项
        a、限定条件。是来结束循环调用,否则是死循环。
        b、注意递归的次数,尽量避免内存溢出。因为每次调用自身的时候都会先执行下一次调用自己的方法,所以会不断在栈内存中开辟新空间,次数过多,会导致内存溢出。
/* 
需求:列出指定目录下文件或文件夹,包含子目录,即列出指定目录下所有内容(带层次的)。 
 
分析,因为目录中还有目录,只有使用同一个列出目录功能的函数完成即可,在列出过程中出现的还是目录的话,还可以再调用本功能,这就是利用递归原理。 
 
*/  
import java.io.*;  
class  RecursionDemo  
{  
    public static void main(String[] args)   
    {  
        //关联指定路径  
        File dir=new File("e:\\Java Study\\Practice");  
          
        //列出关联路径中所有的.java文件  
        allFileList(dir,0);  
    }  
  
    //列出指定目录下的所以内容  
    public static void allFileList(File dir,int level)  
    {  
        //有层次的输出  
        System.out.println(getLevel(level)+dir);  
        level++;  
        File[] fileArr=dir.listFiles();//获取本目录下的所以文件和目录的抽象路径  
          
        //遍历  
        for (File file : fileArr)  
        {  
            if(file.isDirectory())  
            {  
                //如果目录下还是目录,则继续调用本函数  
                allFileList(file,level);  
            }  
            else  
                System.out.println(getLevel(level)+file);//显示(列出)文件  
        }     
    }  
  
    //带层次的列表  
    public static String getLevel(int level)  
    {  
        StringBuilder sb=new StringBuilder();  
        sb.append("|--");  
        //每多一级目录,就多输出指定字符  
        for (int x=level;x>0 ; x--)  
        {  
            //sb.append("|--");  
            sb.insert(0,"|  ");  
        }  
        return sb.toString();  
    }  
} 

/* 
删除一个带内容的目录。 
删除原理: 
在windows中,删除目录从里面往外面删除的。 
既然是从里往外删除。就需要用到递归。 
 
*/  
import java.io.*;  
class RemoveDir   
{  
    public static void main(String[] args)   
    {  
        //指定目录  
        File dir=new File("e:\\1");  
        //删除目录  
        removeDir(dir);  
  
    }  
  
    //删除传入目录  
    public static void removeDir(File dir)  
    {  
        File[] files=dir.listFiles();//列出目录下的所以文件和文件夹  
        //遍历  
        for (File file : files )  
        {  
            //如果还是目录且非隐藏  
            if(!file.isHidden()&&file.isDirectory())  
                removeDir(file);//继续删除目录里的内容  
            else  
                System.out.println(file.toString()+":-file-:"+file.delete());//删除文件  
        }  
        System.out.println(dir+":::dir:::"+dir.delete());//删除目录  
    }  
}  


/* 
练习: 
将一个指定目录下的java文件的绝对路径,存储到一个文本文件中。建立一个java文件列表的文件。 
思路: 
     1、对指定的目录进行递归。 
     2、获取递归过程所有的java文件的路径。 
     3、将这些路径存储到集合中。 
     4、将集合中的数据写入到一个文件中。 
*/  
import java.util.*;  
import java.io.*;  
  
class  JavaFileList  
{  
    public static void main(String[] args)   
    {  
        //指定目录  
        File dir=new File("e:/Java Study/Practice");  
          
        //定义一个List集合,用于存储.java文件的File对象  
        List<File> list =new ArrayList<File>();  
          
        //调用获取文件路径方法  
        fileToList(dir,list);  
          
        //指定写入文件  
        File file=new File(dir,"javafilelist.txt");  
        //调用写入文件方法  
        writeToFile(list,file);  
      
    }  
    //获取指定文件夹内的所有java文件的绝对路径,并存入集合中  
    public static void fileToList(File dir,List<File> list)  
    {  
        File[] files=dir.listFiles();//列出dir路径下的所以文件和目录,  
        //遍历  
        for (File file : files)  
        {  
            //如果是目录,则继续获取  
            if(file.isDirectory())  
            {  
                list.add(file.getAbsoluteFile());//把父目录路径也存入  
                fileToList(file,list);  
            }  
            //将是.java文件的绝对路径存入  
            else if(file.getName().endsWith(".java"))  
                list.add(file);  
        }  
    }  
  
    //将集合中元素写入到一个文本文件中  
    public static void writeToFile(List<File> list,File file)  
    {  
          
        BufferedWriter bw=null;  
              
        try  
        {   //使用字符流缓冲区对象关联写入的文件  
            bw=new BufferedWriter(new FileWriter(file));  
            for (File file0 : list )  
            {  
                bw.write(file0.getAbsolutePath());//写入  
                bw.newLine();//换行  
                bw.flush();//刷新  
            }  
        }  
        catch (IOException e)  
        {  
            throw new RuntimeException("写入文件失败");  
        }  
        finally  
        {  
            try  
            {  
                if(bw!=null)  
                    bw.close();//关流  
            }  
            catch (IOException e)  
            {  
                throw new RuntimeException("流资源关闭失败");  
            }  
        }  
    }  
}  



第二讲      Properties类
一、概述
1、Properties是Hashtable的子类,它具备Map集合的特点。而且它里面还有存储的键值对,都是字符串,无泛型定义。是集合中和IO技术相结合的集合容器。
2、特点:
        1)可用于键值对形式的配置文件
        2)在加载时,需要数据有固定的格式,常用的是:键=值

二、特有方法
1、设置
        Object setProperty(String key,String value);
        //设置键和值,调用Hashtable的方法put
2、获取
        String getProperty(String key);
        //指定key搜索value
        Set<String> stringPropertyName();
        //返回属性列表的键集,存入Set集合
3、加载流和存入流
        void load(InputStream ism);
        //从输入字节流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。
        void load(Reader reader);
        //从输入字符流中读取属性列表(键和元素对)。又称将流中的数据加载进集合。
        void list(PrintStream out);//将属性列表输出到指定的输出流
        void store(OutputStreamout,String comments);
        //对应load(InputStream )将属性列表(键值对)写入输出流。comments属性列表的描述。
        void store(Writerwriter, String comments);
        //对应load(Reader)将属性列表(键值对)写入输出流。comments属性列表的描述。
示例

/* 
练习:用于记录应用程序运行次数。如果使用次数已到,那么给出注册提示。 
     
分析: 
很容易想到的是:计数器。可是该计数器定义在程序中,随着该应用程序的退出,该计数器也在内存中消失了。 
所以要建立一个配置文件,用于记录该软件的使用次数。该配置文件使用键值对的形式。键值对数据是map集合。数据是以文件形式存储。使用io技术。那么map+io——>Properties。 
 
思路:1、用读取流关联文本信息文件。如果存在则读取,如果不存在,则创建 
      2、每次运行,将文件数据存入集合中,读取值,判断次数,如果小于等于5次,则次数增加1次,如果大于则输出提示信息。 
      3、将值小于等于5次的信息数据存入文件中 
*/  
import java.util.*;  
import java.io.*;  
  
class  RunCount  
{  
    public static void main(String[] args)throws IOException   
    {  
        int count=runCount();  
        if(count>5)//如果程序被使用了超过5次,则终止使用,并提示  
        {  
            System.out.println("次数到了,交钱!!!!!");  
            return ;  
        }  
        else  
            System.out.println("程序第"+count+"次Run!");  
    }  
    //获取程序运行的次数  
    public static int runCount()throws IOException  
    {  
        Properties ps=new Properties();//创建集合对象  
  
        File file=new File("info.ini");//将文件进行封装  
        if(!file.exists())//判断是否存在  
            file.createNewFile();  
        FileReader fr=new FileReader(file);//将文件于读取流进行关联  
          
        ps.load(fr);//加载流中的文件数据到集合中  
  
        int count=0;//定义计数器  
        String value=ps.getProperty("time");//获取次数值  
          
        if(value!=null)//如过值不等于null,则将其赋值给count  
        {  
            count=Integer.parseInt(value);  
        }  
        count++;//每启动一次自增  
        ps.setProperty("time",count+"");//将次数记录住集合  
  
        FileWriter fw=new FileWriter(file);  
        ps.store(fw,"");//将集合中的数据存入硬盘文件中  
          
        fr.close();//关流  
        fw.close();  
  
        return count;//返回程序启动的次数  
    }  
}  


第三讲    打印流
一、概述
        1、打印流包括:PrintStream和PrintWriter
        2、该流提供了打印方法,可将各种类型的数据都原样打印。

二、字节打印流:PrintStream
构造方法中可接收的参数类型:
        1、File对象。File
        2、字符串路径:String
        3、字符输出流:OutputStream

三、字符串打印流:PrintWriter
构造方法中可接受的参数类型
        1、File对象:File
        2、字符串路径:String
        3、字节输出流:OutputStream
        4、字符输出流:Writer
示例
import java.io.*;  
  
class  PrintStreamDemo  
{  
    public static void main(String[] args) throws IOException  
    {  
        //键盘录入  
        BufferedReader bufr =   
            new BufferedReader(new InputStreamReader(System.in));  
  
        //打印流关联文件,自动刷新  
        PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);  
  
        String line = null;  
  
        while((line=bufr.readLine())!=null)  
        {  
            if("over".equals(line))//结束字符  
                break;  
            out.println(line.toUpperCase());  
            //out.flush();  
        }  
          
        //关流  
        out.close();  
        bufr.close();  
  
    }     
}  


第四讲    序列流
一、概述
1、SequenceInputStream对多个流进行合并。也被称为合并流。
2、常用构造函数
        SequenceInputStream(Enumeration<?extends FileInputStream> e)

二、常见合并多个流文件步骤
        1、创建集合,并将流对象添加进集合
        2、创建Enumeration对象,将集合元素加入。
        3、创建SequenceInputStream对象,合并流对象
        4、创建写入流对象,FileOutputStream关联写入文件
        5、利用SequenceInputStream对象和FileOutputStream对象读数据进行反复读写操作。
/* 
SequenceInputStream 
合并流 
需求:将三个文本文件中的数据合并到一个文本文件中 
思路:1、创建一个Vector集合,将三个文本文件字节流添加到集合中 
      2、创建Enumeration对象,创建SequnceInputStream对象关联Enumeration 
      3、输出流关联新文本文件 
      4、反复读写操作 
*/  
import java.util.*;  
import java.io.*;  
  
class  SequenceInputStreamDemo  
{  
    public static void main(String[] args)throws IOException  
    {  
        Vector<InputStream> ve=new Vector<InputStream>();//创建vector集合,并添加相关流对象  
        ve.add(new FileInputStream("1.txt"));  
        ve.add(new FileInputStream("2.txt"));  
        ve.add(new FileInputStream("3.txt"));  
  
        Enumeration<InputStream> en=ve.elements();//创建枚举对象  
        SequenceInputStream sis=new SequenceInputStream(en);//合并流  
  
        FileOutputStream fos=new FileOutputStream("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();  
    }  
}  

/* 
切割文件 
需求:将一个mp3文件按1M大小切割成几部分 
思路:1、使用文件字节流关联mp3文件 
      2、定义一个容器存储1M大小的数据,当存储满时,写入一个新文件中 
 
*/  
import java.util.*;  
import java.io.*;  
  
class  SplitFile  
{  
    public static void main(String[] args) throws IOException  
    {  
        //指定要切割的文件  
        File file=new File("C:\\Users\\asus\\Desktop\\苏芮 - 一样的月光.mp3");  
        //将指定文件进行切割  
        splitFile(file);  
  
        //指定要合并到的文件  
        File file1=new File("E:\\Java Study\\Practice\\day20\\splitFile\\一样的月光.mp3");  
        //将部分文件进行合并指定文件中  
        merge(file1);  
  
    }  
    //接收一个文件,将其按1M大小进行切割  
    public static void splitFile(File file)throws IOException  
    {  
        //关联要切割的文件  
        BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));  
          
        BufferedOutputStream bos=null;  
  
        //定义1M大小存储容器  
        byte[] buf=new byte[1024*1024];  
        int len=0,x=0;  
        while ((len=bis.read(buf))!=-1)  
        {  
            //每满1M就写入一个新文件中  
            bos=new BufferedOutputStream(new FileOutputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+(++x)+".part"));  
            bos.write(buf,0,len);  
            bos.close();//没写完一个文件要记得关流  
        }  
        //关流  
        bis.close();  
    }  
  
    //将部分文件合并为一个可执行文件  
    public static void merge(File file)throws IOException  
    {  
        //定义一个集合存储这些部分文件关联路径数据  
        ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();  
  
        for (int x=1;x<=6 ; x++)  
        {  
            al.add(new FileInputStream("E:\\Java Study\\Practice\\day20\\splitFile\\"+x+".part"));  
        }  
          
        //因为Enumeration是Vector特有的迭代方法,所以这里创建一个Enumeration类型的匿名内部类  
        final  ListIterator<FileInputStream> it=al.listIterator();  
        Enumeration<FileInputStream> en=new Enumeration<FileInputStream>()  
        {  
            public boolean hasMoreElements()  
            {  
                return it.hasNext();  
            }  
  
            public FileInputStream nextElement()  
            {  
                return it.next();  
            }  
        };  
  
        //关联枚举对象  
        SequenceInputStream sis=new SequenceInputStream(en);  
  
        //将合并的文件数据写入指定文件中  
        FileOutputStream fos=new FileOutputStream(file);  
          
        //定义临时存储数据的数组  
        byte[] buf=new byte[1024];  
        int len=0;  
        while((len=sis.read(buf))!=-1)  
        {  
            fos.write(buf,0,len);//写数据  
        }  
  
        //关流  
        fos.close();  
        sis.close();  
  
    }  
  
} 

第五讲 对象的序列化
目的:将一个具体的对象进行持久化,写入到硬盘上。
注意:静态数据不能被序列化,因为静态数据不在堆内存中,是存储在静态方法区中。

如何将非静态的数据不进行序列化?
用transient 关键字修饰此变量即可。

Serializable:用于启动对象的序列化功能,可以强制让指定类具备序列化功能,该接口中没有成员,这是一个标记接口。这个标记接口用于给序列化类提供UID。这个uid是依据类中的成员的数字签名进行运算获取的。如果不需要自动获取一个uid,可以在类中手动指定一个名称为serialVersionUID id号。依据编译器的不同,或者对信息的高度敏感性。最好每一个序列化的类都进行手动显式的UID的指定。
import java.io.*;
class Person implements Serializable{
	private static final long serialVersionUID = 42L;
	private transient String name;//用transient修饰后name将不会进行序列化
	public int age;
	Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	public String toString(){
		return name+"::"+age;
	}
}

import java.io.*;
class ObjectStream {
	public static void main(String[] args) throws Exception{
		writeObj();
		readObj();
	}
	public static void readObj()throws Exception{
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
		Object obj = ois.readObject();//读取一个对象。
		System.out.println(obj.toString());
	}
	public static void writeObj()throws IOException{
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
		oos.writeObject(new Person("lisi",25)); //写入一个对象。
		oos.close();
	}
}


第六讲 管道流
管道读取流和管道写入流可以像管道一样对接上,管道读取流可以读取管道写入流写入的数据。
注意:需要加入多线程技术,因为单线程,先执行read,会发生死锁,因为read方法是阻塞式的,没有数据的read方法会让线程等待。
import java.io.*;

class Read implements Runnable
{
	private PipedInputStream in;
	Read(PipedInputStream in)
	{
		this.in = in;
	}
	public void run()
	{
		try
		{
			byte[] buf = new byte[1024];

			System.out.println("读取前。。没有数据阻塞");
			int len = in.read(buf);
			System.out.println("读到数据。。阻塞结束");



			String s= new String(buf,0,len);

			System.out.println(s);

			in.close();

		}
		catch (IOException e)
		{
			throw new RuntimeException("管道读取流失败");
		}
	}
}

class Write implements Runnable
{
	private PipedOutputStream out;
	Write(PipedOutputStream out)
	{
		this.out = out;
	}
	public void run()
	{
		try
		{
			System.out.println("开始写入数据,等待6秒后。");
			Thread.sleep(6000);
			out.write("一大波测试数据".getBytes());
			out.close();
		}
		catch (Exception e)
		{
			throw new RuntimeException("管道输出流失败");
		}
	}
}

class  PipedStreamDemo
{
	public static void main(String[] args) throws IOException
	{

		PipedInputStream in = new PipedInputStream();
		PipedOutputStream out = new PipedOutputStream();
		in.connect(out);

		Read r = new Read(in);
		Write w = new Write(out);
		new Thread(r).start();
		new Thread(w).start();


	}
}

第七讲 RandomAccessFile
特点:
1:该对象即可读取,又可写入。
2:该对象中的定义了一个大型的byte数组,通过定义指针来操作这个数组。
3:可以通过该对象的getFilePointer()获取指针的位置,通过seek()方法设置指针的位置。
4:该对象操作的源和目的必须是文件。
5:其实该对象内部封装了字节读取流和字节写入流。
注意:实现随机访问,最好是数据有规律。
import java.io.*;
class RandomAccessFileDemo{
	public static void main(String[] args) throws IOException{
		write();
	//	read();
	//	randomWrite();
	}
	//随机写入数据,可以实现已有数据的修改。
	public static void randomWrite()throws IOException{
		RandomAccessFile raf = new RandomAccessFile("random.txt","rw");
		raf.seek(8*4);
		System.out.println("pos :"+raf.getFilePointer());
		raf.write("张三".getBytes());
		raf.writeInt(102);
		raf.close();
	}
	public static void read()throws IOException{
		RandomAccessFile raf = new RandomAccessFile("random.txt","r");//只读模式。
		//指定指针的位置。
		raf.seek(8*1);//实现随机读取文件中的数据。注意:数据最好有规律。
		System.out.println("pos1 :"+raf.getFilePointer());
		byte[] buf = new byte[4];
		raf.read(buf);
		String name = new String(buf);
		int age = raf.readInt();
		System.out.println(name+"::"+age);
		System.out.println("pos2 :"+raf.getFilePointer());
		raf.close();
	}
	public static void write()throws IOException{
		//rw:当这个文件不存在,会创建该文件。当文件已存在,不会创建。所以不会像输出流一样覆盖。
		RandomAccessFile raf = new RandomAccessFile("random.txt","rw");//rw读写模式
		//往文件中写入人的基本信息,姓名,年龄。
		raf.write("张三".getBytes());
		raf.writeInt(97);
		raf.close();
	}
}


第八讲 以流的读写思想来操作数组
ByteArrayInputStream:源:内存
ByteArrayOutputStream:目的:内存。
这两个流对象不涉及底层资源调用,操作的都是内存中数组,所以不需要关闭。
直接操作字节数组就可以了,为什么还要把数组封装到流对象中呢?
因为数组本身没有方法,只有一个length属性。为了便于数组的操作,将数组进行封装,对外提供方法操作数组中的元素。
/*
用流的读写思想来操作数据。
*/
import java.io.*;
class ByteArrayStream 
{
	public static void main(String[] args) 
	{
		//数据源。在构造的时候,需要接收数据源。而且数据源是一个字节数组。
		ByteArrayInputStream bis = new ByteArrayInputStream("ABCDEFD".getBytes());

		//数据目的。在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。
		ByteArrayOutputStream bos = new ByteArrayOutputStream();

		int by = 0;

		while((by=bis.read())!=-1)
		{
			bos.write(by);
		}
		System.out.println(bos.size());
		System.out.println(bos.toString());

	//	bos.writeTo(new FileOutputStream("a.txt"));

	}
}

第七讲 Encoding
gbk编码,一个汉字占2个字节
utf-8编码,一个汉字占3个字节
联通这两个字符的特殊性
联通----用gbk编码的二进制四个字节数据为:
11000001
10101010
11001101
10101000
恰恰符合utf-8中 110 10 110 10打头的字符编码格式,notepad.exe在解码时会默认采用utf-8解码,导致解码出错。
import java.io.*;
import java.util.*;
class Demo{
		public static void main(String[] args)throws IOException{
		/*	write();
			write_utf8();
			write_gbk();*/
		//	read();
			byte[] b = "联通".getBytes();
			for(int i=0; i<b.length; i++){				
				System.out.println(Integer.toBinaryString(b[i] & 0xff));
			}
		
		}
		public static void write()throws IOException{
			OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("moren.txt"));
			ow.write("你好");
			ow.close();
		}
		
		public static void write_utf8()throws IOException{
			OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("utf-8.txt"),"utf-8");
			ow.write("你好");
			ow.close();
		}
		public static void write_gbk()throws IOException{
			OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
			ow.write("你好");
			ow.close();
		}
		
		public static void read()throws IOException{
			InputStreamReader in = new InputStreamReader(new FileInputStream("gbk.txt"),"utf-8");
			char[] c = new char[10];
			int len = in.read(c);
			String s = new String(c, 0, len);
			in.close();
			System.out.println(s);
		}
}


  • 大小: 26.9 KB
分享到:
评论

相关推荐

    Java IO应届生培训讲义

    Java IO应届生培训讲义是一份面向刚毕业的大学生进行Java IO相关知识的培训资料,它涵盖了Java IO的基础知识、不同的IO模型以及Java中的BIO、NIO和AIO高级IO类库。下面详细解释这些知识点: 1. 用户空间和内核空间 ...

    Java IO知识点

    Java IO(Input/Output)是Java编程语言中用于处理输入输出操作的重要部分,涉及文件、网络、内存等数据传输。本文将深入探讨Java IO的基本概念、分类、选择流的策略以及常用的流类型。 首先,File类是Java IO的...

    java IO教程,java IO教程,java IO教程

    java IO教程,java IO教程,java IO教程,java IO教程java IO教程java IO教程java IO教程java IO教程,java IO教程java IO教程java IO教程java IO教程java IO教程,java IO教程,java IO教程,java IO教程,java IO...

    java io 结构图

    Java IO(Input/Output)是Java编程语言中用于处理输入和输出操作的重要组成部分。它提供了一整套类库,使得开发者能够有效地读取和写入数据到不同的源和目标,如文件、网络、内存缓冲区等。Java IO体系结构设计得...

    Java IO_NIO

    Java IO(Input/Output)是Java编程语言中用于处理输入输出操作的基础框架,它提供了丰富的类库,使得程序能够与各种设备、文件、网络进行数据交互。然而,传统的IO模型在处理大量并发连接时表现出效率较低的问题,...

    java IO.chm

    《Java IO.chm》是一个关于Java输入/输出(IO)技术的压缩文件,其中包含了丰富的资料,适合开发者深入理解和学习Java IO系统。这篇详细的总结将围绕Java IO体系结构、核心类、流的概念、缓冲区、转换流、字符集、...

    Java教程之javaIO详解

    Java IO 详解 Java IO(Input/Output)是 Java 语言中用于处理输入输出操作的类库,提供了大量的类和方法来实现文件、网络、字节流等方面的输入输出操作。下面对 Java IO 中的重要知识点进行详细说明。 一、File ...

    Java IO处理类的汇总

    Java IO处理类是Java平台中用于输入输出操作的核心部分,它允许程序与各种类型的输入源(如文件、网络连接)以及输出目标(如显示器、打印机)进行交互。本篇文章将全面解析Java IO处理类,包括基本概念、常用类库、...

    Java IO 编程集合

    Java IO编程是Java平台中处理输入输出操作的重要组成部分,它提供了丰富的类库,使得开发者能够高效地进行数据的读取、写入、流的管理和转换。在这个集合中,我们主要探讨的是Java IO在文件读写方面的实践应用。 一...

    JAVA IO流技术

    Java IO流技术是Java平台中用于处理输入输出的重要机制,其核心在于数据的传输,从数据源到程序或从程序到目的地。在Java中,流分为两大类:输入流(InputStream、Reader)和输出流(OutputStream、Writer)。输入流...

    Java IO 使用例

    在“JavaIODemo”这个示例中,可能会包含以上提到的一些或全部Java IO操作的代码实例,通过这些实例,我们可以学习如何在实际项目中应用Java IO API。实践是掌握Java IO的最佳方式,通过对这些示例的分析和运行,...

    java io.pdf

    Java IO(Input/Output)是Java编程语言中用于处理输入和输出操作的重要组成部分。它提供了丰富的类库,允许程序员在程序之间传输数据,包括从文件、网络、内存缓冲区到其他程序或系统组件。Java IO API是Java平台的...

    JavaIO流详解归纳.pdf

    JavaIO流详解归纳 Java 的核心库 java.io 提供了全面的 IO 接口,包括文件读写、标准设备输出等。Java 中 IO 是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。在项目开发中,IO 是非常...

    javaIo操作的基础代码

    Java IO操作是Java编程中的重要组成部分,主要用于处理输入和输出数据。在Java中,IO操作涉及到文件、字节流、字符流以及管道流等多个概念。下面将详细解释这些知识点。 首先,我们来看“文件类”。在Java中,`java...

    Java IO 与 装饰模式

    Java IO 与 装饰模式 在Java编程中,输入输出(IO)处理是程序设计中的重要组成部分,用于读取、写入和处理数据。Java IO库提供了一整套类来支持各种类型的输入输出操作,包括文件、网络、内存等。而装饰模式是一种...

    JAVA IO流缓冲字节流缓冲字符流等流经典代码示例加注释总结.rar

    2、常用21个IO流:FileWriter、FileReader、...3、JAVA IO流经典代码示例,示例从易到难。代码功能涉及字节、字符、字符串、文本文件、图片、音频、视频。演示错误用法和经典用法。 4、代码的结构可查看README文件。

    java io流 案例

    Java IO流是Java平台中的重要组成部分,用于处理输入和输出操作。它允许程序与外部设备如硬盘、网络、内存等进行数据传输。IO流的概念基于流(Stream)模型,数据以字节或字符序列的形式流动。Java IO库提供了丰富的...

    java io流学习笔记1

    Java IO流是Java编程语言中处理输入输出操作的重要部分,尤其在数据传输、文件读写等方面发挥着核心作用。本文将深入探讨Java IO流的基本概念、类型以及它们在实际开发中的应用。 首先,理解IO流的基本概念至关重要...

    Java IO 工具类大全

    Java IO(Input/Output)是Java平台中处理输入与输出数据的核心部分,它提供了丰富的类库,使得开发者能够高效地进行文件、网络、内存以及其他I/O流的操作。本篇文章将全面解析Java IO工具类,帮助你理解并掌握其在...

Global site tag (gtag.js) - Google Analytics