蓝旭第三周预习作业

本周预习作业主要涉及的是,JAVAIO输入输出流。


前言

程序在运行期间,可能需要从外部的存储媒介或者其他程序中读入所需要的数据,这就需要到了输入流。输入流的指向称为它的源,程序通过输入流读取源中的数据。另一方面,程序在处理数据后,可能需要将处理的结果写入到永久的存储媒介中或者传送到其他的应用程序,这就需要使用输出流。输出流的指向是它的目的地。虽然I/O流经常与磁盘文件的存取有关,但是源的目的地也可以是从键盘,内存,或显示器的窗口。


一主要内容

1File文件类

2文件字节输入,输出流


3文件字符输入,输出流

4缓冲流

5随机流

6数组流

7数据流

8对象流

9序列化与对象克隆

10使用Scanner解析文件

11文件锁

 二基本的一些概念

流的概念和作用

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在设备间传输称之为流。

流的本质是数据传输,根据数据传输的特性将流区分为各种类,方便更直观的进行数据操作。

Java 把 Input输入流 和 Output 输出流,统称为IO流,它的核心就是对文件的操作,对于 字节 、字符类型的输入和输出。

IO流的本质是数据传输,并且流是单向的。

 字节流和字符流

      IO流主要分为两大类,字节流和字符流。字节流可以处理任何类型的数据,如声音文件,图片,视频,文本文件等,字符流只能处理字符类型的数据。

  • 字节流
  1. java.io.InputStream 字节输入流
  2. java.io.OutputStream 字节输出流
  • 字符流
  1. java.io.Reader 字符输入流
  2. java.io.Writer 字符输出流

 各种流的大致关系图

 三FILE类

File类

File类是对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹。File类保存文件或目录的各种数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名、判断文件是否存在、获取当前目录中的文件列表、创建、删除文件和目录等方法

File 类提供了如下三种形式构造方法。

  1. File(String path):如果 path 是实际存在的路径,则该 File 对象表示的是目录;如果 path 是文件名,则该 File 对象表示的是文件。
  2. File(String path, String name):path 是路径名,name 是文件名。
  3. File(File dir, String name):dir 是路径对象,name 是文件名。

表 1  File类的常用方法
方法名称说明
boolean canRead()测试应用程序是否能从指定的文件中进行读取
boolean canWrite()测试应用程序是否能写当前文件
boolean delete()删除当前对象指定的文件
boolean exists()测试当前 File 是否存在
String getAbsolutePath()返回由该对象表示的文件的绝对路径名
String getName()返回表示当前对象的文件名或路径名(如果是路径,则返回最后一级子路径名)
String getParent()返回当前 File 对象所对应目录(最后一级子目录)的父目录名
boolean isAbsolute()测试当前 File 对象表示的文件是否为一个绝对路径名。该方法消除了不同平台的差异,可以直接判断 file 对象是否为绝对路径。在 UNIX/Linux/BSD 等系统上,如果路径名开头是一条斜线/,则表明该 File 对象对应一个绝对路径;在 Windows 等系统上,如果路径开头是盘符,则说明它是一个绝对路径。
boolean isDirectory()测试当前 File 对象表示的文件是否为一个路径
boolean isFile()测试当前 File 对象表示的文件是否为一个“普通”文件
long lastModified()返回当前 File 对象表示的文件最后修改的时间
long length()返回当前 File 对象表示的文件长度
String[] list()返回当前 File 对象指定的路径文件列表
String[] list(FilenameFilter)返回当前 File 对象指定的目录中满足指定过滤器的文件列表
boolean mkdir()创建一个目录,它的路径名由当前 File 对象指定
boolean mkdirs()创建一个目录,它的路径名由当前 File 对象指定
boolean renameTo(File)将当前 File 对象指定的文件更名为给定参数 File 指定的路径名

 特别需要注意的是:

file类是对文本的一些属性的解读和操作,获取文件本身的一些信息,而不是对文件的内容进行操作和修改。

public class Test02 {
    public static void main(String[] args) {
        String path = "C:/windows/"; // 指定文件所在的目录
        File f = new File(path, "notepad.exe"); // 建立File变量,并设定由f变量引用
        System.out.println("C:\\windows\\notepad.exe文件信息如下:");
        System.out.println("============================================");
        System.out.println("文件长度:" + f.length() + "字节");
        System.out.println("文件或者目录:" + (f.isFile() ? "是文件" : "不是文件"));
        System.out.println("文件或者目录:" + (f.isDirectory() ? "是目录" : "不是目录"));
        System.out.println("是否可读:" + (f.canRead() ? "可读取" : "不可读取"));
        System.out.println("是否可写:" + (f.canWrite() ? "可写入" : "不可写入"));
        System.out.println("是否隐藏:" + (f.isHidden() ? "是隐藏文件" : "不是隐藏文件"));
        System.out.println("最后修改日期:" + new Date(f.lastModified()));
        System.out.println("文件名称:" + f.getName());
        System.out.println("文件路径:" + f.getPath());
        System.out.println("绝对路径:" + f.getAbsolutePath());
    }
}

 假设要在 C 盘上创建一个 test.txt 文件,程序启动时会检测该文件是否存在,如果不存在则创建;如果存在则删除它再创建。

public class Test03 {
    public static void main(String[] args) throws IOException {
        File f = new File("C:\\test.txt"); // 创建指向文件的File对象
        if (f.exists()) // 判断文件是否存在
        {
            f.delete(); // 存在则先删除
        }
        f.createNewFile(); // 再创建
    }
}

 四文件字节输入/输出流:

使用输入流通常包括4个基本的操作:

1设定输入流的源

2创建指向源的输入流

3让输入流读取源中的数据

4关闭输入流

使用输出流通常包括的4个基本操作:

1给出输出流的目的地

2创建指向目的地的输出流

3让输出流把数据写入到目的地

4关闭输出流

//构造方法:
FileInputStream(String name);
FileInputStream(File file);
//第一种构造方法使用给定的文件名name创建FileInputStream流,第二个构造方法使用File对象创建File InputStream流。参数name和file指定的文件称为输入流的源。
try{
FileInputStream in= new FileInputStream("Hello.text");//创建指向hello.text的输入流
}
catch (IOException e){
System.out.println("File read error:"+e);
}

 一些特别的注意事项:

FileInputStream 流顺序地读取文件,只要不关闭流,每次调用read方法就会顺序地读取源中的内容,直到源的末尾或者流关闭。

如果没有关闭那些被打开的流,那么就可能不允许另外一个程序操作这些流中的资源。所以要养成不需要流的时候,关闭上流。用close()关闭即可。

有read()的地方一定要有close();

表 1 InputStream类的常用方法
方法名及返回值类型说明
int read()从输入流中读取一个 8 位的字节,并把它转换为 0~255 的整数,最后返回整数。
如果返回 -1,则表示已经到了输入流的末尾。为了提高 I/O 操作的效率,建议尽量
使用 read() 方法的另外两种形式
int read(byte[] b)从输入流中读取若干字节,并把它们保存到参数 b 指定的字节数组中。 该方法返回
读取的字节数。如果返回 -1,则表示已经到了输入流的末尾
int read(byte[] b, int off, int len)从输入流中读取若干字节,并把它们保存到参数 b 指定的字节数组中。其中,off 指
定在字节数组中开始保存数据的起始下标;len 指定读取的字节数。该方法返回实际
读取的字节数。如果返回 -1,则表示已经到了输入流的末尾
void close()关闭输入流。在读操作完成后,应该关闭输入流,系统将会释放与这个输入流相关
的资源。注意,InputStream 类本身的 close() 方法不执行任何操作,但是它的许多
子类重写了 close() 方法
int available()返回可以从输入流中读取的字节数
long skip(long n)从输入流中跳过参数 n 指定数目的字节。该方法返回跳过的字节数
void mark(int readLimit)在输入流的当前位置开始设置标记,参数 readLimit 则指定了最多被设置标记的字
节数
boolean markSupported()判断当前输入流是否允许设置标记,是则返回 true,否则返回 false
void reset()将输入流的指针返回到设置标记的起始处

表 2 OutputStream 类的常用方法
方法名及返回值类型说明
void write(int b)向输出流写入一个字节。这里的参数是 int 类型,但是它允许使用表达式,
而不用强制转换成 byte 类型。为了提高 I/O 操作的效率,建议尽量使用
write() 方法的另外两种形式
void write(byte[] b)把参数 b 指定的字节数组中的所有字节写到输出流中
void write(byte[] b,int off,int len)把参数 b 指定的字节数组中的若干字节写到输出流中。其中,off 指定字节
数组中的起始下标,len 表示元素个数
void close()关闭输出流。写操作完成后,应该关闭输出流。系统将会释放与这个输出
流相关的资源。注意,OutputStream 类本身的 close() 方法不执行任何操
作,但是它的许多子类重写了 close() 方法
void flush()为了提高效率,在向输出流中写入数据时,数据一般会先保存到内存缓冲
区中,只有当缓冲区中的数据达到一定程度时,缓冲区中的数据才会被写
入输出流中。使用 flush() 方法则可以强制将缓冲区中的数据写入输出流,
并清空缓冲区

 五数组流:

字节数组输入流

ByteArrayInputStream 类可以从内存的字节数组中读取数据,该类有如下两种构造方法重载形式。

  1. ByteArrayInputStream(byte[] buf):创建一个字节数组输入流,字节数组类型的数据源由参数 buf 指定。
  2. ByteArrayInputStream(byte[] buf,int offse,int length):创建一个字节数组输入流,其中,参数 buf 指定字节数组类型的数据源,offset 指定在数组中开始读取数据的起始下标位置,length 指定读取的元素个数。

字节数组输出流

ByteArrayOutputStream 类可以向内存的字节数组中写入数据,该类的构造方法有如下两种重载形式。

  1. ByteArrayOutputStream():创建一个字节数组输出流,输出流缓冲区的初始容量大小为 32 字节。
  2. ByteArrayOutputStream(int size):创建一个字节数组输出流,输出流缓冲区的初始容量大小由参数 size 指定。


ByteArrayOutputStream 类中除了有前面介绍的字节输出流中的常用方法以外,还有如下两个方法。

  1. intsize():返回缓冲区中的当前字节数。
  2. byte[] toByteArray():以字节数组的形式返回输出流中的当前内容。

六文件输入输出流:

文件输入流

FileInputStream 是 Java 流中比较常用的一种,它表示从文件系统的某个文件中获取输入字节。通过使用 FileInputStream 可以访问文件中的一个字节、一批字节或整个文件。

在创建 FileInputStream 类的对象时,如果找不到指定的文件将拋出 FileNotFoundException 异常,该异常必须捕获或声明拋出。

FileInputStream 常用的构造方法主要有如下两种重载形式。

  1. FileInputStream(File file):通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。
  2. FileInputStream(String name):通过打开一个到实际文件的链接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。


下面的示例演示了 FileInputStream() 两个构造方法的使用。

文件输出流

FileOutputStream 类继承自 OutputStream 类,重写和实现了父类中的所有方法。FileOutputStream 类的对象表示一个文件字节输出流,可以向流中写入一个字节或一批字节。在创建 FileOutputStream 类的对象时,如果指定的文件不存在,则创建一个新文件;如果文件已存在,则清除原文件的内容重新写入。

FileOutputStream 类的构造方法主要有如下 4 种重载形式。

  1. FileOutputStream(File file):创建一个文件输出流,参数 file 指定目标文件。
  2. FileOutputStream(File file,boolean append):创建一个文件输出流,参数 file 指定目标文件,append 指定是否将数据添加到目标文件的内容末尾,如果为 true,则在末尾添加;如果为 false,则覆盖原有内容;其默认值为 false。
  3. FileOutputStream(String name):创建一个文件输出流,参数 name 指定目标文件的文件路径信息。
  4. FileOutputStream(String name,boolean append):创建一个文件输出流,参数 name 和 append 的含义同上。


注意:使用构造方法 FileOutputStream(String name,boolean append) 创建一个文件输出流对象,它将数据附加在现有文件的末尾。该字符串 name 指明了原文件,如果只是为了附加数据而不是重写任何已有的数据,布尔类型参数 append 的值应为 true。

对文件输出流有如下四点说明:

  1. 在 FileOutputStream 类的构造方法中指定目标文件时,目标文件可以不存在。
  2. 目标文件的名称可以是任意的,例如 D:\\abc、D:\\abc.de 和 D:\\abc.de.fg 等都可以,可以使用记事本等工具打开并浏览这些文件中的内容。
  3. 目标文件所在目录必须存在,否则会拋出 java.io.FileNotFoundException 异常。
  4. 目标文件的名称不能是已存在的目录。例如 D 盘下已存在 Java 文件夹,那么就不能使用 Java 作为文件名,即不能使用 D:\\Java,否则抛出 java.io.FileNotFoundException 异常。

七随机流:

通过前面的学习我们知道,如果准备读入文件,需要建立指向该文件的输入流,如果准备写文件,需要建立指向该文件的输出流。那么,能否建立一个流,通过该流既能读文件,也能写文件。

RandomAcessFile 类创建的流称为随机流,与前面的输入输出流不同的是,RandomAcessFile 类既不是InputStream类的子类。也不是OutputStream类的子类,但是RandomAcessFile类创建的流指向既可以作为源的流,也可以作为流的目的地。

构造函数;

常用:RandomAccessFile ra_read = newRandomAccessFile(File file, String mode);

RandomAccessFile ra_read = newRandomAccessFile(String name, String mode);

file:创建的文件

name:文件路径

mode:操作文件的方式(“r”, "rw"),常用的是rw

r    以只读的方式打开文本,也就意味着不能用write来操作文件
rw    读操作和写操作都是允许的
rws    每当进行写操作,同步的刷新到磁盘,刷新内容和元数据
rwd    每当进行写操作,同步的刷新到磁盘,刷新内容

注意:RandomAcessFile流指向文件时,不刷新文件。

常用读的操作

  1. int read()从此文件中读取一个数据字节。

  2. int read(byte[] b)将最多 b.length 个数据字节从此文件读入 byte 数组。

  3. int read(byte[] b, int off, int len)将最多 len 个数据字节从此文件读入 byte 数组。

  4. boolean readBoolean()从此文件读取一个 boolean。

  5. byte readByte()从此文件读取一个有符号的八位值。

  6. char readChar()从此文件读取一个字符。

  7. double readDouble()从此文件读取一个 double。

  8. float readFloat()从此文件读取一个 float。

  9. void readFully(byte[] b)将 b.length 个字节从此文件读入 byte 数组,并从当前文件指针开始。

  10. void readFully(byte[] b, int off, int len)将正好 len 个字节从此文件读入 byte 数组,并从当前文件指针开始。

  11. int readInt()从此文件读取一个有符号的 32 位整数。

  12. String readLine()从此文件读取文本的下一行。

  13. long readLong()从此文件读取一个有符号的 64 位整数。

  14. short readShort()从此文件读取一个有符号的 16 位数。

  15. int readUnsignedByte()从此文件读取一个无符号的八位数。

  16. int readUnsignedShort()从此文件读取一个无符号的 16 位数。

  17. String readUTF()从此文件读取一个字符串。

常用写的操作

void write(byte[] b) 
          //将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始。 
void write(byte[] b, int off, int len) 
         //将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始。 
void write(int b) 
          //向此文件写入指定的字节。 
void writeBoolean(boolean v) 
          //按单字节值将 boolean 写入该文件。 
void writeByte(int v) 
          //按单字节值将 byte 写入该文件。 
void writeBytes(String s) 
          //按字节序列将该字符串写入该文件。 
void writeChar(int v) 
          //按双字节值将 char 写入该文件,先写高字节。 
 void writeChars(String s) 
          //按字符序列将一个字符串写入该文件。 
 void writeDouble(double v) 
          //使用 Double 类中的 doubleToLongBits 方法将双精度参数转换为一个 long,然后按八字节数量将该 long 值写入该文件,先定高字节。 
 void writeFloat(float v) 
          //使用 Float 类中的 floatToIntBits 方法将浮点参数转换为一个 int,然后按四

八数据流:

DataInputStream和DataOutputStream类创建的对象成为数据输入流和数据输出流。

他们允许程序按着机器无关的风格读取Java原始的数据。也就是说,当读取一个数值时,不必关心这个数值应当是多少个字节。

DataInputStream(InputStream in)创建的数据输入流指向一个由参数in指向的底层输入流。

DataOutputStream(OutputStream out)创建的数据输出流指向一个由参数out指向的底层输出流。

方法:

read+Boolean/Char/Long/Int/Short/Byte/Float/Double () 读取一个类型的值

write+Boolean/Char/Long/Int/Short/Byte/Float/Double () 写下一个类型的值

九对象流:

对象流:ObjectInputStream 和 ObjectOutputStream
可以把内存中的数据(基本数据类型数据,对象的处理流)持久化起来。需要的时候可以还原成内存层面的数据。

序列化:用ObjectOutputStream类保存基本类型数据或对象的机制。
反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
 

ObjectInputStream 和 ObjectOutputStream类的构造方法如下:

objectinputstream(inputstream in)

objectoutputstream(outputstream out)

objectoutputstream的指向应当是一个输出流的对象,因此当准备将一个对象写入到文件的时候,首先用outputstream的子类创建一个输出流。

例子如下

@Test
    public void ObjectOutputStreamTest(){
        ObjectOutputStream objectOutputStream = null;
        try {
            objectOutputStream = new ObjectOutputStream(new FileOutputStream("object.abt"));

            objectOutputStream.writeObject(new String("how are you"));
            objectOutputStream.flush();
            objectOutputStream.writeObject(new Cat("sda",2));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(objectOutputStream != null){
                try {
                    objectOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Test
    public void ObjectInputStreamTest(){
        ObjectInputStream objectInputStream = null;
        try {
            objectInputStream = new ObjectInputStream(new FileInputStream("object.abt"));
            String temp = (String) objectInputStream.readObject();
            System.out.println(temp);
            Cat cat = (Cat) objectInputStream.readObject();
            System.out.println(cat);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            if(objectInputStream != null){
                try {
                    objectInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

十缓冲流:

BufferedReader 和 BufferedWriter 类创建的对象成为缓冲输入,输出流。二者增强了读写文件的能力。比如Student.txt是一个学生的名单,每个姓名占一行。如果我们想读取名字,那么每次必须读入一行,但是我们不知道一行有多少个字符,File Reader就很难完成这样的任务。

Java提供了更高级的流:BufferedReader 流和BufferedWriter流,二者的源和目的地必须是字符输入流和字符输出流。因此,如果把文件字符输入流作为Buffer额度Reader的源,把文件字符输出流作为BufferedWriter流的目的地,那么,BufferedReader和BufferedWriter类创建的流比字符输入流和字符输出流有更强的读写能力,比如,BufferedReader 流就可以按行读取文件。

BufferedInputStream 字节输入缓冲流
构造方法
BufferedInputStream(InputStream in)     创建 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。 
BufferedInputStream(InputStream in, int size)     创建具有指定缓冲区大小的 BufferedInputStream,并保存其参数,即输入流 in,以便将来使用。

BufferedOutputStream 字节输出缓冲流
构造方法
BufferedOutputStream(OutputStream out)     创建一个新的缓冲输出流,以将数据写入指定的基础输出流。
BufferedOutputStream(OutputStream out, int size)     创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的基础输出流。

flush() 和 close()

flush 是从缓冲区把文件写出,

close 是将文件从缓冲区内写出并且关闭相应的流。

缓冲流的数据存储在缓冲区,所以必须强行的将数据从缓冲区写出,否则可能无法写出是数据。

BufferedReader 字符输入缓冲流
构造方法

BufferedReader(Reader in)     创建一个使用默认大小输入缓冲区的缓冲字符输入流
BufferedReader(Reader in, int sz)     创建一个使用指定大小输入缓冲区的缓冲字符输入流。
 

BufferedWriter 字符输出缓冲流
构造方法
BufferedWriter(Writer out)     创建一个使用默认大小输出缓冲区的缓冲字符输出流。 
BufferedWriter(Writer out, int sz)     创建一个使用指定大小输出缓冲区的新缓冲字符输出流。 

常用方法:

方法名    说明
int read()    读取单个字符
int read(char[] cbuf, int off, int len)    读取一部分到数组中
String readLine()    读取一个文本行
boolean ready()    判断此流是否准备读取
long skip(long n)    跳过指定字符并返回跳过了多少个字符
void close()    关闭此流并释放所有系统资源
void reset()    将此流重置到最新的标记
void mark(int readAheadLimit)    标记此流的位置
boolean markSupported()    判断此流是否支持 mark() 操作(它一定支持)

方法名    说明
void write(int c)    写入单个字符
void write(char[] cbuf, int off, int len)    写入字符数组的一部分到缓冲流中
void write(String s, int off, int len)    写入字符串的一部分到缓冲流中
void newLine()    写入一个行分割符
void close()    关闭此流以及系统缓存
void flush()    刷新此流

十一:使用Scanner解析文件:

借助Scanner类和正则表达式来解析文件,比如,要解析出文件中特殊字符,数字等信息。

使用Scanner类和正则表达式来解析文件的特点就是以时间换取空间,虽然解析的速度会变慢,但节省内存。

创建Scanner对象,并且指向要解析的文件:

File file = new File("Hello.java");

Scanner sc = new Scanner(file);

scanner类中常用的方法:

这里写图片描述

Scanner 类的作用
Scanner类可以方便地读取从控制台、文件等输入流中读取基本类型和字符串。Scanner类可以读取int、long、float、double和String等基本类型。它还可以使用正则表达式读取符合模式的文本。

Scanner类有多种构造函数,可以接受多种类型的输入流,包括标准输入流(System.in)、文件输入流(FileInputStream)等。在构造Scanner对象时,可以指定字符集和语言环境,以支持不同的语言和字符集。

Scanner类提供了一系列的方法来读取不同类型的数据。例如,nextInt()可以读取一个整数,nextDouble()可以读取一个双精度浮点数,nextLine()可以读取一行文本等等。此外,Scanner类还提供了hasNext()和hasNextLine()等方法,用于检测是否还有更多的数据可以读取。
 

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
 
public class ScannerDemo {
    public static void main(String[] args) {
        File file = new File("input.txt");
        try {
            Scanner scanner = new Scanner(file);
 
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                System.out.println(line);
            }
 
            scanner.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

十二:文件锁

经常出现几个程序同时处理同一个文件的情景,比如同时更新或者读取文件。应对这样的问题做出处理,否则可能发生混乱。JDK1.4版本后,Java提供了文件锁的功能,可以帮助解决这样的问题。

FileLock 和 FileChannel 类分别在java.nio和java.nio.channels包中。输入输出流读写文件时候可以使用文件锁,一下结合RandomAccessFile类来说明文件锁的使用方法。RandomAces是File创建的流在读写文件时候可以使用文件锁,那么只要不解除该锁,其他程序无法操作被锁定的文件。

1:首先使用RandomAccessFile流建立指向文件的流对象,该对象的读写属性必须是rw,

例如:

RandomAccessFile input =new RandomAccessFile(“Example.java","rw");

2.input流调用方法getChannel()获得一个连接到底层文件的File Channel 对象(信道);

例如:FileChannel channel=input.getChannel();

3信道调用tryLock()或者lock()的方法获得一个FileLock(文件锁)对象,这一过程也被称作对文件加锁,例如:

FileLock lock =channel.tryLock();

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

public class Main {
  public static void main(String[] args) throws Exception {
    RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");
    FileChannel fileChannel = raf.getChannel();
    FileLock lock = null;
    try {
      lock = fileChannel.lock(0, 10, true);

    } catch (IOException e) {
      // Handle the exception
    } finally {
      if (lock != null) {
        try {
          lock.release();
        } catch (IOException e) {
          // Handle the exception
        }
      }
    }

  }
}

十三:序列化与对象克隆:

有时想得到对象的一个”复制品“,复制品实体的变化 不会引起原对象实体发生变化,反之亦然。这样的复制品成为原对象的一个克隆对象或者简称克隆对象。

使用对象流很容易获取一个序列化对象的克隆,只需要将该对象写入对象输出流指向的目的地,然后将目的地作为一个对象输入流的源,那么该对象输入流从源中读回的对象一定是原对象的一个克隆,即对象输入流通过对象的序列化信息来得到当前对象的一个克隆。

import java.io.Serializable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

class Person implements Serializable {
  private String name = "Unknown";
  private String gender = "Unknown";
  private double height = Double.NaN;

  public Person(String name, String gender, double height) {
    this.name = name;
    this.gender = gender;
    this.height = height;
  }

  @Override
  public String toString() {
    return "Name: " + this.name + ", Gender:   " + this.gender + ",  Height: "
        + this.height;
  }
}

public class Main {
  public static void main(String[] args) {
    Person p1 = new Person("John", "Male", 1.7);
    Person p2 = new Person("Wally", "Male", 1.7);
    Person p3 = new Person("Katrina", "Female", 1.4);

    File fileObject = new File("person.ser");

    try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(
        fileObject))) {

      oos.writeObject(p1);
      oos.writeObject(p2);
      oos.writeObject(p3);

      // Display the serialized objects on the standard output
      System.out.println(p1);
      System.out.println(p2);
      System.out.println(p3);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

https://blog.csdn.net/makersy/article/details/90378813http://xn--jhqu2fpr25ab21anxdeo0iw7q

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值