Java基础知识之IO流(二)

来源:互联网 发布:淘宝女装行业退款率 编辑:程序博客网 时间:2024/05/17 04:56


一、IO流练习

(1).复制文本文件/*  复制文本文件    分析:  复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。  通过该原理,我们知道我们应该采用字符流更方便一些。  而字符流有5种方式,所以做这个题目我们有5种方式。推荐掌握第5种。  数据源:  c:\\a.txt -- FileReader -- BufferdReader  目的地: d:\\b.txt -- FileWriter -- BufferedWriter */public class CopyFileDemo {public static void main(String[] args) throws IOException {String srcString = "c:\\a.txt";String destString = "d:\\b.txt";// method1(srcString, destString);// method2(srcString, destString);// method3(srcString, destString);// method4(srcString, destString);method5(srcString, destString);}// 字符缓冲流一次读写一个字符串private static void method5(String srcString, String destString)throws IOException {BufferedReader br = new BufferedReader(new FileReader(srcString));BufferedWriter bw = new BufferedWriter(new FileWriter(destString));String line = null;while ((line = br.readLine()) != null) {bw.write(line);bw.newLine();bw.flush();}bw.close();br.close();}// 字符缓冲流一次读写一个字符数组private static void method4(String srcString, String destString)throws IOException {BufferedReader br = new BufferedReader(new FileReader(srcString));BufferedWriter bw = new BufferedWriter(new FileWriter(destString));char[] chs = new char[1024];int len = 0;while ((len = br.read(chs)) != -1) {bw.write(chs, 0, len);}bw.close();br.close();}// 字符缓冲流一次读写一个字符private static void method3(String srcString, String destString)throws IOException {BufferedReader br = new BufferedReader(new FileReader(srcString));BufferedWriter bw = new BufferedWriter(new FileWriter(destString));int ch = 0;while ((ch = br.read()) != -1) {bw.write(ch);}bw.close();br.close();}// 基本字符流一次读写一个字符数组private static void method2(String srcString, String destString)throws IOException {FileReader fr = new FileReader(srcString);FileWriter fw = new FileWriter(destString);char[] chs = new char[1024];int len = 0;while ((len = fr.read(chs)) != -1) {fw.write(chs, 0, len);}fw.close();fr.close();}// 基本字符流一次读写一个字符private static void method1(String srcString, String destString)throws IOException {FileReader fr = new FileReader(srcString);FileWriter fw = new FileWriter(destString);int ch = 0;while ((ch = fr.read()) != -1) {fw.write(ch);}fw.close();fr.close();}}(2).复制图片550 113 133/*  复制图片    分析:  复制数据,如果我们知道用记事本打开并能够读懂,就用字符流,否则用字节流。  通过该原理,我们知道我们应该采用字节流。  而字节流有4种方式,所以做这个题目我们有4种方式。推荐掌握第4种。    数据源:  c:\\a.jpg -- FileInputStream -- BufferedInputStream  目的地  d:\\b.jpg -- FileOutputStream -- BufferedOutputStream */public class CopyImageDemo {public static void main(String[] args) throws IOException {// 使用File对象做为参数File srcFile = new File("c:\\a.jpg");File destFile = new File("d:\\b.jpg");// method1(srcFile, destFile);// method2(srcFile, destFile);// method3(srcFile, destFile);method4(srcFile, destFile);}// 字节缓冲流一次读写一个字节数组private static void method4(File srcFile, File destFile) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));byte[] bys = new byte[1024];int len = 0;while ((len = bis.read(bys)) != -1) {bos.write(bys, 0, len);}bos.close();bis.close();}// 字节缓冲流一次读写一个字节private static void method3(File srcFile, File destFile) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));int by = 0;while ((by = bis.read()) != -1) {bos.write(by);}bos.close();bis.close();}// 基本字节流一次读写一个字节数组private static void method2(File srcFile, File destFile) throws IOException {FileInputStream fis = new FileInputStream(srcFile);FileOutputStream fos = new FileOutputStream(destFile);byte[] bys = new byte[1024];int len = 0;while ((len = fis.read(bys)) != -1) {fos.write(bys, 0, len);}fos.close();fis.close();}// 基本字节流一次读写一个字节private static void method1(File srcFile, File destFile) throws IOException {FileInputStream fis = new FileInputStream(srcFile);FileOutputStream fos = new FileOutputStream(destFile);int by = 0;while ((by = fis.read()) != -1) {fos.write(by);}fos.close();fis.close();}}(3).把ArrayList集合中的字符串数据存储到文本文件/*  分析:  ArrayList集合里存储的是字符串。  遍历ArrayList集合,把数据获取到。  然后存储到文本文件中。  文本文件说明使用字符流。    数据源:  ArrayList<String> -- 遍历得到每一个字符串数据  目的地:  a.txt -- FileWriter -- BufferedWriter */public class ArrayListToFileDemo {public static void main(String[] args) throws IOException {// 封装数据与(创建集合对象)ArrayList<String> array = new ArrayList<String>();array.add("hello");array.add("world");array.add("java");// 封装目的地BufferedWriter bw = new BufferedWriter(new FileWriter("a.txt"));// 遍历集合for (String s : array) {// 写数据bw.write(s);bw.newLine();bw.flush();}// 释放资源bw.close();}}(4).从文本文件中读取数据(每一行为一个字符串数据)到集合中,并遍历集合/*  分析:  数据源是一个文本文件。  目的地是一个集合。  而且元素是字符串。    数据源:  b.txt -- FileReader -- BufferedReader  目的地:  ArrayList<String> */public class FileToArrayListDemo {public static void main(String[] args) throws IOException {// 封装数据源BufferedReader br = new BufferedReader(new FileReader("b.txt"));// 封装目的地(创建集合对象)ArrayList<String> array = new ArrayList<String>();// 读取数据存储到集合中String line = null;while ((line = br.readLine()) != null) {array.add(line);}// 释放资源br.close();// 遍历集合for (String s : array) {System.out.println(s);}}}(5).复制单级文件夹/*    数据源:e:\\demo  目的地:e:\\test    分析:  A:封装目录  B:获取该目录下的所有文本的File数组  C:遍历该File数组,得到每一个File对象  D:把该File进行复制 */public class CopyFolderDemo {public static void main(String[] args) throws IOException {// 封装目录File srcFolder = new File("e:\\demo");// 封装目的地File destFolder = new File("e:\\test");// 如果目的地文件夹不存在,就创建if (!destFolder.exists()) {destFolder.mkdir();}// 获取该目录下的所有文本的File数组File[] fileArray = srcFolder.listFiles();// 遍历该File数组,得到每一个File对象for (File file : fileArray) {String name = file.getName(); // e.mp3File newFile = new File(destFolder, name); // e:\\test\\e.mp3copyFile(file, newFile);}}private static void copyFile(File file, File newFile) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));byte[] bys = new byte[1024];int len = 0;while ((len = bis.read(bys)) != -1) {bos.write(bys, 0, len);}bos.close();bis.close();}}(6).复制指定目录下的指定文件,并修改后缀名。/*  指定的文件是:.java文件。  指定的后缀名是:.jad  指定的目录是:jad    数据源:e:\\java\\A.java  目的地:e:\\jad\\A.jad    分析:  A:封装目录  B:获取该目录下的java文件的File数组  C:遍历该File数组,得到每一个File对象  D:把该File进行复制  E:在目的地目录下改名 */public class CopyFolderDemo {public static void main(String[] args) throws IOException {// 封装目录File srcFolder = new File("e:\\java");// 封装目的地File destFolder = new File("e:\\jad");// 如果目的地目录不存在,就创建if (!destFolder.exists()) {destFolder.mkdir();}// 获取该目录下的java文件的File数组File[] fileArray = srcFolder.listFiles(new FilenameFilter() {@Overridepublic boolean accept(File dir, String name) {return new File(dir, name).isFile() && name.endsWith(".java");}});// 遍历该File数组,得到每一个File对象for (File file : fileArray) {String name = file.getName();File newFile = new File(destFolder, name);copyFile(file, newFile);}// 在目的地目录下改名File[] destFileArray = destFolder.listFiles();for (File destFile : destFileArray) {String name =destFile.getName(); //DataTypeDemo.javaString newName = name.replace(".java", ".jad");//DataTypeDemo.jadFile newFile = new File(destFolder,newName);destFile.renameTo(newFile);}}private static void copyFile(File file, File newFile) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));byte[] bys = new byte[1024];int len = 0;while ((len = bis.read(bys)) != -1) {bos.write(bys, 0, len);}bos.close();bis.close();}}(7).复制多极文件夹/*  数据源:E:\Java\day21\code\demos  目的地:E:\\    分析:  A:封装数据源File  B:封装目的地File  C:判断该File是文件夹还是文件  a:是文件夹  就在目的地目录下创建该文件夹  获取该File对象下的所有文件或者文件夹File对象  遍历得到每一个File对象  回到C  b:是文件  就复制(字节流) */public class CopyFoldersDemo {public static void main(String[] args) throws IOException {// 封装数据源FileFile srcFile = new File("E:\\Java\\day21\\code\\demos");// 封装目的地FileFile destFile = new File("E:\\");// 复制文件夹的功能copyFolder(srcFile, destFile);}private static void copyFolder(File srcFile, File destFile)throws IOException {// 判断该File是文件夹还是文件if (srcFile.isDirectory()) {// 文件夹File newFolder = new File(destFile, srcFile.getName());newFolder.mkdir();// 获取该File对象下的所有文件或者文件夹File对象File[] fileArray = srcFile.listFiles();for (File file : fileArray) {copyFolder(file, newFolder);}} else {// 文件File newFile = new File(destFile, srcFile.getName());copyFile(srcFile, newFile);}}private static void copyFile(File srcFile, File newFile) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcFile));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));byte[] bys = new byte[1024];int len = 0;while ((len = bis.read(bys)) != -1) {bos.write(bys, 0, len);}bos.close();bis.close();}}(8).键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低存入文本文件public class Student {// 姓名private String name;// 语文成绩private int chinese;// 数学成绩private int math;// 英语成绩private int english;public Student() {super();}public Student(String name, int chinese, int math, int english) {super();this.name = name;this.chinese = chinese;this.math = math;this.english = english;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getChinese() {return chinese;}public void setChinese(int chinese) {this.chinese = chinese;}public int getMath() {return math;}public void setMath(int math) {this.math = math;}public int getEnglish() {return english;}public void setEnglish(int english) {this.english = english;}public int getSum() {return this.chinese + this.math + this.english;}}/*   分析:  A:创建学生类  B:创建集合对象  TreeSet<Student>  C:键盘录入学生信息存储到集合  D:遍历集合,把数据写到文本文件 */public class StudentDemo {public static void main(String[] args) throws IOException {// 创建集合对象TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {@Overridepublic int compare(Student s1, Student s2) {int num = s2.getSum() - s1.getSum();int num2 = num == 0 ? s1.getChinese() - s2.getChinese() : num;int num3 = num2 == 0 ? s1.getMath() - s2.getMath() : num2;int num4 = num3 == 0 ? s1.getEnglish() - s2.getEnglish() : num3;int num5 = num4 == 0 ? s1.getName().compareTo(s2.getName()): num4;return num5;}});// 键盘录入学生信息存储到集合for (int x = 1; x <= 5; x++) {Scanner sc = new Scanner(System.in);System.out.println("请录入第" + x + "个的学习信息");System.out.println("姓名:");String name = sc.nextLine();System.out.println("语文成绩:");int chinese = sc.nextInt();System.out.println("数学成绩:");int math = sc.nextInt();System.out.println("英语成绩:");int english = sc.nextInt();// 创建学生对象Student s = new Student();s.setName(name);s.setChinese(chinese);s.setMath(math);s.setEnglish(english);// 把学生信息添加到集合ts.add(s);}// 遍历集合,把数据写到文本文件BufferedWriter bw = new BufferedWriter(new FileWriter("students.txt"));bw.write("学生信息如下:");bw.newLine();bw.flush();bw.write("姓名,语文成绩,数学成绩,英语成绩");bw.newLine();bw.flush();for (Student s : ts) {StringBuilder sb = new StringBuilder();sb.append(s.getName()).append(",").append(s.getChinese()).append(",").append(s.getMath()).append(",").append(s.getEnglish());bw.write(sb.toString());bw.newLine();bw.flush();}// 释放资源bw.close();System.out.println("学习信息存储完毕");}}(9).已知s.txt文件中有这样的一个字符串:“hcexfgijkamdnoqrzstuvwybpl”,请编写程序读取数据内容,把数据排序后写入ss.txt中。 /*      分析:  A:把s.txt这个文件给做出来  B:读取该文件的内容,存储到一个字符串中  C:把字符串转换为字符数组  D:对字符数组进行排序  E:把排序后的字符数组转换为字符串  F:把字符串再次写入ss.txt中 */public class StringDemo {public static void main(String[] args) throws IOException {// 读取该文件的内容,存储到一个字符串中BufferedReader br = new BufferedReader(new FileReader("s.txt"));String line = br.readLine();br.close();// 把字符串转换为字符数组char[] chs = line.toCharArray();// 对字符数组进行排序Arrays.sort(chs);// 把排序后的字符数组转换为字符串String s = new String(chs);// 把字符串再次写入ss.txt中BufferedWriter bw = new BufferedWriter(new FileWriter("ss.txt"));bw.write(s);bw.newLine();bw.flush();bw.close();}}(10).用Reader模拟BufferedReader的readLine()功能/*  readLine():一次读取一行,根据换行符判断是否结束,只返回内容,不返回换行符 */public class MyBufferedReader {private Reader r;public MyBufferedReader(Reader r) {this.r = r;}/*  思考:写一个方法,返回值是一个字符串。 */public String readLine() throws IOException {/*  要返回一个字符串,我们必须去看看r对象能够读取什么东西呢? 两个读取方法,一次读取一个字符或者一次读取一个字符数组  那么,我们要返回一个字符串,我们很容易想到字符数组比较好,但是就是这个数组的长度是多长呢?  根本就没有办法定义数组的长度,你定义多长都不合适。 所以,只能选择一次读取一个字符。  但是呢,这种方式的时候,我们再读取下一个字符的时候,上一个字符就丢失了 所以,我们又应该定义一个临时存储空间把读取过的字符给存储起来。  这个用谁比较和是呢?数组,集合,字符串缓冲区三个可供选择。  经过简单的分析,最终选择使用字符串缓冲区对象。并且使用的是StringBuilder */StringBuilder sb = new StringBuilder();// 做这个读取最麻烦的是判断结束,但是在结束之前应该是一直读取,直到-1int ch = 0;while ((ch = r.read()) != -1) { //104,101,108,108,111if (ch == '\r') {continue;}if (ch == '\n') {return sb.toString(); //hello} else {sb.append((char)ch); //hello}}// 为了防止数据丢失,判断sb的长度不能大于0if (sb.length() > 0) {return sb.toString();}return null;}/*  先写一个关闭方法 */public void close() throws IOException {this.r.close();}}/*  测试MyBufferedReader的时候,当作BufferedReader一样的使用 */public class MyBufferedReaderDemo {public static void main(String[] args) throws IOException {MyBufferedReader mbr = new MyBufferedReader(new FileReader("my.txt"));String line = null;while ((line = mbr.readLine()) != null) {System.out.println(line);}mbr.close();}}(11).自定义类模拟LineNumberReader的特有功能,获取每次读取数据的行号public class MyLineNumberReader extends MyBufferedReader {private Reader r;private int lineNumber = 0;public MyLineNumberReader2(Reader r) {super(r);}public int getLineNumber() {return lineNumber;}public void setLineNumber(int lineNumber) {this.lineNumber = lineNumber;}@Overridepublic String readLine() throws IOException {lineNumber++;return super.readLine();}}public class MyLineNumberReaderTest {public static void main(String[] args) throws IOException {MyLineNumberReader mlnr = new MyLineNumberReader(new FileReader("my.txt"));String line = null;while ((line = mlnr.readLine()) != null) {System.out.println(mlnr.getLineNumber() + ":" + line);}mlnr.close();}}


二、其他流
1.操作基本数据类型
可以读写基本数据类型的数据
 数据输入流:DataInputStream
  DataInputStream(InputStream in)
 数据输出流:DataOutputStream
  DataOutputStream(OutputStream out) 


public class DataStreamDemo {public static void main(String[] args) throws IOException {//write();read();}private static void read() throws IOException {// DataInputStream(InputStream in)// 创建数据输入流对象DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt"));// 读数据byte b = dis.readByte();short s = dis.readShort();int i = dis.readInt();long l = dis.readLong();float f = dis.readFloat();double d = dis.readDouble();char c = dis.readChar();boolean bb = dis.readBoolean();// 释放资源dis.close();System.out.println(b);System.out.println(s);System.out.println(i);System.out.println(l);System.out.println(f);System.out.println(d);System.out.println(c);System.out.println(bb);}private static void write() throws IOException {// DataOutputStream(OutputStream out)// 创建数据输出流对象DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt"));// 写数据了dos.writeByte(10);dos.writeShort(100);dos.writeInt(1000);dos.writeLong(10000);dos.writeFloat(12.34F);dos.writeDouble(12.56);dos.writeChar('a');dos.writeBoolean(true);// 释放资源dos.close();}}

2.内存操作流
操作字节数组
ByteArrayInputStream
ByteArrayOutputStream
操作字符数组
CharArrayReader 
CharArrayWriter
操作字符串
StringReader
StringWriter
内存操作流一般用于处理临时信息,因为临时信息不需要保存,使用后就可以删除。
ByteArrayInputStream 在构造的时候,需要接收数据源,而且数据源是一个字节数组。
ByteArrayOutputStream 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组,这就是数据目的地。
因为这两个流对象都是操作数组,并没有使用系统资源,所以不用进行close()关闭。

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



3.打印流概述
字节流打印流
字符打印流
 打印流特点
只能操作目的地,不能操作数据。
可以操作任意类型的数据。
  如果启用了自动刷新,在调用println()方法的时候,能够换行并刷新
  该流是可以直接操作文本文件的。
  看API,查流对象的构造方法,如果同时有File类型和String类型的参数,一般来说就是可以直接操作文件的。




  1:可以操作任意类型的数据。
  print()
  println()
  2:启动自动刷新
  PrintWriter pw = new PrintWriter(new FileWriter("pw.txt"), true);
  还是应该调用println()的方法才可以
  这个时候不仅仅自动刷新了,还实现了数据的换行。
  
  println()
  其实等价于于:
  bw.write();
  bw.newLine();
  bw.flush();
/*  需求:DataStreamDemo.java复制到Copy.java中  数据源:  DataStreamDemo.java -- 读取数据 -- FileReader -- BufferedReader  目的地:  Copy.java -- 写出数据 -- FileWriter -- BufferedWriter -- PrintWriter */public class CopyFileDemo {public static void main(String[] args) throws IOException {// 封装数据源BufferedReader br = new BufferedReader(new FileReader("Demo.java"));// 封装目的地PrintWriter pw = new PrintWriter(new FileWriter("Copy.java"), true);String line = null;while((line=br.readLine())!=null){pw.println(line);}pw.close();br.close();}}

4.标准输入输出流
System类中的字段:in,out。
它们各代表了系统标准的输入和输出设备。
默认输入设备是键盘,输出设备是显示器。
System.in的类型是InputStream.
System.out的类型是PrintStream是OutputStream的子类FilterOutputStream 的子类.


  System类中的两个成员变量:
public static final InputStream in “标准”输入流。
public static final PrintStream out “标准”输出流。
 
InputStream is = System.in;
PrintStream ps = System.out;
 
System.in 标准输入流。是从键盘获取数据的
键盘录入数据:
A:main方法的args接收参数。
java HelloWorld hello world java
B:Scanner(JDK5以后的)
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int x = sc.nextInt()
C:通过字符缓冲流包装标准输入流实现
  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));


输出语句的原理和如何使用字符流输出数据
A:原理
System.out.println("helloworld");

PrintStream ps = System.out;
ps.println("helloworld");
B:把System.out用字符缓冲流包装一下使用
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
5.随机访问流
  RandomAccessFile类不属于流,是Object类的子类。
  但它融合了InputStream和OutputStream的功能。
  支持对文件的随机访问读取和写入。
public RandomAccessFile(String name,String mode):第一个参数是文件路径,第二个参数是操作文件的模式。
  模式有四种,我们最常用的一种叫"rw",这种方式表示我既可以写数据,也可以读取数据 
 

public class RandomAccessFileDemo {public static void main(String[] args) throws IOException {// write();read();}private static void read() throws IOException {// 创建随机访问流对象RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");int i = raf.readInt();System.out.println(i);// 该文件指针可以通过 getFilePointer方法读取,并通过 seek 方法设置。System.out.println("当前文件的指针位置是:" + raf.getFilePointer());char ch = raf.readChar();System.out.println(ch);System.out.println("当前文件的指针位置是:" + raf.getFilePointer());String s = raf.readUTF();System.out.println(s);System.out.println("当前文件的指针位置是:" + raf.getFilePointer());// 我不想重头开始了,我就要读取a,怎么办呢?raf.seek(4);ch = raf.readChar();System.out.println(ch);}private static void write() throws IOException {// 创建随机访问流对象RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");// 怎么玩呢?raf.writeInt(100);raf.writeChar('a');raf.writeUTF("中国");raf.close();}}

6.合并流
SequenceInputStream概述
SequenceInputStream类可以将多个输入流串流在一起,合并为一个输入流,因此,该流也被称为合并流。
SequenceInputStream的构造方法
SequenceInputStream(InputStream s1, InputStream s2)  :将两个文件写入一个文件中
SequenceInputStream(Enumeration<? extends InputStream> e)

把多个文件的内容写入到一个文本文件

// 需求:把下面的三个文件的内容复制到Copy.java中public class SequenceInputStreamDemo2 {public static void main(String[] args) throws IOException {// ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java// SequenceInputStream(Enumeration e)// Enumeration<E> elements()Vector<InputStream> v = new Vector<InputStream>();InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");InputStream s2 = new FileInputStream("CopyFileDemo.java");InputStream s3 = new FileInputStream("DataStreamDemo.java");v.add(s1);v.add(s2);v.add(s3);Enumeration<InputStream> en = v.elements();SequenceInputStream sis = new SequenceInputStream(en);BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("Copy.java"));// 按照以前怎么读写,现在还是怎么读写byte[] bys = new byte[1024];int len = 0;while ((len = sis.read(bys)) != -1) {bos.write(bys, 0, len);}bos.close();sis.close();}}
7.序列化流


序列化流  :把对象按照流一样的方式存入文本文件或者在网络中传输。对象 -- 流数据
ObjectOutputStream
反序列化流: 把文本文件中的流对象数据或者网络中的流对象数据还原成对象。流数据 -- 对象:
ObjectInputStream


类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
该接口没有任何方法,类似于这种没有方法的接口被称为标记接口。
使用transient关键字声明不需要序列化的成员变量


  看到类实现了序列化接口的时候,要想解决黄色警告线问题,就可以自动产生一个序列化id值。
  而且产生这个值以后,我们对类进行任何改动,它读取以前的数据是没有问题的。
public class Person implements Serializable {private static final long serialVersionUID = -2071565876962058344L;private String name;// private int age;private transient int age;// int age;public Person() {super();}public Person(String name, int age) {super();this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}}public class ObjectStreamDemo {public static void main(String[] args) throws IOException,ClassNotFoundException {// 由于我们要对对象进行序列化,所以我们先自定义一个类// 序列化数据其实就是把对象写到文本文件// write();read();}private static void read() throws IOException, ClassNotFoundException {// 创建反序列化对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));// 还原对象Object obj = ois.readObject();// 释放资源ois.close();// 输出对象System.out.println(obj);}private static void write() throws IOException {// 创建序列化流对象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));// 创建对象Person p = new Person("张三", 30);// public final void writeObject(Object obj)oos.writeObject(p);// 释放资源oos.close();}}

8.Properties集合


Properties概述
属性集合类。是一个可以和IO流相结合使用的集合类
可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
是Hashtable的子类,说明是一个Map集合。
Properties作为Map集合的使用
Properties的特殊功能
public Object setProperty(String key,String value):添加元素
public String getProperty(String key):获取元素
public Set<String> stringPropertyNames():获取所有键的集合
Properties和IO流的结合使用(这里的集合必须是Properties集合:)
public void load(Reader reader):把文件中的数据读取到集合中
public void load(InputStream inStream)


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

/* * 我有一个文本文件(user.txt),我知道数据是键值对形式的,但是不知道内容是什么。 * 请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其实为”100” *  * 分析: * A:把文件中的数据加载到集合中 * B:遍历集合,获取得到每一个键 * C:判断键是否有为"lisi"的,如果有就修改其值为"100" * D:把集合中的数据重新存储到文件中 */public class PropertiesTest {public static void main(String[] args) throws IOException {// 把文件中的数据加载到集合中Properties prop = new Properties();Reader r = new FileReader("user.txt");prop.load(r);r.close();// 遍历集合,获取得到每一个键Set<String> set = prop.stringPropertyNames();for (String key : set) {// 判断键是否有为"lisi"的,如果有就修改其值为"100"if ("lisi".equals(key)) {prop.setProperty(key, "100");break;}}// 把集合中的数据重新存储到文件中Writer w = new FileWriter("user.txt");prop.store(w, null);w.close();}}/*   我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,超过5次提示:游戏试玩已结束,请付费。 */public class PropertiesTest2 {public static void main(String[] args) throws IOException {// 读取某个地方的数据,如果次数不大于5,可以继续玩。否则就提示"游戏试玩已结束,请付费。"// 创建一个文件// File file = new File("count.txt");// if (!file.exists()) {// file.createNewFile();// }// 把数据加载到集合中Properties prop = new Properties();Reader r = new FileReader("count.txt");prop.load(r);r.close();// 自己的程序,当然知道里面的键是什么String value = prop.getProperty("count");int number = Integer.parseInt(value);if (number > 5) {System.out.println("游戏试玩已结束,请付费。");System.exit(0);} else {number++;prop.setProperty("count", String.valueOf(number));Writer w = new FileWriter("count.txt");prop.store(w, null);w.close();GuessNumber.start();}}}



9.NIO包
NIO其实就是新IO的意思。
JDK4出现NIO。新IO和传统的IO有相同的目的,都是用于进行输入输出的,
但新IO使用了不同的方式来处理输入输出,采用内存映射文件的方式,
将文件或者文件的一段区域映射到内存中,就可以像访问内存一样的来访问文件了,
这种方式效率比旧IO要高很多,但是目前好多地方我们看到的还是旧IO的引用,所以我们仍以旧IO为主,知道NIO即可。
JDK7的IO改进
Path
Paths
Files




JDK7的之后的nio:
  Path:路径
  Paths:有一个静态方法返回一个路径
  public static Path get(URI uri)
  Files:提供了静态方法供我们使用
  public static long copy(Path source,OutputStream out):复制文件
  public static Path write(Path path,Iterable<? extends CharSequence> lines,Charset cs,OpenOption... options):把集合的数据写到文件。


public class NIODemo {public static void main(String[] args) throws IOException {// public static long copy(Path source,OutputStream out)// Files.copy(Paths.get("ByteArrayStreamDemo.java"), new// FileOutputStream(// "Copy.java"));ArrayList<String> array = new ArrayList<String>();array.add("hello");array.add("world");array.add("java");Files.write(Paths.get("array.txt"), array, Charset.forName("GBK"));}}


0 0