`
yuyututuw
  • 浏览: 27848 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

JAVA I / O操作与字节流

阅读更多

JAVA I / O操作与字节流
2010年08月17日
  第7课 JAVA I / O操作与字节流 File类 一个File类的对象,表示了磁盘上的文件或目录 File类提供了与平台无关的方法来对磁盘上的文件或目录进行操作。 创建文件或目录 利用File类型的对象向磁盘创建一个文件。 import java.io.File; import java.io.IOException; public class FileTest { public static void main(String[] args) throws IOException { File f = new File("java.txt");// 定义一个File类型的对象变量 f.createNewFile();// 创建一个标准文件 } } 编译运行: 利用File类型的对象向磁盘创建一个目录。 import java.io.File; import java.io.IOException; public class FileTest { public static void main(String[] args) throws IOException { File f = new File("java.txt");// 默认是在当前路径下创建文件 // f.createNewFile();// 创建一个文件 f.mkdir();// 创建一个目录 } } 编译运行结果如下: 在绝对路径下创建文件或目录 package io; import java.io.File; import java.io.IOException; public class FileTest { public static void main(String[] args) throws IOException { File f = new File("G:\\java.txt");// 在绝对路径下创建文件。指定G盘 // f.createNewFile();// 创建一个文件 f.mkdir();// 创建一个目录 } } 编译运行结果如下: 注意: File f = new File("G:\\java.txt");// 这一句代码在LINUX系统下是不能使用的,因为Linux并没有盘符的概念。 这一句代码中,使用了"\\"。在java中"\"被作为转义字符。第一根反斜杠成功将第二根反斜杠转义。其实下面这种做法也是对的。 File f = new File("G:/java.txt");// 一根正斜杠解决问题,我强烈推荐就用一根正斜杠 删除文件或目录 语法:File类型变量.delete(); import java.io.File; import java.io.IOException; public class FileTest { public static void main(String[] args) throws IOException { File f = new File("G:/java.txt"); // f.createNewFile();// 创建一个文件 f.mkdir();// 创建一个目录 f.delete();// 删除文件或目录 } } 编译运行: 起初已经创建了一个目录java.txt,现在调用delete方法,那么G盘下就不存在该文件了。 delete()和deleteOnExit()的区别:当delete()被调用的时候就删除文件或目录。当程序中止的时候才调用deleteOnExit()方法来删除文件或目录。 package io; import java.io.File; import java.io.IOException; public class FileTest { public static void main(String[] args) throws IOException, InterruptedException { File f = new File("G:/java.txt");// 在绝对路径下创建文件。 // f.createNewFile();// 创建一个文件 f.mkdir();// 创建一个目录 // f.delete();// 删除文件或目录 f.deleteOnExit(); Thread.sleep(3000); // 让线程睡眠3秒钟,之后程序退出,看见目录被删除。 } } 编译运行: 当线程睡眠3秒钟之后,这个程序就退出了,于是现在目录被删除了。 deleteOnExit()的好处:有时候在程序运行的时候可能会产生一些临时文件,但是当退出程序的时候,这些临时文件就没有用了,此时给机子留下了这些垃圾,那么就让程序退出的时候删除这些临时文件吧! 在缺省的临时文件夹下产生临时文件:public static File createTempFile(String prefix,String suffix)。两个参数分别是指定文件的前缀名和后缀名。缺省的临时文件所在位置可以通过环境变量的Temp来查看。 在指定文件夹下面创建临时文件: public static File createTempFile(String prefix,String suffix,File directory) package io; import java.io.File; import java.io.IOException; public class FileTest { public static void main(String[] args) throws IOException, InterruptedException { File f = new File("G:/java.txt");// 在绝对路径下创建文件。 // f.createNewFile();// 创建一个文件 f.mkdir();// 创建一个目录 for (int i = 0; i 输入流(InputStream)和输出流(OutputStream)。可从中读出一系列字节的对象称为输入流。而能向其中写入一系列字节的对象称为输出流。 流的分类 节点流:从特定的地方读写的流类,例如:磁盘或一块内存区域。 过滤流:使用节点流作为输出或输入。过滤流是使用一个已经存在的输入流或输出流连接创建的。 InputStream 三个基本的读方法一. abstract int read(): 读取一个字节数据,并返回读到的数据,如果返回-1,表示独到了流的末尾。注意:如果要打印读到的数据,则需要强制类型转换成(char),如果直接打印,那么得到的 就是数字。二. int read(byte[] b):将数据读入一个字节数组,同时返回读取的字节数。如果返回-1,表示读到了输入流的末尾。三. int read(byte[] b,int off,int len):将数据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。off指定在数组b中存放数据的起始偏移位置;len指定读取的最大字节数。 OutputStream 三个基本的写方法一. abstract void write(int b): 往输出流中写入一个字节。二. void write(byte[] b): 往输出流中写入数组b中的所有字节。三. void write(byte[] b,int off,int len):往输入流中写入数组b中从偏移量off开始的len个字节的数据。 其它方法一.void flush():刷新输出流,强制缓冲区中的输出字节被写出。二.void close: 就是关闭输出流。 System.out是向标准设备上输出数据。比如屏幕,out是一个对象,out的类型是PrintStream。out可以被System调用,是因为它是System类当中的静态字段。 java.io.OutputStream java.io.FilterOutputStream java.io.PrintStream static PrintStream out "标准"输出流。 既然out的类型是PrintStream,所以out也有write 方法往输入流中写入一个字节。 System.in是从标准设备上读入数据。比如键盘,扫描仪。in的类型是InputStream。所以它有一些读取的方法。 根据以上的介绍,那么就可以先从键盘上写入数据,然后往标准设备(屏幕)上打印这些数据。 import java.io.IOException; public class StreamTest { public static void main(String[] args) throws IOException { System.out.println("请输入数据:"); int data; while ((data = System.in.read()) != -1) {// 读取一个字节的数据,返回值是一个整型,data接收字节。 // 返回-1,则表示到了流的末尾。 System.out.write(data);// 如果返回!=-1,那么就打印出 } } } 编译运行: 基本的流类 FileInputStream和FileOutputStream 节点流,用于从文件中读取或往文件中写入字节,如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。 原来我想为什么不使用OutputStream,而要使用FileOutputStream呢?现在看了JDK帮助文档才知道OutputStream是一个抽象类,它是输出字节流的所有类的超类,它需要子类至少书写一种可以写入输出字节的方法。 FileOutputStream演示 package io; import java.io.FileOutputStream; import java.io.IOException; public class StreamTest { public static void main(String[] args) throws IOException { System.out.println("请输入数据:"); FileOutputStream fos = new FileOutputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/test. txt"); /* * write()要么是写入一个字节数组,要么是写入一个字节,没有写入字符串的一种方法, * 但是String有一个getBytes()方法,getBytes()可以返回一个字节数组。 */ fos.write("大家好".getBytes()); fos.close();// 关闭输出流。 } } 编译运行如下: FileInputStream演示 package io; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class StreamTest { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/Hello .java"); byte[] buf = new byte[100]; // 定义一个字节数组 /* * 在读取数据的时候,不一定就读取了100个字节,在这个字节数组当中可能有一些无用的数据,因此在构造 * String的时候不能直接用String(byte[] bytes)去构造,需要使用String类的另外一个构造方法, * String(byte[] bytes, int offset, int length) ,指定一个字节数组,然后指定从这个字节 * 数组中off位置开始,然后指定长度len */ int len = fis.read(buf); // 返回实际读到的数据的长度。保存在len中 System.out.println(new String(buf, 0, len));// 非常重要 fis.close();// 关闭输入流 } } package io; public class Hello { public static void main(String[] args) { System.out.println("Are you ok"); System.out.println(); } } 编译运行StreamTest类: 为什么没有显示完整呢?这是因为Hello.java的size:149bytes,而这里给的是100。 public int read(byte[] b)从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。在某些输入可用之前,此方法将阻塞。 其实它的意思应该是这样的: 在定义数组byte[] buf = new byte[100]的时候,此时它还没有与文件建立任何关系,然而在fis.read(buf)的时候,它们就联系起来了,相当于fis找到了一个容器,如果buf.length不是0,那么文件的内容放在这个byte数组中,所以在放入数据之前就应该设定该数组的大小,也并不一定文件的全部内容都能保存到该byte数组中,该数组也最大只能保存b.length个字节。 BufferedInputStream和BufferedOutputStream 过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的效率。BufferedInputStream派生自java.io.FilterInputStream,并不是InputStream。在后面将看到BufferedReader派生自Reader,而不是派生自FilterReader,这个可能是SUN公司在设计上的一个小bug吧!BufferedInputStream的构造函数有BufferedOutputStream(OutputStream out),之所以说它需要一个已经存在的输入节点流,就是因为构造函数的参数类型是OutputStream,然而FileOutputStream派生自OutputStream。所以可以把FileOutputStream类型的对象放进去。 BufferedOutputStream package io; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class StreamTest { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/test. txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); bos.write("大家好".getBytes()); _____ } } 编译运行 此时在文件中并没有数据,这是怎么回事呢?BufferOutputStream提供了一个缓冲区,写入的数据首先是放在这个缓冲区,等缓冲区满了之后才向硬盘写入数据。然而这里写入缓冲区的数据并没有填满缓冲区。所以不能向硬盘写入数据。这时想要往硬盘写入数据 ,就可以使用flush()强制写入到硬盘上。 修改代码如下: package io; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class StreamTest { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/test. txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); bos.write("大家好".getBytes()); bos.flush(); } } 再次编译运行: 好了,输出了。 其实,关闭输出流也可以使数据强制输出。close()。 package io; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class StreamTest { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/test. txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); bos.write("大家好".getBytes()); bos.close(); fos.close(); // bos.flush(); } } 编译运行: BufferedInputStream 它的描述跟BufferedOutputStream相类似。 package com.io; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { File f = new File( "C:/Documents and Settings/Administrator/workspace/demo/src/com/io/C onsumer.java"); FileInputStream fis = new FileInputStream(f); //获取文件大小,返回值为long。 int i = (int)f.length(); byte[] buf = new byte[i];// 定义一个字节数组 BufferedInputStream bis = new BufferedInputStream(fis); int len = bis.read(buf); System.out.println(new String(buf, 0, len)); // 没有必要声明len,因为len的长度就是文件的大小i,只需要传递i的值就可以了。 bis.close(); } } 编译运行: 关闭流遵照先打开后关闭。其实,关闭流也可以直接就关闭过滤流。这样和它相关的流也就被关闭了。也就是关闭最底层的流就可以了。 注意:BufferedInputStream中没有像BufferedOutputStream中的flush()方法 DataInputStream和DataOututStream 过滤流,需要使用已经存在的节点流来构造,提供了读写java中的基本数据类型的功能。 public class DataOutputStream extends FilterOutputStream implements DataOutput DataOutputStream的使用方法 package io; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; public class StreamTest { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/test. txt"); BufferedOutputStream bos = new BufferedOutputStream(fos); DataOutputStream dos = new DataOutputStream(bos); byte b = 1; int i = 2; char c = 'c'; float f = 2.2f; dos.writeByte(b); dos.writeInt(i); dos.writeChar(c); dos.writeFloat(f); dos.close(); } } 编译运行: c@掏 ,看不懂,但是计算机能看懂。 DataOututStream的构造方法: DataOutputStream(OutputStream out) 创建一个新的数据输出流,将数据写入指定基础输出流。 它需要传递的参数类型是OutputStream,因为OutputStream被作为参数传递给了BufferedOutputStream,所以也就可以将BufferedOutputStream作为参数传递给DataOutputStream,这样就串在了一起。 DataInputStream和DataOututStream的联合使用 package io; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class StreamTest { public static void main(String[] args) throws IOException { File f = new File("C:/Documents and Settings/Administrator/workspace/demo/src/io/test. txt"); FileOutputStream fos = new FileOutputStream(f); BufferedOutputStream bos = new BufferedOutputStream(fos); DataOutputStream dos = new DataOutputStream(bos); byte b = 1; int i = 2; char c = 'c'; float f = 2.2f; dos.writeByte(b); dos.writeInt(i); dos.writeChar(c); dos.writeFloat(f); dos.close(); FileInputStream fis = new FileInputStream(f); BufferedInputStream bis = new BufferedInputStream(fis); DataInputStream dis = new DataInputStream(bis); System.out.println(dis.readByte());// 注意读入数据的顺序要和写入数据的顺序相同 System.out.println(dis.readInt()); System.out.println(dis.readChar()); System.out.println(dis.readFloat()); dis.close(); } } 编译运行如下: PipedInputStream和PipedOutputStream 管道流,用于线程间的通信。一个线程的PipedInputStream对象从另外一个线程的PipedOutputStream对象读取输入。要使管道流有用,必须同时构造管道输入流和管道输出流。 Producer.java package com.io; import java.io.IOException; import java.io.PipedOutputStream; public class Producer extends Thread { private PipedOutputStream pos; public Producer(PipedOutputStream pos) { this.pos = pos; } @Override public void run() { super.run(); try { pos.write("Hello".getBytes()); } catch (IOException e) { e.printStackTrace(); } } } Consumer.java package com.io; import java.io.IOException; import java.io.PipedInputStream; public class Consumer extends Thread { private PipedInputStream pis; public Consumer(PipedInputStream pis) { this.pis = pis; } @Override public void run() { super.run(); byte[] b = new byte[100]; // 将数据保存在byte数组中 try { int len = pis.read(b); // 从数组中得到实际大小。 System.out.println(new String(b, 0, len)); pis.close(); } catch (IOException e) { e.printStackTrace(); } } } PipedStreamTest.java package com.io; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; public class PipedStreamTest { public static void main(String[] args) { PipedOutputStream pos = new PipedOutputStream(); PipedInputStream pis = new PipedInputStream(); try { pos.connect(pis);// 连接管道 new Producer(pos).start();// 启动线程 new Consumer(pis).start();// 启动线程 } catch (IOException e) { e.printStackTrace(); } } } Reader和Writer java.io.Reader | +--java.io.InputStreamReader Java程序语言使用Unicode来表示字符串和字符。 Reader和Writer这两个抽象类主要用来读写字符流。 InputStreamReader是一个从字节流转换到字符流的桥。 OutputStreamWrite是一个从字符流转换到字节流的桥。 package io; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; public class ReaderWriterTest { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/test. txt"); OutputStreamWriter osw = new OutputStreamWriter(fos);// 充当字符流到字节流桥梁的作用。 // osw.write("你们好么?"); // osw.close(); // 通常很少直接用OutputStreamWriter去进行写入操作,通常使用BufferedWriter进行写入操作,以此输入提高效率。 BufferedWriter bw = new BufferedWriter(osw); bw.write("大家好"); bw.close(); } } 编译运行: BufferedWriter 的构造函数有:BufferedWriter(Writer out),参数是Writer类型的。而OutputStreamWriter又派生自Writer。所以可以将OutputStreamWriter的对象作为参数传递进去。 package io; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; public class ReaderWriterTest { public static void main(String[] args) throws IOException { FileOutputStream fos = new FileOutputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/test. txt"); OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");// 充当字符流到字节流桥梁的作用。 // osw.write("你们好么?"); // osw.close(); // 通常很少直接用OutputStreamWriter去进行写入操作,通常使用BufferedWriter进行写入操作,以此输入提高效率。 BufferedWriter bw = new BufferedWriter(osw); bw.write("大家好"); bw.close(); FileInputStream fis = new FileInputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/test. txt"); InputStreamReader isr = new InputStreamReader(fis); BufferedReader br = new BufferedReader(isr); System.out.println(br.readLine());// readLine()读取一行数据。 br.close(); } } 编译运行如下: 利用这个BufferedWriter和BufferedReader就可以完成从标准输入设备上读取字符流,和按行读取字符流。 package io; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class ReaderWriterTest { public static void main(String[] args) throws IOException { InputStreamReader isr = new InputStreamReader(System.in);// 从标准输入设备上读取数据 BufferedReader br = new BufferedReader(isr); String strLine; while ((strLine = br.readLine()) != null) { System.out.println(strLine);// 向标准输出设备上打印数据 } br.close();// 关闭输入流 } } 编译运行: Print流 printWriter和printStream都属于输出流,分别针对与字符和字节 printWriter和printStream提供了重载的print println方法用语多种数据类型的输出。 printWriter和printStream输出的操作不会抛出异常,用户通过检测错误状况获取错误信息。 printWriter和printStream有自动的flush功能。 PrintWriter(Writer out) PrintWriter(Writer out, boolean autoFlush) PrintWriter(OutputStream out) PrintWriter(OutputStream out, boolean autoFlush) PrintStream(OutputStream out) PrintStream(OutputStream out, boolean autoFlush) 在java语言当中,当我们将一个字节转换为一个字符的时候,那么这个字符是用unicode表示的,这个过程叫做解码。将一个unicode码转换为一个本地字符集所表示的代码,那么这个过程叫做编码。InputStreamReader将读到的字节解码为字符。获取一个unicode就是解码过程。Java中字符和字符串都是采用unicode来表示的。构造一个字符或者字符串这个就是属于一个解码过程。将字符或者字符串转换成为字节,这个过程就是属于编码。 利用线程的函数从数据库中读取一个记录,以字符串的形式返回,我们知道数据库存储的这个记录是中文的,也就是中文所对应的GBK码。然而当我们将字符串打印出来的时候,看到的却是乱码。可能就是这个函数在将字节解码为字符串的时候采用了其它的字符集。例如:ISO-8859-1,当我们用System.out打印这个字符串的时候,因为这个out对象在我们的这个中文系统平台上,是采用GBK字符集所创建的,打印的时候它会将我们的这个字符串编码为字节数组,然后打印,那么看到的就是乱码,那么就应该将得到的字符串按照ISO-8859-1再次编码为字节数组。这样就得到了中文字符原先的gbk码。然后再用GBK字符集解码为字符串。就ok了。 在OutputStreamWriter中有一个类叫做CharSet,在这个类中有一个public static SortedMap availableCharsets() 方法。可以获得当前java虚拟机可以使用字符集的排过序的map package io; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Map; import java.util.Set; public class CharSetTest { public static void main(String[] args) { Map m = Charset.availableCharsets(); Set names = m.keySet(); Iterator it = names.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } } 编译运行: 在java语言当中,将一个字节转换成一个字符的过程叫做解码。这个字符是用unicode来表示的。 在java语言中,将一个字符集转换成一个字节的过程叫做编码。 RandomAccessFile RandomAccessFile类同时实现了DataInput和DataOutput接口,提供了对文件随机存取的功能,利用这个类可以在文件的任何位置读取或写入数据。可以对java中基本数据类型进行读写。 public class RandomAccessFile extends Object implements DataOutput, DataInput, Closeable 例如:读boolean,读byte… … boolean readBoolean() 从此文件读取一个 boolean。 byte readByte() 从此文件读取一个有符号的八位值。 char readChar() 从此文件读取一个字符。 写boolean,写byte … … void writeBoolean(boolean v) 按单字节值将 boolean 写入该文件。 void writeByte(int v) 按单字节值将 byte 写入该文件。 void writeBytes(String s) 按字节序列将该字符串写入该文件。 RandomAccessFile类提供了一个文件指针,用来标志要进行读写操作的下一数据的位置。在RandomAccessFile类中写入字符有3种方式: public final void writeBytes(String s):将字符的两个字节数据的第一个字节写入到文件当中,第二个字节就舍弃了,不适宜中文,不建议使用。 public final void writeChars(String s):将两个字节表示的字符全部写入到文件当中,也就是按照unicode写入文件。 public final void writeUTF(String str):适宜中文。建议使用。 package io; import java.io.IOException; import java.io.RandomAccessFile; public class RandomFileTest { public static void main(String[] args) throws IOException { Student s1 = new Student(1, "zhangsan", 98.5); Student s2 = new Student(2, "lisi", 58.5); Student s3 = new Student(3, "wangwu", 56); RandomAccessFile raf = new RandomAccessFile( "C:/Documents and Settings/Administrator/workspace/demo/src/io/stude nt.txt", "rw"); s1.writeStudent(raf); s2.writeStudent(raf); s3.writeStudent(raf); raf.close(); } } class Student { int num; String name; double score; public Student(int num, String name, double score) { super(); this.num = num; this.name = name; this.score = score; } public void writeStudent(RandomAccessFile raf) throws IOException { raf.writeInt(num); raf.writeUTF(name); raf.writeDouble(score); } } 编译运行: 将该文件打开: package io; import java.io.IOException; import java.io.RandomAccessFile; public class RandomFileTest { public static void main(String[] args) throws IOException { Student s1 = new Student(1, "zhangsan", 98.5); Student s2 = new Student(2, "lisi", 58.5); Student s3 = new Student(3, "wangwu", 56); RandomAccessFile raf = new RandomAccessFile( "C:/Documents and Settings/Administrator/workspace/demo/src/io/stude nt.txt", "rw"); s1.writeStudent(raf); s2.writeStudent(raf); s3.writeStudent(raf); // 读取数据 Student s = new Student(); // raf.seek(0); /* * public long length() throws IOException Returns the length of this * 在读取学生信息的时候,我们并不知道它一次要读取多少信息。但是文件指针可以指向下一个将要读取的位置。 * 也就是可以返回当前文件的偏移量 getFilePointer()获取文件指针。不管是读取还是写入,文件指针都会跟着移动。读取完一个学生信息,那么文件指针就指向下一个学生。 */ for (long i = 0; i read or write occurs. The offset may be set beyond the end of the file. Setting the offset beyond the end of the file does not change the file length. The file length will change only by writing after the offset has been set beyond the end of the file. 上面代码修改如下: package io; import java.io.IOException; import java.io.RandomAccessFile; public class RandomFileTest { public static void main(String[] args) throws IOException { Student s1 = new Student(1, "zhangsan", 98.5); Student s2 = new Student(2, "lisi", 58.5); Student s3 = new Student(3, "wangwu", 56); RandomAccessFile raf = new RandomAccessFile( "C:/Documents and Settings/Administrator/workspace/demo/src/io/stude nt.txt", "rw"); s1.writeStudent(raf); s2.writeStudent(raf); s3.writeStudent(raf); // 读取数据 Student s = new Student(); raf.seek(0);// 设置文件指针的偏移量 for (long i = 0; i 不能和其他的流混合使用。 对象序列化 将对象转换成字节流保存起来,并在日后还原这个对象,这种机制叫做对象序列化。 将一个对象保存到永久存储设备上成为持续性。 一个对象要实现序列化,必须实现Serializable接口或Externalizable接口。 Serializable是一个标识接口(没有任何的方法。)对象只需要实现这个接口。 Serializable是Externalizable的父接口。 要实现对象的序列化,可以利用java.io包当中的两个类:ObjectOutputStream和ObjectInputStream。 ObjectOutputStream实现了DataOutput接口,所以它能够往输出流当中写入java基本数据类型。这个类当中的public final void writeObject(Object obj)方法很重要,可以写入一个指定的对象到对象的输出流当中,这个方法就是用来完成对象的序列化的,它不是在DataOutput中声明的。ObjectInputStream介绍和ObjectOutputStream相对应。 当我们反序列化一个对象时,它并不会调用这个对象当中的任何构造方法,它仅仅是根据我们所保存的对象的状态信息重新在内存当中构建这个对象。 package io; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class ObjectSerializableTest { public static void main(String[] args) throws IOException, ClassNotFoundException { Employee e1 = new Employee("zhangsan", 20, 3653.0); Employee e2 = new Employee("lisi", 22, 3343.0); Employee e3 = new Employee("wangwu", 24, 3643.0); // 构造对象输出流 FileOutputStream fos = new FileOutputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/Emplo yee.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(e1); oos.writeObject(e2); oos.writeObject(e3); oos.close(); // 构造对象输入流 FileInputStream fis = new FileInputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/Emplo yee.txt"); ObjectInputStream ois = new ObjectInputStream(fis); Employee e; for (int i = 0; i 不能保存任何的成员方法和静态的成员变量。(我突然有这样的想法,对象序列化就是与对象有关的才可以被序列化,而静态成员是属于类本身的,与对象无关,所以它不给保存。但是为什么方法不被保存,这个我就有点不明白了。) 如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。 如果一个可序列化的对象包含对某个不可序列化的对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。我们可以将这个引用标记为transient,那么对象仍然可以序列化。线程类对象就是一个不可序列化对象。 package io; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; public class ObjectSerializableTest { public static void main(String[] args) throws IOException, ClassNotFoundException { Employee e1 = new Employee("zhangsan", 20, 3653.0); Employee e2 = new Employee("lisi", 22, 3343.0); Employee e3 = new Employee("wangwu", 24, 3643.0); // 构造对象输出流 FileOutputStream fos = new FileOutputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/Emplo yee.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(e1); oos.writeObject(e2); oos.writeObject(e3); oos.close(); // 构造对象输入流 FileInputStream fis = new FileInputStream( "C:/Documents and Settings/Administrator/workspace/demo/src/io/Emplo yee.txt"); ObjectInputStream ois = new ObjectInputStream(fis); Employee e; for (int i = 0; i  al = new ArrayList(); al.add(s1); al.add(s2); al.add(s3); ser(al); al = dser(); for (int i = 0; i 输入流 FileInputStream fis = new * FileInputStream("G:/root/a.txt"); ObjectInputStream ois = new * ObjectInputStream(fis); Student s; for (int i = 0; i  al) throws Exception { File f = new File("G:/root/a.txt"); FileOutputStream fos = new FileOutputStream(f); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(al); oos.close(); } @SuppressWarnings("unchecked") public static ArrayList dser() throws Exception { File f = new File("G:/root/a.txt"); FileInputStream fis = new FileInputStream(f); ObjectInputStream ois = new ObjectInputStream(fis); ArrayList al = (ArrayList) ois.readObject(); ois.close(); return al; } } 
分享到:
评论

相关推荐

    Java I/O 第二版

    OReilly.Java.I.O.2nd.Edition.May.2006 Java的io包主要包括: 1. 两种流:字节流(byte Stream)和字符流(character stream),这两种流不存在所谓的谁代替谁、谁比谁高级之说,它们互为补充,只是侧重点不同...

    Java I/O编程 java

    数据流的概念及输入输出方法 字节流和字符流 文件、文件流 随机访问文件 过滤流 管道流 对象流 数据流小结

    I/O流复制文档或者歌曲等

    Java I/O字符流复制文档,字节流复制歌曲等 自己定义

    java文件与I/O流

    高效的课件,详细的内容介绍,针对性的代码展示,提高性的练习题目。适合新手或者基础薄弱人员学习,一个PPT解决你编程中常见的错误,最重要的是一人下载多人使用,不受限制,没有隐藏密码

    Java中I/O流对文件进行复制粘贴及可能会出现的问题

    需求:将E:\电脑桌面壁纸... //创建字节输入流对象,关联数据源文件路径 FileInputStream fis = new FileInputStream("E:\\电脑桌面壁纸\\MisakaMikoto.jpg"); //创建字节输出流对象,关联目的地文件路径 FileOutputSt

    java IO流总结.md

    java I/O流的总结 1.操作数据单位:字节流、字符流 对于文本文件(.txt,.java,.c,.cpp),使用字符流处理 对于非文本文件(.jpg,.mp3,.mp4,.avi,.doc,.ppt,...),使用字节流处理 2.数据的流向:输入流、输出流 ...

    IO流的使用,自己的心得

    * 用缓存的字节入做写入操作 * */ @Test public void testOutPut(){ String filePath = "F://test1.txt"; String writeString = "testOutPut:1231"; int tempLength = 2; StringBuffer bs = new ...

    Java输入与输出(I、O).

    Java输入输出合集。 File类 RandomAccessFile类 Scanner类 字节流:IputStream类 等等等等

    基础深化和提高-IO流技术学习大全

    I/O流主要分为两种类型:字节流和字符流。 字节流: 字节输入流(InputStream)和字节输出流(OutputStream):用于处理二进制数据,以字节为单位进行读写。常见的实现类包括FileInputStream、FileOutputStream等...

    Java I/O输入输出流详解

     文件操作的时候一定要记得关闭!!!!!!!!  ASCII:美国标准信息交换码,用一个字节的7位可以表示一个字符  ISO8859-1:拉丁码表,西欧标准字符集,用一个字节的8位表示  GB2312:中文编码表,用两个...

    I/O程序的设计 设计语言java

    1.显示一个“打开”文件对话框,并选择一个文件 2.从字节流、字符流、随机访问文件3种方式选择一种完成对该文件的复制 3.检查复制后的文件内容与原文件是否一致

    java_I\O学习笔记

    java_I\O学习笔记 主要讲的是字节流以及缓冲流的操作

    java深度历险

    序 1 目录 2 JAVA字节代码的操纵 4 动态编译JAVA源文件 4 ...JAVA I/O 45 流 45 缓冲区 47 字符与编码 48 通道 49 参考资料 52 JAVA安全 53 认证 53 权限控制 55 加密、解密与签名 57 安全套接字连接 58 参考资料 59

    JAVA_API1.6文档(中文)

    javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I/O。 javax.management 提供 Java Management Extensions 的核心类。 javax.management.loading 提供实现高级动态加载的类...

    跟汤老师学Java(第15季):I/O输入输出流

     字节流、字符流  节点流、包装流 4.字节流  InputStream:FileInputStream、ByteArrayInputStream、ObjectInputStream  OutputStream:FileOutputStream、ByteArrayOutputStream、ObjectOutputStream 5....

    JAVA SE 开发手册.CHM

    1、JDK的安装和环境变里的配置 2. HelloWorld程序 3、JAVA的数据类型及转换 4、JAVA运算符 5、JAVA控制语句结构 6、JAVA数组及查找和排序 ...20、I0流之字符流、字节流、转换流、缓冲流、对象流 21,I0流之HIO

    java-io-guide:Java中的Java IO(输入和输出流)指南

    File示例列表,显示了使用Java I / O创建,读取,写入,修改文件以及获取文件信息的方法。 使用BufferInputStream读取文件 使用DataInputStream读取文件 以字节为单位获取文件大小KB MB GB TB 文件序列化示例 如何...

    java 面试常见问题整理

    泛型 Java 泛型了解么?什么是类型擦除?介绍一下常用的通配符? 常用的通配符有哪些? 你的项目中哪里用到了泛型? 反射 何为反射?...Checked Exception 和 Unchecked Exception ...既然有了字节流,为什么还要有字符流?

    Java 1.6 API 中文 New

    javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I/O。 javax.management 提供 Java Management Extensions 的核心类。 javax.management.loading 提供实现高级动态加载的类。...

    java jdk-api-1.6 中文 chmd

    javax.imageio.stream Java Image I/O API 的一个包,用来处理从文件和流中产生的低级别 I/O。 javax.management 提供 Java Management Extensions 的核心类。 javax.management.loading 提供实现高级动态加载的类...

Global site tag (gtag.js) - Google Analytics