javaSECore-IO
编码
。File
。字节流
。InputStream
。OutputStream
。字符流
。Reder
。Writer
。RandomAccessFile
。Properties类的使用
。序列化
1,java.io 包
API解释: 通过数据流,序列化和文件系统提供系统输入和输出。(主要针对文件的读写)
-
编码问题,一个字符串放入文本文件--------->其实是一种序列化,也可以称为字符串的序列胡
从文本读取,-------->可以认为是一种反序列化
文本文件中内容都是以字节的盎司呈现的。
字符串放入文本文件 ,首先将字符串----》转化为字节,转化成字节的时候可以选择很多种编码。
以什么样的编码方式转化为字节的,将来需要转化为字符串也需要改编码的方式转化。
(如:使用gbk转化的 ,后面转化也需要gbk)
2,常用编码
gbk,utf-8,utf-16be
//java语言内部一个字符占两个字节,不管是中文还是英文
package corelesson4; import java.io.UnsupportedEncodingException; public class EncodeDemo1 { public static void main(String[] args) { String s="ABC沃"; byte[] b = s.getBytes();// 默认会用项目的编码 for (byte b1 : b) { System.out.print(Integer.toHexString(b1&0xFF)+" "); } System.out.println(); try { s.getBytes("GBK"); for (byte b1 : b) { System.out.print(Integer.toHexString(b1&0xFF)+" "); } // gbk 编码1个英文占用一个字节,一个中文占用两个字节 } catch (UnsupportedEncodingException e) { e.printStackTrace(); } System.out.println("\n==========================="); try { s.getBytes("UTF-8"); for (byte b1 : b) { System.out.print(Integer.toHexString(b1&0xFF)+" "); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }
// 可以看出 一个英文占用一个字节 ,一个中文占 三个字节。
41 42 43 e6 b2 83
41 42 43 e6 b2 83
2, Java.io.file 类
可以表示一个文件也可以表示一个目录。
file 类的常用方法
package corelesson4; import java.io.File; import java.io.IOException; public class FileDemo1 { public static void main(String[] args) throws IOException { //代表一个目录 创建方式1 File file = new File("F:\\1_java大神之路\\全新java分布式软件工程师\\13.JavaSECore-IO专题\\Filedemo"); //判断一个目录是否存在 //true 表示存在,false 表示不存在 System.out.println(file.exists()); // 创建方式2 File file1 = new File("F:\\1_java大神之路\\全新java分布式软件工程师\\13.JavaSECore-IO专题\\Filedemo\\aaa"); if (!file1.exists()){ file1.mkdirs();//这个目录不存在就创建 }else { file1.delete();//目录存在就删除 } //创建方式3 File file2 = new File(file, "bbb"); if (!file2.exists()){ file2.mkdirs();//这个目录不存在就创建 mkdirs 创建多级目录 }else { file2.delete();//目录存在就删除 } System.out.println("================================="); // 判断是否是目录 System.out.println(file2.isDirectory()); //判断是否是文件,如果目录不存在 也返回false System.out.println(file2.isFile()); System.out.println("=========================================="); // 创建一个文件 File file3 = new File(file, "aaa.txt"); if (!file3.exists()) { file3.createNewFile(); } System.out.println(file3.exists()); System.out.println(file3.isFile()); // 得到目录的绝对路径 getAbsolutePath System.out.println(file.getAbsolutePath()); // 返回的是最后一个文件名 System.out.println(file.getName()); System.out.println(file2.getName()); // 得到他的父目录 System.out.println(file1.getParentFile()); System.out.println(file1.getParentFile().getAbsolutePath()); System.out.println(file2.getParentFile().getAbsolutePath()); } }
File 文件的过滤器
package corelesson4; import java.io.File; import java.io.FilenameFilter; public class FileDemo2 { public static void main(String[] args) { File file = new File("E:\\Myeclipse\\MyEclipse2014汉化\\features"); // listFile(file); // listFile1(file); listFile2(file); } public static void listFile(File file){ /** * list()显示里面所有的文件名和目录名,不会列出父目录 * 也不会遍历子目录 */ String[] list = file.list(); for (String s : list) { System.out.println(s); } System.out.println("===================================================="); //直接累出目录下的,产生的是File对象 File[] files = file.listFiles(); for (File file1 : files) { //打印目录的所有名字 System.out.println(file1.getAbsolutePath()); } } /** * 把子目录下的也列出来 * 和目录下所有的内容 */ public static void listFile1(File file){ //拿到file对象 File[] files = file.listFiles(); for (File file1 : files) { if (file1.isFile()){ //如果是文件就列出来 System.out.println(file1.getAbsolutePath()); }else { listFile1(file1);// 如果是目录就递归调用 } } } public static void listFile2(File file){ // String[] list = file.list(new MyFileNameFileter()); String[] list = file.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { name.startsWith(".babel"); //过滤以这个开头的 return name.endsWith("724060447");// 过滤以这个结尾的 } }); for (String s : list) { System.out.println(file.getAbsolutePath()+"/"+ s); } } //写个内部类实现这个过滤器接口 static class MyFileNameFileter implements FilenameFilter{ // file 列出的每个文件都要调用accept 方法, 返回true 留下,false 被过滤掉 @Override public boolean accept(File dir, String name) { //File dir 代表父目录 ,String name 代表直接的文件名或者目录名 // System.out.println(dir.getAbsolutePath() +" "+name); return name.endsWith("subversive_zh_4.2.0.v20130724060447"); } } }
过滤器方式一 :FilenameFilter()
public static void listFile2(File file){ // String[] list = file.list(new MyFileNameFileter()); String[] list = file.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) {
name.startsWith(".babel"); //过滤以这个开头的 return name.endsWith("724060447");// 过滤以这个结尾的 } }); for (String s : list) { System.out.println(file.getAbsolutePath()+"/"+ s); } }
过滤器方式二 :FileFilter()
package corelesson4; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; public class FileDemo2 { public static void main(String[] args) { File file = new File("E:\\Myeclipse\\MyEclipse2014汉化\\features"); // listFile(file); // listFile1(file); //listFile2(file); // listFile3(file); //listFile4(file); listFile5(file); } public static void listFile(File file){ /** * list()显示里面所有的文件名和目录名,不会列出父目录 * 也不会遍历子目录 */ String[] list = file.list(); for (String s : list) { System.out.println(s); } System.out.println("===================================================="); //直接累出目录下的,产生的是File对象 File[] files = file.listFiles(); for (File file1 : files) { //打印目录的所有名字 System.out.println(file1.getAbsolutePath()); } } /** * 把子目录下的也列出来 * 和目录下所有的内容 */ public static void listFile1(File file){ //拿到file对象 File[] files = file.listFiles(); for (File file1 : files) { if (file1.isFile()){ //如果是文件就列出来 System.out.println(file1.getAbsolutePath()); }else { listFile1(file1);// 如果是目录就递归调用 } } } public static void listFile2(File file){ // String[] list = file.list(new MyFileNameFileter()); String[] list = file.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { name.startsWith(".babel"); //过滤以这个开头的 return name.endsWith("724060447");// 过滤以这个结尾的 } }); for (String s : list) { System.out.println(file.getAbsolutePath()+"/"+ s); } } //写个内部类实现这个过滤器接口 static class MyFileNameFileter implements FilenameFilter{ // file 列出的每个文件都要调用accept 方法, 返回true 留下,false 被过滤掉 @Override public boolean accept(File dir, String name) { //File dir 代表父目录 ,String name 代表直接的文件名或者目录名 // System.out.println(dir.getAbsolutePath() +" "+name); return name.endsWith("subversive_zh_4.2.0.v20130724060447"); } } public static void listFile3(File file){ // 用匿名类方式实现 过滤器 File[] files = file.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { //File pathname 就是ile下的每个文件or目录的全路径 System.out.println(pathname); // 只留下java 其他被过滤 return pathname.getAbsolutePath().endsWith(".java"); } }); System.out.println("==============================="); for (File file1 : files) { System.out.println(file1.getAbsolutePath()); } } /** * 递归拿出子目录下的.java 文件也拿出来 * @param file */ public static void listFile4(File file){ File[] files = file.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { if (pathname.isFile()){ return pathname.getAbsolutePath().endsWith(".html"); }else if ( pathname.isDirectory()) listFile4(pathname); return true; } }); for (File file1 : files) { if (file1.isFile()){ System.out.println(file1.getAbsolutePath()); } } } public static void listFile5(File file){ File[] files = file.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { // System.out.println(dir.getAbsolutePath()+"...."+name); // 需要重新构造file File file1=new File(dir,name); if (file1.isFile()){ return name.endsWith(".html"); }else if(file1.isDirectory()){ listFile5(file1); } return true; } }); for (File file1 : files) { if (file1.isFile()){ System.out.println(file1.getAbsolutePath()); } } } }
File类的常用方法
list(), listFiles, list(FilenameFilter) , listFile(FileFilter or FilenameFilter)
注意递归问题!
文件的递归删除
目录必须为空,该目录才能删除。
所以要删除一个目录先删除里面的东西
package corelesson4; import java.io.File; public class FileDemo3 { public static void main(String[] args) { File file = new File("E:\\Myeclipse\\MyEclipse2014汉化\\features"); deleteFile(file); } public static void deleteFile(File file){ File[] files = file.listFiles(); for (File file1 : files) { if (file1.isFile()){ System.out.println(file1.getAbsolutePath()); file1.delete();// 如果是文件直接删除 } else if(file1.isDirectory()){ deleteFile(file1);// 递归删除 } } //到这里为止删除的都是子目录,下面删除父目录 System.out.println(file.getAbsolutePath()); file.delete(); } }
3,字节流 (文件读写操作)
字节流-------------- > 读写以字节单位(各种类型 mp3,MP4
,图片 文本等)
字符流-----------------> 读写以字符单位(只适合 文本文件的读写)
输入流----》读操作的
输出流----》写操作的
3,1 以字节为单位的输入输出流 FileInputStream
输入流: InputStream(读)(它是一个抽象类)
read() 重载三个重要方法
------->FileInputStream(子类) :把文件作为字节流进行读操作
------->BufferedInputStream(先读到内存,再从内存中读取,多了一个缓冲区的功能)
------->PipedInputStream : 管道流 ------->DataInputStream : 可以直接输出很多数据类型的方法,,分析读写的原理 ------->System.in : 从键盘读
如果是FileOutStream Out
out.write(10000); write 方法只能写一个字节
但是10000 是32 个字节,所以它只写后8位;
所以DataOutputStream dos 对象的writeInt 方法一定是利用out 对象的write 方法写4 次写8位
writeInt 方法内部一定是:
out.write(10000>>24)
out.write(10000>>16)
out.write(10000>>8)
out.write(10000)
输出流 : OutputStream(写) 同理读也是读4次
write () 重载三个写的方法
------->FileOutputStream(子类) :把文件作为字节流进行写操作
------->BufferedOutputStream
------->PipedOutputStream
------->DataOutputStream ------->System.out :-------> PrintStream 输出流
package corelesson4; import javax.print.DocFlavor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class StreamDemo1 { public static void main(String[] args) throws IOException { // test1(); //test2(); test3(); } // 所有的IO操作都会产生 IOEx产品提on public static void test1(){ FileInputStream in=null; try { in = new FileInputStream("H:\\WorkspacesMyEclipse2014\\ssh_test1\\src\\org\\sshtest\\entities\\UserInfo.java"); FileOutputStream out = new FileOutputStream("D:\\1.txt"); // 读文件 然后写到这个文件中 //1.txt 不存在就创建,如果存在先删除 在创建 /** * //read 一个字节一个字节的读 * 问题1:对于单字节编码 没有问题,对于多字节的文字会有乱码 * 问题2:对于大文件,读取效率比较低 */ int c; while ((c=in.read())!=-1){ //怎么读的就怎么写 out.write(c); System.out.print((char)c); } out.close(); } catch (IOException e) { e.printStackTrace(); } finally { if (in!=null){ try { // 最后关闭 in.close(); } catch (IOException e) { e.printStackTrace(); } } } } // 这里先不关心异常 public static void test2() throws IOException { FileInputStream in = new FileInputStream("H:\\WorkspacesMyEclipse2014\\ssh_test1\\src\\org\\sshtest\\entities\\UserInfo.java"); FileOutputStream out = new FileOutputStream("D:\\11.txt"); // 读文件 然后写到这个文件中 byte[] b = new byte[1024 * 5]; //读到这个数组,从第0个位置开始放 放到哪里, //int bytes = in.read(b, 0, b.length);//返回读到字节的个数 // 往b字节数组中放 最多放b.length个 // 相当于开辟了一个内存空间,把读到的放进去 // 相当于批量读取,效率高 // String s = new String (b,0,bytes); //System.out.println(s); // 方式二 int bytes; // 这样写的话就是bytes 中放满了 输出 然后清空 再放 ,在放满再输出,在放 while ((bytes=in.read(b,0,b.length))!=-1){ // 然后构造字符串, 从内存中读,如果不是文本文件 可以不用打印到控制台 String s=new String(b,0,bytes); // 写的话就直接卸载文件中 不需要构造再写 out.write(b,0,bytes); System.out.println(s); } } //方式三 public static void test3() throws IOException { /** * 缺点:如果文件很大 开辟的内存空间很大 建议都用test2 方法写文件。 */ FileInputStream in = new FileInputStream("H:\\WorkspacesMyEclipse2014\\ssh_test1\\src\\org\\sshtest\\entities\\UserInfo.java"); FileOutputStream out = new FileOutputStream("D:\\21.txt"); // 读文件 然后写到这个文件中 int length = in.available();// 返回可读的字节数 // 构造字节数组 byte[] b = new byte[length]; int read = in.read(b); String s= new String (b,0,b.length); System.out.println(s); //这里直接写在文件中 out.write(b); in.close(); } //不管是读写 建议使用 第二种方式。 public static void test4(){ FileInputStream in = null; try { in = new FileInputStream("D:\\aa.txt"); FileOutputStream out = new FileOutputStream("D:\\bb.txt"); // 读文件 然后写到这个文件中 byte[] b = new byte[1024 * 5]; int bytes; while ((bytes=in.read(b,0,b.length))!=-1){ String s=new String(b,0,bytes,"utf-8");//这里解决字符编码不一样的问题 out.write(b,0,bytes); System.out.println(s); } } catch (IOException e) { e.printStackTrace(); } } }
------->BufferedInputStream
------->BufferedInputStream(先读到内存,再从内存中读取,多了一个缓冲区的功能)
内部源码有一个:protected volatile byte buf[]; 数组
package corelesson4; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class StreamDemo2 { public static void main(String[] args) { try { BufferedInputStream in = new BufferedInputStream(new FileInputStream("D:\\1.txt")); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("D:\\a1.txt")); byte[] bytes = new byte[10000]; int c; //内部操作先把文件放置到 内存中(缓冲区字节数组),所以也不太适合太大的文件 //我们读的时候充内存中读取。 while ((c=in.read(bytes,0,bytes.length))!=-1){ //把缓冲区中读到的内容写入磁盘,刷新缓冲区才会写入磁盘 out.write(bytes,0,c); out.flush();//刷新缓冲区 ,缓冲区大小满了 会自动刷新。 } in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } }
------->PipedInputStream : 管道流
PipedInputStream (PipedOutputStream())
PipedInputStream (PipedInputStream() )
out写出的数据正好被in 读到
package corelesson4; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; public class StreamDemo3 { public static void main(String[] args) { // 管道流 try { PipedInputStream in = new PipedInputStream(); PipedOutputStream out = new PipedOutputStream(in); Send send = new Send(out); Receive rec = new Receive(in); send.send(); rec.rec(); in.close(); out.close(); } catch (Exception e) { e.printStackTrace(); } } } class Send{ OutputStream out; public Send(OutputStream out) { super(); this.out = out; } public void send(){ byte value=(byte)(Math.random()*100); try { System.out.println("send the value is: "+value); out.write(value);//写出去 } catch (IOException e) { e.printStackTrace(); } } } class Receive{ InputStream in; public Receive(InputStream in) { super(); this.in = in; } public void rec(){ try { byte value = (byte)in.read(); System.out.println("rec the value is: "+value); } catch (IOException e) { e.printStackTrace(); } } }
将来 两个需要交互的时候 一边写,正好被一边读到。
------->DataInputStream
package corelesson4; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class StreamDemo4 { public static void main(String[] args) { wirte(); read(); } public static void wirte(){ try { //把1.txt文件作为字节输出流,并且直接写java的数据类型 // DataOutputStream dos = new DataOutputStream(new FileOutputStream("D:\\1.txt")); // 都是一个字节流装饰出来的,称装饰模式 // 把 1.txt 文件作为字节输出流,并且先写入缓冲区,可以直接写数据类型 // DataOutputStream dos1 = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("D:\\1.txt"))); // 发现 特殊功能流类都是基本的流,嵌套构造出来,其实是一种装饰模式。 // 优点 直接写数据类型 DataOutputStream dos = new DataOutputStream(new FileOutputStream("D:\\1.txt")); // 写一个int 类型 dos.writeInt(10000); //写一个Boolean 类型 dos.writeBoolean(true); //写一个Double类型 dos.writeDouble(10.03); //写一个字符串类型 dos.writeUTF("HELLO"); dos.close(); } catch (IOException e) { e.printStackTrace(); } } public static void read(){ try { DataInputStream dis = new DataInputStream(new FileInputStream("D:\\1.txt")); // 对应的读出来 System.out.println(dis.readInt()); System.out.println(dis.readBoolean()); System.out.println(dis.readDouble()); System.out.println(dis.readUTF()); } catch (IOException e) { e.printStackTrace(); } } }
------->System.in : 从键盘读
package corelesson4; import java.io.IOException; public class StreamDemo5 { public static void main(String[] args) { byte[] bytes = new byte[10000]; System.out.println("请输入: "); try { while (true){ int read = System.in.read(bytes, 0, bytes.length); String str = new String(bytes, 0, read); if ("end".equals(str)){ break; } System.out.println(str); } } catch (IOException e) { e.printStackTrace(); } } }
-------> PrintStream 输出流
文件找那个追加写内容
FileOutputStream("D:\2.txt"),true); //后面这里为true 如果文件存在 就会追加写在里面
package corelesson4; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; public class StreamDemo6 { public static void main(String[] args) { try { PrintStream ps = new PrintStream(new FileOutputStream("D:\\2.txt")); //FileOutputStream("D:\\2.txt"),true); //后面这里为true 如果文件存在 就会追加写在里面 // System.out 目标是标准输出设备 System.in 标准输入设备 就是我们的控制台 ps.println("hello"); ps.close(); } catch (IOException e) { e.printStackTrace(); } } }
4 字符流,(文本操作)
字符流(文本操作)------>都是有字节流构造出来的(用到的是适配器模式)
输入流 ------->Reader
---------------->InputStreamReader
----------------> FileReader
----------------> BufferedReafer 一次可以读一行字符字符串
输出流-------->Writer
---------------->OutputStreamReader
----------------> FileWriter
----------------> BufferedWriter一次可以写一行字符字符串
---------------------------------PrintWriter
主要的方式也是读和写
不管是字符流还是字节流我们需要关注的是输入和输出的方法。
1, ------>InputStreamReader
bufferedReader
package corelesson4; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; public class RWDemo1 { public static void main(String[] args) { RWStream1(); RWStream2(); } public static void RWStream1(){ try { InputStreamReader in = new InputStreamReader(new FileInputStream("D:\\11.txt")); OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("D:\\11w.txt")); // 一个字符一个字符的读 int c; while ((c=in.read())!=-1){ // c 读到的是一个字符 这样读取没有乱码 ,默认是一样的 System.out.print((char)c); out.write(c); out.flush();// 字符流都是有缓冲区的 不要忘记了刷新 } in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } public static void RWStream2(){ try { InputStreamReader in = new InputStreamReader(new FileInputStream("D:\\11.txt")); OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("D:\\11w1.txt")); char[] c = new char[1000]; int len; while ((len=in.read(c,0,c.length))!=-1){ // 然后拿字符数组来构造成字符串 String s= new String (c,0,c.length); System.out.print(s); out.write(c,0,len); out.flush(); } in.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } }
2, ---------------> FileReader
package corelesson4; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class RWDemo2 { public static void main(String[] args) { RWStream1(); } public static void RWStream1(){ try { //这样构造就很方便,缺点 不能指定编码 FileReader fr = new FileReader("D:\\11.txt"); FileWriter fw = new FileWriter("D:\\11w2"); char[] chars = new char[1000]; int len; while ((len=fr.read(chars,0,chars.length))!=-1) { // 构造成字符串打印熬控制台 String s = new String(chars, 0, chars.length); System.out.print(s); fw.write(chars,0,len); } } catch (IOException e) { e.printStackTrace(); } } }
3,-----> BufferedReafer 一次可以读一行字符字符串
Filewriter
注意: 读一行readLine ,换行 newLine,刷新缓冲 bw.flush();
package corelesson4; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; public class RWDemo3 { public static void main(String[] args) { try { // BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\11.txt"))); BufferedReader br = new BufferedReader(new FileReader("D:\\11.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\11w3.txt")); // 有一个重要的方法就是readLine()方法一次可以读一行 String s=null; while ((s=br.readLine())!=null){ System.out.print(s);// 一次读一行不读取换行 // 读一行写一行 bw.write(s); // 读一行还下一行开始写 bw.newLine(); // 读完一行刷新依稀缓存 bw.flush(); } br.close(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } }
PrintWriter也比较常用
package corelesson4; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; public class RWDemo4 { public static void main(String[] args) { try { // BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("D:\\11.txt"))); BufferedReader br = new BufferedReader(new FileReader("D:\\11.txt")); PrintWriter pw = new PrintWriter(new FileOutputStream("D:\\44.txt"),true);//加true 自动刷新 不用非手动flush了 // 有一个重要的方法就是readLine()方法一次可以读一行 String s=null; while ((s=br.readLine())!=null){ System.out.print(s);// 一次读一行不读取换行 // 读一行写一行 pw.println(s); } br.close(); pw.close(); } catch (IOException e) { e.printStackTrace(); } } }
字节流决定 输入输出的目标, 字符流呢就是适配它自己的类型。
从键盘一次读一行 读到end 及结束
最内层决定了它的输入输出目标
package corelesson4; import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; public class RWDemo5 { public static void main(String[] args) { try { // 从键盘一次读一行 读到end 及结束 // 输入输出 是由最内层来决定的。 这个过程就是一个适配器的过程。 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while (true){ String str=br.readLine(); System.out.println(str); if("end".equals(str)){ break; } } } catch (IOException e) { e.printStackTrace(); } } }
5,RandomaccessFile 随机访问的流类
一种比较早的方式
package corelesson4; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; public class RWDemo6 { public static void main(String[] args) { try { RandomAccessFile raf = new RandomAccessFile("D:\\44.txt","rw"); System.out.println(raf.getFilePointer()); raf.writeInt(1000); System.out.println(raf.getFilePointer()); // 相当于写了 raf.write(1000>>24); raf.write(1000>>16); raf.write(1000>>8); raf.write(1000); System.out.println(raf.getFilePointer()); raf.writeUTF("hello"); //写入hello System.out.println(raf.getFilePointer());// 查看hello 所在的位置 byte[] b=new byte[10000]; int bytes = raf.read(b, 0, b.length);// 返回的是字节的个数 } catch (IOException e) { e.printStackTrace(); } } }
6.java.util.Properties(并不是IO种的类)
实际使用需要和IO结合在一起
资源文件已properties 作为文件的扩展名
文件的内容 是以key =value 的方式进行存放的
properties 的使用
package corelesson4; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class PropertiesDemo1 { public static void main(String[] args) { Properties prop = new Properties(); //加载这个文件, 把这个文件转化为输入流。 try { prop.load(new FileInputStream("这里 放properties 文件")); for (Object o : prop.keySet()) { String key=(String)o; System.out.println(key+"="+prop.get(key)); } // 资源文件中的内容是可以看见的 key 就是已知的 //可以直接这样用 System.out.println( prop.getProperty("key"));// 直接拿到里面的值 } catch (IOException e) { e.printStackTrace(); } } }
properties 基本使用 升级2
package corelesson4; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; public class PropertiesDemo2 { public static void main(String[] args) { Properties prop = new Properties(); //加载这个文件, 把这个文件转化为输入流。 try { // 缺点 : 这样写 路径就写死了 项目一旦移动就找不到路径了 // prop.load(new FileInputStream("这里 放properties 文件")); // 使用class 得到当前类的字节流 //getResourceAsStream 得到的是classPath 路径 // 用哪个类的 类类型呢? 都是可以的在同一包下什么类的类类型 的classpath 都是一样的 prop.load(PropertiesDemo2.class.getResourceAsStream("")); // 这种方式 用的多一些 // 还有一种 是加载包下的properties 文件 直接输入包下的文件 //class.getClassLoader() 获得的是类加载器 prop.load(PropertiesDemo2.class.getClassLoader().getResourceAsStream("corelesson4/aa.properties")); //可以直接这样用 System.out.println( prop.getProperty("key"));// 直接拿到里面的值 } catch (IOException e) { e.printStackTrace(); } } }
资源文件 将来 在设计中 用来解耦的。 一般和反射结合使用。
7, IO 序列化问题
序列化---->对象系列化
(对象进行存储or 在网络中进行传递,该对象必须进行序列化)
Java.ioObjectOutputStream
Java.ioObjecInputStream
java.io.Serializable 如果一个对象想要 序列化 必须实现这个序列化的接口
该接口只是一个标准规范 ,没有任何方法。
7.2 transient 关键字
如果该对象的属性用transient 关键字来修饰,那么 该属性不会做jvm 默认的序列化工作
package corelesson4; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SeriDemo1 { public static void main(String[] args) { Student stu = new Student(1000,"zhangshan",20); try { //写入文件 ObjectOutputStream out = new ObjectOutputStream( new FileOutputStream("D:\\55.txt")); out.writeObject(stu);//直接写入一个对象 out.flush(); out.close(); //读操作 ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:\\44.txt")); Student stu1=(Student)in.readObject(); System.out.println(stu1); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
7.3 集合中的 类是如何序列化的 比如ArrayList
ArrayList 中有数组,且数组不一定放满元素, 所以没有必要吧整个数组做序列化。只需要序列化有效元素。
用了以下两个方法签名做了 序列化和反序列化的工作。
Private void readObject (java.io.ObjectInputStream stream)
throws IOExcrption,ClassNoFoundException;
Private void writeObject (java.io.ObjectOutputStream stream)
throws IOExcrption;
这样的新能比较高
7.4 java 实现接口,继承 都有传递性
如果父类 实现了Serializable 接口,那么其子类都可以序列化
需要注意的是:
如果父类是可序列化的,那么在反序列化子类的时候不会调用父类
的构造函数,如果父类是不可序列化的,而子类是可以序列化的,那么在子类反序列化时,会调用父类的构造函数。
package corelesson4; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; public class SeriDemo2 { public static void main(String[] args) { // 1 序列化 try { // ObjectOutputStream out = new ObjectOutputStream( // // new FileOutputStream("D:\\66.txt")); // // 2,创建对象 // C c = new C(); // //3 ,接下来 做序列化工作。 // out.writeObject(c); // out.flush(); // out.close(); //4,以上就是他的序列化 //5 .接下来做反序列化, 保存到那个文件,就到哪个文件去取 ObjectInputStream out = new ObjectInputStream(new FileInputStream("D:\\66.txt")); C c=(C)out.readObject(); System.out.println(c); } catch (Exception e) { e.printStackTrace(); } } } class A implements Serializable{ public A() { System.out.println("a....."); } } class B extends A{ // 这样 B类是可以被序列化的 public B() { System.out.println("b......"); } } class C extends B{ public C() { System.out.println("c....."); } }
7.5 java 中 有一个克隆的功能Object 类中已经提供了
一个类的对象要进行克隆直接实现Cloneable 接口即可
Cloneable 也是一个标准 没有具体的方法;
package corelesson4.prototype; public class CloneTest { public static void main(String[] args) { User user = new User(); User user1=null; Address address = new Address(); user.setAddress(address); //现在就可以克隆新的对象 try { // 这样就克隆 一个新的对象出来了 user1 =(User)user.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } System.out.println(user==user1); System.out.println(user.getAddress()==user1.getAddress()); } }
称为: 浅克隆 or 浅拷贝
浅拷贝主要是内部引用指向同一个对象的内存。
比如 A---->b1 ---->C对象
B ------->b2----->C 对象 内部指向的都是C对象同一块内存 称为浅拷贝
深拷贝
1,对当前对象序列化的工作,
深克隆or 深拷贝 , 通过序列化和反序列化的方式
这其实是一个设计模式---》原型模式
7.6 结合集合使用IO
案例 有如下文本文件
1,zhangshan,28 2,lishi,23 3,wangwu,19 4,zhaoliu,24 5,zhangshan,28 6,zhangshan,28 7,lishi,23 8,zhangshan,28 9,tianqi,30
要求统计姓名出现的次数 ,并且按照次数降序输出,如果次数相同,按照名字升序。
思路: 一次读一行,然后进行字符串分割,把名字放入map 集合中
统计次数,然后 用treeSet 排序
package corelesson4; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.util.HashMap; public class works { public static void main(String[] args) { getStuduens(); } public static HashMap<String ,Integer> getStuduens(){ HashMap<String, Integer> map = new HashMap<>(); try { BufferedReader br = new BufferedReader(new FileReader("D:\\aa.txt")); String str= null; while ((str=br.readLine())!=null){ String[] ss=str.split(","); for (String s : ss) { System.out.print(s+" "); } System.out.println(); } } catch (Exception e) { e.printStackTrace(); } return null; } }
IO 专题主要是这些 后续有补充的在补充笔记!