4月3日,MLDN Java 学习之旅,跟李兴华老师混了

今天所讲的知识点
A File类
B 可随机读取文件内容:RandomAccessFile类
C 字节流输入输出:OutputStream和InputStream
D 字符流输入输出:Writer和Reader
E 字符流和字节流的区别
F 字节流-字符流的转换
G 打印流:PrintStream流
H 对象序列化:Serializable
I 对象序列化操作:ObjectOutputStream
J 对象反序列化操作:ObjectInputStream
K 一组对象的序列化
L 指定不可序列化的属性:transient

所有的io操作都在java.io包中定义。
学习IO包就始终记住一点:“抽象类或接口的功能由实现它的子类来决定,根据实例化其子类的不同,完成的功能也不同。”
需要注意的是,所有关于文件的操作,在每次操作的最后一定要关闭资源。




我对知识点的分析

A File类

如果在一个程序中涉及到和文件打交道,那么就必须用到File类。
和文件有关的操作有文件的创建、删除、重命名、得到路径、创建时间等等。

一、File类的定义
java.io.File类的定义如下:
public class File
extends Object
implements  Serializable,  Comparable<File>
此类继承了Object类,实现了Serializable接口(表示可序列化)和Comparable接口(表示可排序)

二、File类的实例化
其中最常用的一个构造方法:public File(String pathname)
关于这个参数的使用说明:
作用:指定文件的路径及文件名
例如:"d:\\test.txt"(在文件分隔符前加\表示转义,否则无法表示\)
注意:关于路径的分隔符,各种操作系统不一样,例如Windows下是“\”,Linux下是“/”
为了程序的可移植性,一般不直接在路径中加分隔符,而是采用File类中分隔符的常量代替。
例如:想要指定“D:\test.txt”,那么则写“"d:" + File.separator + "test.txt"”


三、File类的常量
File类常用的两个常量:
public static final String separator  表示路径分隔符的“\”
public static final String pathSeparator 表示路径分隔符的“;”

四、File类的操作方法

No. 方法或常量名称 描述
1 public boolean createNewFile() throws IOException 创建新文件
2 public boolean delete() 删除文件
3 public String getParent() 得到文件的上一级路径
4 public boolean isDirectory() 判断给定的File对象是否是文件夹
5 public boolean isFile() 判断给定的File对象是否是文件
6 public String[] list() 列出文件夹中的文件
7 public File[] listFiles() 列出文件夹中的文件,以对象形式返回
8 public boolean mkdir() 创建新的文件夹
9 public boolean renameTo(File dest) 为文件重命名
10 public long length() 返回文件大小
11 public boolean equals(Object obj) 判断是否和另一文件对象相同
示例代码:
import java.io.File;
import java.io.IOException;
public class FileDemo{
public static void main(String[] args) {
  File file = new File("d:" + File.separator + "test.txt");//实例化文件对象
  try {
   file.createNewFile(); // 创建文件
  } catch (IOException e) {
   e.printStackTrace();
  }
  System.out.println(file.isFile());//判断是否是文件
  System.out.println("文件大小:" + file.length());
  System.out.println("文件路径:" + file.getPath());
  System.out.println("文件路径:" + file);//与上行相同
  if(file.isDirectory()){//判断是否是文件夹
   String str[] = file.list(); // 列出file对象中的文件和文件夹名
     for (int x = 0; x < str.length; x++) {
      System.out.println(str[x]);//例如mldn  test.txt等
     }
   File files[] = file.listFiles(); // 列出file对象中的文件和文件夹名,带完整路径
   for (int x = 0; x < files.length; x++) {
    System.out.println(files[x]);//例如d:\mldn   d:\test.txt等
   }
  }
  if (file.exists()) { // 文件是否存在
   file.delete();// 删除文件
  }
}
}

B 可从任意位置开始读写:RandomAccessFile类

如果想要对文件中的内容进行读写,可以采用RandomAccessFile类,并且此种方式读写的最大特点在于能够随机指定一个位置开始读取或者写入。
但是这种操作方式的前提是表示同一类信息的数据写入时数据长度必须一致,否则读取时会发生错误。

一、RandomAccessFile类的定义
public class RandomAccessFile
extends Object
implements DataOutput, DataInput, Closeable
此类也是直接继承的Object类,实现了Closeable接口(表示可关闭文件)、DataOutput接口(表示可写入数据)、DataInput接口(表示可读取数据)

二、RandomAccessFile类的构造方法
(1)public RandomAccessFile(File file,String mode) throws FileNotFoundException
参数说明:
第一个参数表示接收一个File类对象,指定读写操作的对象,第二个参数要求说明打开的模式
模式说明:
"r"     只读
"rw"    可读可写,如果指定文件不存在,自动创建一个
"rws"   在rw基础上加个“对文件内容和元数据的修改要限制为同步”
"rwd"   在rw基础上加个“对文件内容的修改要限制为同步”
(2)public RandomAccessFile(String name,String mode) throws FileNotFoundException

三、RandomAccessFile类的操作方法
No. 方法名称 描述
1 public final void writeBytes(String s) throws IOException 将字符串以字节的形式输出
2 public final void writeInt(int v) throws IOException 输出整型数据
3 public final byte readByte() throws IOException 读取一个字节
4 public final int readInt() throws IOException 读取int数据
5 public void seek(long pos) throws IOException 设置读或写指针位置seek(0),回到开始位置
6 public int skipBytes(int n) throws IOException 跳过指定的字节长度

例如:
package mldn.lin.Test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class Test
{
public static void main(String[] args) throws IOException {
  File file=new File("d:"+File.separator+"test.txt");
  RandomAccessFile out=null;
  try {
   out=new RandomAccessFile(file,"rw");
  } catch (FileNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }//声明为可读可写
 
  String name=null;
  int age=0;
  name="zhangsan";
  age=25;
  out.writeBytes(name);// 写入8个长度
  out.writeInt(age);// 写入数字
  name="lisi    ";
  age=45;
  out.writeBytes(name);
  out.writeInt(age);
 
  out.seek(0);//把指针移回到文件开始处
  out.skipBytes(12);//移动8个字节开始读取
  byte[] b=new byte[8];//读取八个字节 
  for(int i=0;i<b.length;i++){
   b[i]=out.readByte();
  }
  name=new String(b);
  age=out.readInt();
  System.out.println(name+":"+age);
 
  out.close();
}
}
C 字节流输入输出:OutputStream和InputStream
按处理数据的单位划分,Java支持两种基本的流类型: char流和byte流。
两个对称性:
输入-输出对称:InputStream和OutputStream各自占据byte流的输入与输出的两个平行的类等级结构的根部;而Reader和Writer各自占据char流的输入与输出的两个平行的类等级结构的根部
byte-char对称: InputStream与Reader的子类分别负责byte和char流的输入; OutputStream和Writer的子类分别负责byte和char流的输出
但是,不管使用那种操作,字节流和字符流的操作都是采用如下的步骤完成:
1、 找到一个要操作的资源,可能是文件,可能是其他的位置
2、 根据字节流或字符流的子类,决定输入及输出的位置
3、 进行读或写的操作
4、 关闭
一、OutputStream字节输出流类
public abstract class OutputStream
extends Object
implements Closeable, Flushable
此类继承了Object类,实现了Closeable接口(可关闭文件)和Flushable接口(可刷新);
此类是一个抽象类,所以不可直接实例化,必须通过其子类来实现。


那么此处操作文件呢,就用。

二、FileOutputStream类
其构造方法有:
No. 方法名称 描述
1 public FileOutputStream(File file) throws FileNotFoundException 接收File类的实例,表示要操作的文件位置。
2 public FileOutputStream(File file,boolean append) throws FileNotFoundException 接收File类实例,并指定是否可以追加

三、OutputStream类的操作方法
No. 方法名称 描述
1 public void close() throws IOException 关闭
2 public void flush() throws IOException 刷新操作
3 public void write(byte[] b) throws IOException 将一组字节写入到输出流之中
4 public void write(byte[] b,int off,int len) throws IOException 将指定范围的字节数组进行输出
5 public abstract void write(int b) throws IOException 每次写入一个字节,byte  int
例如:
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class Test {
public static void main(String[] args) throws IOException {
  File file = new File("D:" + File.separator + "test.txt"); // 指定要操作的文件
  OutputStream out = null; // 定义字节输出流对象
  out = new FileOutputStream(file, true); // 实例化操作的父类对象,可以追加内容
  String info = "Hello World!!!";// 要输出的信息
  byte b[] = info.getBytes(); // 将字符串变为字节数组
  out.write(b);// 输出内容
  out.close(); // 关闭
}
}

四、InputStream字节输入流
此类的定义如下:
public abstract class InputStream
extends Object
implements Closeable
同样此类继承了Object类,实现了Closeable接口(可关闭文件);但此类是一个抽象类,所以不可直接实例化,必须通过其子类来实现。

操作文件就使用FileInputStream类

五、FileInputStream类
构造方法:public FileInputStream(File file) throws FileNotFoundException

六、InputStream类的操作方法
No. 方法名称 描述
1 public void close() throws IOException 关闭
2 public abstract int read() throws IOException 读取一个字节,如果为-1,表示读到尾了
3 public int read(byte[] b) throws IOException 向字节数组中读取,同时返回读取的个数
4 public int read(byte[] b,int off,int len) throws IOException 指定读取的范围
例如:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) throws IOException {
  File file = new File("D:" + File.separator + "test.txt");// 要读取的文件路径
  InputStream input = null; // 字节输入流
  input = new FileInputStream(file);
  byte b[] = new byte[input.available()];// 开辟byte数组空间,读取内容
// byte b[] = new byte[(int) file.length()];
  input.read(b); // 读取
  input.close();
  System.out.println(new String(b));
}
}

D 字符流输入输出:Writer和Reader
一、Writer类
此类的定义如下:
public abstract class Writer
extends Object
implements Appendable, Closeable, Flushable
此类继承Object类,并且实现Appendable接口(可连接的), Closeable(可关闭的), Flushable(可刷新的)
同样是抽象类,需要子类来实例化

此处操作文件选用FileWrite类

二、FileWrite类
构造方法:
No. 方法名称 描述
1 public FileWriter(File file) throws IOException 根据File类构造FileWriter实例
2 public FileWriter(File file,boolean append) throws IOException 根据File类构造FileWriter实例是否追加内容

三、Writer类操作方法
No. 方法名称 描述
1 public void write(String str) throws IOException 直接将字符串写入输出
2 public void write(char[] cbuf) throws IOException 输出字符数组
3 public abstract void close() throws IOException 关闭
4 public abstract void flush() throws IOException 刷新
例如:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Test {
public static void main(String[] args) throws IOException  { // 所有异常抛出
  File file = new File("D:" + File.separator + "test.txt"); // 指定要操作的文件
  Writer out = new FileWriter(file); // 实例化操作的父类对象
  String info = "Hello World!!!";// 要打印的信息
  out.write(info);// 输出内容
  out.close(); // 关闭
}
}

四、Reader类
此类的定义如下:
public abstract class Reader
extends Object
implements Readable, Closeable
此类继承Object类,并且实现Readable(可读取的), Closeable(可关闭的)
同样是抽象类,需要子类来实例化

此处操作文件,选用FileReader类

五、FileReader类
构造方法:public FileReader(File file) throws FileNotFoundException

六、Reader类操作方法
No. 方法名称 描述
1 public int read() throws IOException 读取一个字符,返回-1表示到文件尾
2 public int read(char[] cbuf) throws IOException 读取一组内容,返回读入的大小
3 public abstract void close() throws IOException 关闭
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class Test {
public static void main(String[] args) throws IOException  {
  File file = new File("D:" + File.separator + "test.txt");// 要读取的文件路径
  Reader input = null; // 字节输入流
  input = new FileReader(file);
  char b[] = new char[(int)file.length()];// 开辟char数组空间,读取内容
  int len = input.read(b); // 读取
  input.close();
  System.out.println(new String(b, 0, len));
}
}

E 字符流和字节流的区别
区别:字节流没有使用到缓冲区,而是直接操作输出的,而字符流使用到了缓冲区,是通过缓冲区操作输出的。
那么如果在操作字节流的输出时,忘了关闭文件,没有影响,还是能直接输出到文件的,而如果是操作字符流的话,在文件没有关闭的时候,内容都暂时在缓冲区,只有关闭文件或者手动调用flush()方法,才能清空缓冲区,实现输出
F 字节流-字符流的转换
之前的操作都是以字节流的方式写入字节数组的数据,那么就以字节流的方式读出到字节数组,同样以字符流的方式写入字符数组或字符串的数据,那么就以字符流的方式读出到字符数组。
那么如果里面的数据是字节流的,能不能直接读出到字符数组中呢?即字节流和字符流能不能转换呢?答案是肯定的。那么主要使用以下的两个类完成:
• OutputStreamWriter:可以将输出的字符流变为字节流的输出形式
• InputStreamReader:将输入的字节流变为字符流输入形式
      
一、OutputStreamWriter类
构造方法:public OutputStreamWriter(OutputStream out)
当与任何一个OutputStream的具体子类链接时, OutputStreamWriter可以将char类型的数据转换成为byte类型的数据,再交给输出流
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class Test {
public static void main(String[] args) throws IOException {
  File file = new File("D:" + File.separator + "temp.txt");
  // 通过转换类,将字符输出流变为字节输出流
  Writer out = new OutputStreamWriter(new FileOutputStream(file));
  out.write("Hello World!!!");
  out.close();
}
}

二、InputStreamReader类
构造方法:public InputStreamReader(InputStream in)
InputStreamReader是从byte流到char流的一个桥梁,它读入byte数据并根据指定的编码将之翻译成为char数据
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
public class Test{
public static void main(String[] args) throws IOException  {
  File file = new File("D:" + File.separator + "temp.txt");
  Reader input = new InputStreamReader(new FileInputStream(file));
  char c[] = new char[100];
  int len = input.read(c);// 读取数据
  System.out.println(new String(c, 0, len));
  //char c[] = new char[(int)file.length()];
//  input.read(c);// 读取数据
//  System.out.println(new String(c));
  input.close();
}
}

G 打印流:PrintStream流
之前的所有数据的输入输出要么转换成字符串,要么转换成字节,或整数,那么如果是boolean,float等类型数据能否直接进行输入输出呢?这就需要用到打印流或者叫装饰流。
一、PrintStream类
PrintStream类的定义格式:
public class PrintStream
extends FilterOutputStream
implements Appendable, Closeable

PrintStream类继承了FilterOutputStream类,而该类又是OutputStream的子类,只不过它比OutputStream类具有更加强的输入输出功能。

二、PrintStream类的构造方法
1、public PrintStream(OutputStream out)
2、public PrintStream(File file) throws FileNotFoundException
因为OutputStream是抽象类,那么其实例化是通过其子类实现,这样的话,当用public PrintStream(OutputStream out)构造方法实例话PrintStream对象的时候,哪个OutputStream子类对象为PrintStream实例化,PrintStream就具备了向指定位置的输出能力。样的设计在设计模式上讲称为装饰设计模式。

二、PrintStream类的操作方法
No. 方法名称 描述
1 public PrintStream format(String format, Object... args) 表示格式化输出
2 public void print(数据类型 f) 打印输出,不换行
3 public PrintStream printf(String format,Object... args) 格式化输出
4 public void println(数据类型 f) 打印输出,换行
可以调用print和println方法输出任意数据类型的内容,同时还可以指定输出格式的模板来完成格式化输出的功能。
模板的指定如下:
No. 模板标记 描述
1 %s 表示字符串
2 %d 表示整数
3 %n.mf 表示小数,一共的数字长度是n,其中小数是m位
4 %c 表示字符
5 %o或%O 以八进制显示
6 %x或%X 以十六进制显示
7 %05d 五位显示整数,不够左边添0
例如:
PrintStream out = new PrintStream(new FileOutputStream(new File("d:"
    + File.separator + "temp.txt")));
out.printf("姓名:%s,年龄:%d,工资:%7.2f。", name, age, salary);
out.close();

H 对象序列化:Serializable
对象序列化就是指将一个对象转化成二进制的byte流。将对象输出到资源链接中的操作称为对象的序列化操作,将对象从资源之中读取称为反序列化的操作
如果要想实现对象的序列化,则需要使用ObjectOutputStream类完成,要想实现反序列,则需要使用ObjectInputStream类完成。

在使用对象序列化的时候一定要注意一点,要被序列化对象所在的类必须实现java.io.Serializable接口,表示该对象可被序列化。Serializable接口的定义如下:
public interface Serializable{
}
此接口中没有任何的方法定义。与Cloneable接口一样,此接口也属于标识接口。
在实现此接口的类中,一般增加一个常量属性:
private static final long serialVersionUID = 1L;// 此常量表示的是一个序列化的版本编号,为的是可以在不同的JDK 版本间进行移植
I 对象序列化操作:ObjectOutputStream
一、ObjectOutputStream构造方法
public ObjectOutputStream(OutputStream out) throws IOException
与PrintStream一样,根据实例化其子类的不同,输出的位置也不同。

二、ObjectOutputStream操作方法
1、public final void writeObject(Object obj) throws IOException
2、public void close() throws IOException
例如:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
    new File("D:" + File.separator + "person.ser")));
Person per = new Person("张三", 30);
oos.writeObject(per);// 输出,即序列化操作
oos.close();// 关闭


J 对象反序列化操作:ObjectInputStream
一、ObjectInputStream构造方法
public ObjectInputStream(InputStream in) throws IOException

二、ObjectInputStream操作方法
1、public final Object readObject() throws IOException,ClassNotFoundException
2、public void close() throws IOException
例如:
ObjectInputStream oos = new ObjectInputStream(new FileInputStream(
    new File("D:" + File.separator + "person.ser")));
Person p = (Person)oos.readObject() ;
System.out.println(p);

K 一组对象的序列化
可以采用对象数组的形式完成一组对象的序列化操作,和反序列化操作
一、对象数组的序列化
因为public final void writeObject(Object obj) throws IOException方法的参数是Object类型,那么一个对象数组也是一个Object对象,所以可以直接序列化一个对象数组。
例如:
Person per[] = { new Person("张三", 30), new Person("李四", 35),
    new Person("王五", 50) };
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
    new File("D:" + File.separator + "person.ser")));
oos.writeObject(per);// 输出
oos.close();// 关闭
二、一组对象的反序列化
public final Object readObject() throws IOException,ClassNotFoundException方法的返回值是Object类型,那么可以直接返回一个对象数组的引用。
Person p[] = (Person[])oos.readObject();

L 指定不可序列化的属性:transient
如果现在对象中的某个属性不希望被序列化,则此时就可以使用transient关键字进行声明。
例如:
private transient String name;
private transient int age;
则以后在进行对象序列化的时候,name和age属性将无法被序列化下来。则在进行反序列化操作的时候,所有内容的返回值都是该数据类型的默认值,例如此处分别为null和0。

你可能感兴趣的:(java,设计模式,数据结构,linux,F#)