Presentation is loading. Please wait.

Presentation is loading. Please wait.

Java Programming Spring, 2013

Similar presentations


Presentation on theme: "Java Programming Spring, 2013"— Presentation transcript:

1 Java Programming Spring, 2013

2 Java I/O java.io File Class RandomAccessFile Class
InputStream & OutputStream Reader & Writer FileInputStream & FileOutputStream FileReader & FileWriter BufferedStream

3 I/O 输入(Input)/输出(Output)系统,简称为I/O系统,
对于输入/输出问题,Java将之抽象化为流(Stream)对象来解决,对不同的输入/输出问题,提供了相应的流对象解决的方案。 流式输入输出的特点是数据的获取和发送沿数据序列的顺序进行,即每一个数据都必须等待排在它前面的数据,等前面的数据读入或送出之后才能被读写。

4 java.io 包 java.io包中定义与输入、输出流相关的类和接口,构成了Java语言的I/O框架。
java.io包中定义的各种各样的输入输出流类,它们都是Object类的直接或间接子类,每一个流类代表一种特定的输入或输出流。 import java.io.*;

5 流的类结构 java.io包的类层次结构: 以四个顶层抽象类为基础,衍生出系列具体的类来完成各种输入/输出。
InputStream,OutputStream:用于字节的读/写。 Reader,Writer:用于文本(字符)的读/写。 实际使用的是它们的子类的对象。 Object InputStream OutputStream Reader Writer File RandomAccessFile

6 File类 RandomAccessFile类
File handling File类 RandomAccessFile类

7 File类 Fundamental class: File
Represents either a file(文件) or a dir(文件夹) location in a file system. Through its pathname(路径名) A pathname Unix: /usr/java/bin/javac Windows: c:\java\bin\javac

8 Java文件路径的表示: Java约定是用UNIX和URL风格的斜线(/)来作路径分隔符;
如果用Windows/DOS所使用的反斜线( \ )的约定,则需要在字符串内使用它的转义序列( \\ )。 例: c:\\java\\bin\\javac (Windows/DOS) c:/java/bin/javac (UNIX和URL风格)

9 Example—separator(分隔符)
//显示分隔符 import java.io.*; public class Prova { public static void main(String[] arg) { System.out.println(File.separator+" - "+ File.separatorChar+" - "+ File.pathSeparator+" - "+ File.pathSeparatorChar); } Output (in Windows) \ - \ - ; - ; Output (in Unix): / - / - : - :

10 File类 java.io包中的File类提供了获得文件基本信息及文件操作的方法。
构造方法 File(String filename); File(String directoryPath, String filename); File(File f, String filename);

11 Example: 创建文件和文件夹 //创建文件夹 File file1 = new File("e:/java");
file1.mkdir(); //在目录中创建文件 File file2 = new File(file1,"test.txt"); file2.createNewFile();

12 File类的常用方法 操作文件属性的方法 public boolean canRead();判断文件是否是可读的。
public boolean canWrite();判断文件是否可被写入。 public boolean exists(); 判断文件是否存在。 public boolean isFile(); 判断文件是否是一个正常文件,而不是目录。 public boolean isDirectroy();判断文件是否是一个目录。

13 File类的常用方法 获取文件的名称、路径 public String getName():获取文件的名字。
public String getPath():得到文件的路径名。 public String getAbsolutePath():得到文件的绝对路径名。 public String getParent():得到文件的上一级目录名。

14 File类的常用方法 获取文件处理信息 public long length(): 获取文件的长度(单位是字节)。
public long lastModified():获取文件最后修改时间。 public boolean delete():删除文件。

15 File类的常用方法 目录(directory)操作 创建一个名为File的目录: 列出目录中的文件 在目录中创建文件
public boolean mkdir() 列出目录中的文件 public String[] list() public File[] listFiles() 在目录中创建文件 public boolean createNewFile()

16 Example: //创建文件夹 File file1 = new File(“e:/java”); //创建File对象
file1.mkdir(); //通过File对象创建文件夹 //在目录中创建文件 File file2 = new File(file1,"test.txt"); file2.createNewFile(); //通过File对象创建文件

17 //显示文件夹中所有文件的文件名 String[ ] files = file1.list(); for(int i = 0; i<files.length; i++) System.out.print(files[i]); //显示文件夹中所有文件的对象 File[ ] files = file1.listFiles(); for(int i = 0; i<files.length; i++) System.out.println(files[i].getName()+"\t"+ files[i].length());

18 Example 1 to test the methods of ‘File’
import java.io.File; public class TryFile { public static void main(String[] args) { // Create an object that is a directory File myDir = new File(“C:/jdk1.5.0/src/java/io”); System.out.println(myDir + (myDir.isDirectory() ? “ is” : “ is not”) + “ a directory.”); // Create an object that is a file File myFile = new File(myDir, “File.java”); System.out.println(myFile + (myFile.exists() ? “ does” : “ does not”) + “ exist”); System.out.println(myFile + (myFile.isFile() ? “ is” : “ is not”) + “ a file.”); System.out.println(myFile + (myFile.isHidden() ? “ is” : “ is not”) + “ hidden”); System.out.println(“You can” + (myFile.canRead() ? “ “ : “not “) + “read “ + myFile); System.out.println(“You can” + (myFile.canWrite() ? “ “ : “not “) + “write “ + myFile); }

19 文件的随机访问类(RandomAccessFile)
用来访问保存数据记录的文件; 数据记录是指对应于数据源中一行信息的一组完整的相关信息。 例如: 时间 地点 课程 班级 2013/04/02 1302教室 Java程序设计 数媒2011

20 文件的随机访问类(RandomAccessFile)
定义了对各种数据类型进行读写的方法,如:byte, char, double, float, int, short, long等。 可以用getFilePointer()方法获得当前的文件读取指针,可以用seek(long pos)方法访问记录,并进行读写。 getFilePointer():返回文件指针在文件中的当前偏移量。 seek(long pos): 设置从文件开头到文件指针的偏移量为pos,在偏移量pos的位置发生下一个读取或写入操作。

21 文件的随机访问类(RandomAccessFile)
RandomAccessFile(File file, String mode) RandomAccessFile(String name, String mode); 构造函数可能产生FileNotFoundException及IOException异常 mode r:只读; rw:可读可写 File file=new File(“d:\\lx\\a.txt”); RandomAccessFile rf=new RandomAccessFile( file, ”rw”) ; RandomAccessFile rfile=new RandomAccessFile(“d:\\lx\\a.txt”, ”rw”);

22 文件的随机访问类(RandomAccessFile)
读写数据的常用方法 读、写基本数据类型: readInt()、writeInt(int n)等; 读取文件中的一行: readLine(); 读、写UTF字符串: readUTF()、writeUTF(String str); UTF-8:8-bit Unicode Transformation Format,一种针对Unicode的可变长度字符编码 。

23 文件的随机访问类(RandomAccessFile)
文件随机读写流的读取指针控制 long getFilePointer(); 得到当前的文件读取指针。 void seek(long pos); 把指针从开始移动到pos位置。 long length(); 得到文件的长度(有多少个字节) 。 void setLength(long newLength); 重新设置文件的长度。

24 What is the stream (流) ? 流是数据的有序序列。 流可分为输入流和输出流(按流动方向) :
输入流指从某个数据来源输入Java应用程序的数据序列, InputStream和Reader处理输入 输出流指Java应用程序向某个数据目的地输出的数据序列, OutputStream和Writer处理输出

25 输入流、输出流 输入流、输出流分别如下图所示。 数据源 程序 输入流 输入流示意图 数据宿 程序 输出流 输出流示意图

26 System类和标准输入输出流 System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。System类在java.lang包中。 You do not instantiate the System class to use it. All of System's variables and methods are static variables and static cmethods. To use a class variable, you use it directly from the name of the class using Java's dot (.) notation.

27 标准流-- System Class //获得运行程序的电脑系统的用户名 class UserNameTest {
public static void main(String[] args) { String name; name = System.getProperty("user.name"); System.out.println(“Your name is “ + name); } Notice that the program never instantiates a System object. It just references the getProperty method and the out variable directly from the class.

28 标准流 System.in:表示系统的标准输入流对象,通常的环境下标准输入流指向键盘输入;
System.out:表示系统的标准输出流对象,通常环境下指向屏幕输出; System.err:表示系统的标准错误输出流对象,通常环境下也指向屏幕输出。 上述三个标准流由系统负责打开关闭,使用时不需要显式地打开或关闭。 System.out和System.err都用于输出,通常情况下: Syetem.out用于程序输出一般信息,而System.err用于输出错误信息和其他需要引起用户立即注意的信息。 在系统中,System.out具有缓冲机制,而System.err是没有缓冲的,这是两者之间的一个重要区别。

29 The Standard I/O Streams
Standard Input Stream System.in -- The System class provides a stream for reading text -- the standard input stream. Use System.in.read to read the input entered by user. Standard Output and Error Streams System.out -- The standard output stream is typically used for command output. System.err -- The standard error stream is typically used to display any errors that occur when a program is running. The print, println, and write Methods The print and println methods write their String argument to the screen. System.out.println("Duke is not a penguin!"); The write method is used to write bytes to the stream.

30 //DataTypePrintTest.java, println方法的重载
public class DataTypePrintTest { public static void main(String[] args) { String stringData = "Java Mania"; char[ ] charArrayData = { 'a', 'b', 'c' }; int integerData = 4; long longData = Long.MIN_VALUE; float floatData = Float.MAX_VALUE; double doubleData = Math.PI; boolean booleanData = true; System.out.println(stringData); System.out.println(charArrayData); System.out.println(integerData); System.out.println(longData); System.out.println(floatData); System.out.println(doubleData); System.out.println(booleanData); System.out.println(); }

31 javac TranslateByte.java java TranslateByte b B
//标准输入、输出 import java.io.*; class TranslateByte{ public static void main(String[] args) throws IOException{ byte from=(byte)args[0].charAt(0); byte to=(byte)args[1].charAt(0); int b; while((b=System.in.read())!=-1) //从键盘读入一个byte System.out.write(b==from ? to : b);//输出到屏幕 } javac TranslateByte.java java TranslateByte b B 输入:abracadabra! 输出:aBracadaBra! Args[0] Args[1]

32

33 标准输入输出示例: import java.io.*; public class StandardIO1{
public static void main(String []args) { int ch; System.out.println("请输入一行字符"); try{ //read in a byte from keybord while((ch=System.in.read())!='\r') System.out.write(ch); //写入标准输出流 }catch(IOException e){ System.out.println(e.toString()); } System.out.write('\n');

34

35 流的分类 字节流和字符流 节点流和处理流(按流的处理位置 ) InputStream和OutputStream处理8位字节流数据
Reader和Writer处理16位的字符流数据 节点流和处理流(按流的处理位置 ) 节点流:可以从或向一个特定的地方(节点)读写数据。如FileReader 。 处理流:使用节点流作为输入或输出。 处理流不直接与数据源或目标相连,而是与另外的流进行配合,对数据进行某种处理,例如: BufferedReader, InputStreamReader等。

36 字符流和字节流 java.io包中类和接口从功能上主要分为字符流类型和字节流类型
字符(character)流是指数据序列的基本构成单位是16位的Unicode字符数据,如:各类基于字符编码的纯文本文件。 字节(byte)流是指数据序列的基本构成单位是8位的字节数据,如:各类基于二进制数据的文件、图形图像文件。

37 文本文件(Text Files,纯字符文件) vs. 二进制文件(Binary Files)
纯文本文件是指的只包含纯文字和字符的文件,这些文字是没有格式的。 Example: ASCII (binary)文件: , , 记事本文件(.txt文件,默认ANSI编码 )。 Binary file: 非字符文件,如:图片、声音、word文档。 文件含有特殊的格式及计算机代码 。

38 字节流(Byte Streams) 字节流可分为输入字节流和输出字节流 抽象类 InputStream 用于表示所有输入字节流
抽象类 OutputStream 用于表示所有输出字节流

39 Byte Stream family System.in System.err System.out

40 InputStream和OuputStream两个抽象类的子类

41 InputStream类 该抽象类作为所有输入字节流类的基类,声明用于读取字节流数据的通用方法。
public abstract int read() throws IOException; public int read(byte[] buf, int offset, int count) throws IOException; public int read(byte[] buf) throws IOException; public long skip(long count) throws IOException; public int available() throws IOException; public void close() throws IOException; Every method here can throw an IOException; If a programmer uses any of these methods, he/she must catch IOException (or Exception);

42 How to do I/O import java.io.*; 所有的流类对象在使用前必须打开(即:创建),在使用后必须关闭。
Open the stream:创建流对象 Use the stream (read, write, or both) 通过流对象调用方法 Close the stream: 关闭流,释放I/O资源

43 InputStream类 创建InputStream类对象时,便自动打开了对象所表示的输入流;
InputStream所有与输入相关的方法声明抛出异常类IOException InputStream类的对象在完成数据输入后,除标准输入流类对象System.in外,必须调用close方法关闭输入流,通常可将该方法的调用放入finally语句块中

44 Example: Output: a 97 import java.io.*; public class StandardIO1{
public static void main(String []args) throws IOException { int b; InputStream stdin1= System.in; //声明输入字节流并指向标准输入流 try { b = stdin1.read( ); //使用流,从键盘读入一个字节 System.out.println((char)b); System.out.println(b); stdin1.close(); //关闭流 }catch(IOException ie) { System.out.println(); } Output: a 97

45 /***** HelloWorld.java *****/
import java.io.*; public class HelloWorld { public static void main( String[ ] args ) { byte[] ba = new byte[10]; InputStream stdin = System.in; System.out.println("Please input a string: "); try{ stdin.read(ba); //从键盘读入多个字节 }catch(IOException ie){ System.out.println(); }finally { } String s = new String(ba); System.out.println("The string read in is "+ s);

46 OutputStream类 当创建OnputStream类对象时,便自动打开了对象所表示的输出流。
OutputStream所有与输出相关的方法声明抛出异常类IOException OutputStream类的对象在完成数据输出后,除标准输出流对象System.out外,必须调用close方法关闭输出流

47 OutputStream类 该抽象类作为所有输出字节流类的基类,声明用于输出字节流数据的通用方法:
void write(int b) throws IOException public void write(byte[] buf, int offset, int count) throws IOException void write(byte[] b) throws IOException void flush() throws IOException void close() throws IOException

48 public abstract void write(int b)
OutputStream类 public abstract void write(int b) throws IOException 将指定的字节写入此输出流。 write 的常规协定是:向输出流写入一个字节。要写入的字节是参数 b 的八个低位。b 的 24 个高位将被忽略。 OutputStream 的子类必须提供此方法的实现。 OutputStream stdout = System.out; stdout.write(104); // ASCII ‘h’ ,一个字节 stdout.flush();

49 字符流(Character Streams)
字符流可分为输入字符流和输出字符流 抽象类 Reader 用于表示所有输入字符流 抽象类 Writer 用于表示所有输出字符流

50 Character Stream Family

51 Reader和Writer的主要子类如下:

52 Reader类 该抽象类作为所有输入字符流类的基类,声明用于读取输入字符文本数据的通用方法: public int read();
public abstract int read(char[] buf, int offset,int count); public int read(char[] buf); public long skip(long count); public int available(); public abstract void close();

53 Writer类 该抽象类作为所有输出字符流类的基类,声明用于输出字符文本数据的通用方法:
public void write(int ch); public abstract void write(char[] buf, int offset, int count); public void write(char[] buf); public void write(String str, int offset, int count); public void write(String str); public Writer append(char c) public Writer append(CharSequence csq) public Writer append(CharSequence csq, int start, int end) public abstract void flush(); public abstract void close();

54 文件的读写 FileOutputStream/FileInputStream 是抽象类InputStream/OutputStream的子类. 它们生成与文件链接的字节流。 为打开文件,只需创建FileOutputStream/FileInputStream类的一个对象,在构造函数中以参数形式指定文件的名称。

55 文件的读写 FileInputStream类和FileOutputStream类的构造函数是创建一个输入输出的对象,通过引用该对象的读写方法,来完成对文件的输入输出操作。 在构造函数中,需要指定与所创建的输入输出对象相连接的文件。 要构造一个FileInputStream对象,所连接的文件必须存在而且是可读的; 构造一个FileOutputStream对象,如果输出文件已经存在且可写,该文件内容会被新的输出所覆盖。

56 FileInputStream fin = new FileInputStream(“c:\\java\\test.java”);
从InputStream中派生出来,其所有方法都从InputStream类继承而来。基本操作步骤: 1>建立文件的输入流对象 2>从输入流中读取字节 3>关闭流 常用构造方法 public FileInputStream(String name) throws FileNotFoundException public FileInputStream(File file) throws FileNotFoundException 均会抛出FileNotFoundException异常 构造方法参数指定的文件称作输入流的源 FileInputStream fin = new FileInputStream(“c:\\java\\test.java”);

57 FileInputStream 文件字节流的读取
read方法给程序提供从输入流中读取数据的基本方法。 read方法按顺序读取流,直到流的末尾或流被关闭(close()方法)。 read方法的格式: public int read() throws IOException 从输入流中顺序读取单个字节的数据,并将所读单个字节以int返回。如果已到达文件末尾,则返回 -1 。 public int read(byte b[]) throws IOException public int read(byte b[], int off, int len) throws IOException 把多个字节读到一个字节数组中,返回实际所读的字节数。

58 Example with FileInputStream
/* class example FileIn.java */ import java.io.*; public class FileIn{ public static void main(String[] args){ try { FileInputStream fin = new FileInputStream(“c:\\java\\test.java”); int input; while ((input = fin.read()) != -1)//读取字节直到末尾 System.out.print((char)input); fin.close(); }catch(IOException ie){ System.out.println(e); }

59 FileOutputStream fout = new FileOutputStream(“c:\\java\\test.java”);
从OutputStream中派生出来,其所有方法都从OutputStream类继承来的。 基本操作步骤: 1>建立文件的输出流对象 >向输出流中写字节 >关闭流 常用构造方法 public FileOutputStream(String name) public FileOutputStream(File file) 如果输出流要写入数据的文件已经存在,该文件中的数据内容就会被刷新;如果要写入数据的文件不存在,该文件就会被建立。 FileOutputStream fout = new FileOutputStream(“c:\\java\\test.java”);

60 FileOutputStream文件输出字节流
write方法把字节发送给输出流,顺序地写文件,直到流的末尾或流被关闭(close()方法) write方法的格式: public void write(byte b[]) throws IOException public void write(byte b[], int off, int len) throws IOException

61 /*例:编写程序,接收用户从键盘输入的数据,回车后保存到
文件test.txt中。若用户输入符号#,则退出程序。*/ import java.io.*; public class WriteFile{ public static void main(String args[]) { byte buffer[]=new byte[128]; System.out.println("请输入数据,回车后保存到文件test.txt"); System.out.println("输入 # 则退出!"); try{ FileOutputStream f=new FileOutputStream("test.txt"); while(true){ int n=System.in.read(buffer);//从键盘读多个字节存入buffer if(buffer[0]=='#' ) break; f.write(buffer, 0, n); f.write(‘\n'); } f.close(); }catch(IOException e){ System.out.println(e.toString());

62 上例程序运行结果如图所示:

63 例:使用FileInputStream类与FileOutputStream类复制文件。
/* class example FileIn_Out.java */ /* assumes each char is a single byte */ import java.io.*; public class FileIn_Out{ public static void main(String[] args) { try { FileInputStream fin=new FileInputStream(“c:\\java\\file1.java”); FileOutputStream fout=new FileOutputStream(“c:\\java\\file2.java”); byte b[]= new byte[512]; while((fin.read(b, 0, 512))!=-1) fout.write(b); fin.close(); fout.close(); }catch(IOException ie) { System.out.println(ie); }catch(Exception e) { System.out.println(e); }

64 7.3 File I/O //File and File Stream -- FileStream.java
import java.io.*; class filestream { public static void main(String args[]) { try{ File inFile=new File(“file1.txt"); File outFile=new File(“file2.txt"); FileInputStream fis=new FileInputStream(inFile); FileOutputStream fos=new FileOutputStream(outFile); int c; while((c=fis.read())!=-1) fos.write(c); fis.close(); fos.close(); }catch(FileNotFoundException e) { System.out.println("FileStreamsTest: "+e); }catch(IOException e) { System.err.println("FileStreamsTest: "+e); } 7.3 File I/O

65 FileReader类 从InputStreamReader中派生出来,其所有方法都从InputStreamReader类和Reader类继承而来。 基本操作步骤: 1>建立文件的输出流对象 >向输出流中写字符 >关闭字符流 常用构造方法 public FileReader(String name) throws FileNotFoundException public FileReader (File file) throws FileNotFoundException 均会抛出FileNotFoundException异常 构造方法参数指定的文件称作输入流的源.

66 FileReader类:文件字符流的读取
public int read() throws IOException 从源中顺序读取一个字符,以int返回。 public int read(char ch[]) throws IOException public int read(char ch[], int off, int len) throws IOException 把多个字符读到一个字符数组中,返回实际所读的字符数。

67 //FileIn.java import java.io.*; class FileIn { public static void main(String args[]) throws IOException{ int i; FileReader fr; try { fr = new FileReader("D:\\workspace\\test\\FileIn.java"); while((i = fr.read())!= -1) System.out.print((char) i); fr.close(); }catch(FileNotFoundException e) { System.out.println("File Not Found"); }catch(ArrayIndexOutOfBoundsException e) { System.out.println("Usage: ShowFile File"); }

68 //FileReaderSample.java import java.io.*; public class FileReaderSample { public static void main(String args[ ]) throws IOException{ char data[ ]=new char[100]; //建立可容纳100个字符的数组 // 建立对象fr FileReader fr=new FileReader("D:\\workspace\\copy.txt"); // 将数据读入字符数组data内 int num=fr.read(data); // 输出在控制台 System.out.println("Characters read= "+num); for(int i=0; i<data.length; i++){ System.out.println("data["+i+"]="+data[i]); } fr.close();

69 FileWriter类 从OutputStreamReader中派生出来,其所有方法都从OutputStreamReader类和Writer类继承而来。 基本操作步骤: 1>建立文件的输出流对象 >向输出流中写字符 >关闭字符流 常用构造方法 public FileWriter(String name) public FileWriter(File file) 均会抛出FileNotFoundException异常

70 FileWriter类:文件字符流的输出
public void write(char b[ ]) throws IOException public int write(char b[ ], int offset, int len) throws IOException public int write(String str) throws IOException public int write(String str, int offset, int len) throws IOException

71 BufferedStream(缓冲流) 处理流 节点流 71 /84

72 Add BufferedStream to improve performance
BufferedReader和BufferedWriter类被用来从基于字符的输入和输出流中读取和写入文本。 BufferdReader类缓存字符以更高效的读取字符串,数组和文本行。 BufferedWriter类缓存字符以更高效的写入字符串,数组和文本行 Add BufferedStream to improve performance

73 BufferedStream缓冲流 文件 文件流 缓冲区流 处理 增加缓冲区流,减少访问硬盘的次数,提高效率。 程序 file1.txt
输入流 输出流 输入缓冲区 输出缓冲区 程序

74 缓冲流--BufferedReader类
构造方法 public BufferedReader(Reader in, int sz); //sz为缓冲区的大小 public BufferedReader(Reader in); BufferedReader对象的创建 先创建一个Reader子类的对象,然后使用这个对象来创建缓冲流对象。 任何Reader流都可以用来包装成缓冲流 FileReader inOne = new FileReader("Student.txt"); BufferedReader inTwo = new BufferedReader(inOne);

75 缓冲流--BufferedReader类
从缓冲区读取 缓冲流的读取 public int read() throws IOException 读取一个字符 public int readLine() throws IOException 读取一行文本 读取完毕后,最好调用close()方法关闭流。

76 BufferedWriter类 Writer类的直接子类 构造方法 BufferedWriter对象的创建
public BufferedWriter(Writer in,int sz) public BufferedWriter(Reader in) BufferedWriter对象的创建 先创建一个Writer子类的对象,然后使用这个对象来创建缓冲流对象。 FileWriter outOne = new FileWriter("Student.txt"); BufferedWriter outTwo = new BufferedWriter(outOne);

77 BufferedWriter类 缓冲流的写入 输出完毕后,最好调用close()方法关闭流。
public void write(String str) throws IOException 向缓冲区写入一个字符串。 public int writeLine(String str,int off,int len) throws IOException 向缓冲区写入一个字符串的一部分。 输出完毕后,最好调用close()方法关闭流。

78 \r\n是windows下的换行 \n是UNIX下的
/**ReadWriteFile.java--读出1.txt中的内容,写入2.txt中 */ import java.io.*; public class ReadWriteFile{ public static void main(String[] args){  try{    File read = new File(“c:\\1.txt”);    File write = new File(“c:\\2.txt”);        BufferedReader br = new BufferedReader(new FileReader(read));    BufferedWriter bw = new BufferedWriter(new FileWriter(write));    String temp = null;    temp = br.readLine(); //读一行文本    while(temp != null){           bw.write(temp + “\r\n”);  //写文件, “\r\n”-回车只适用Windows系统      temp = br.readLine(); //继续读文件    }        bw.close();    br.close();       }catch(FileNotFoundException e){ //文件未找到异常     System.out.println (e);   }catch(IOException e){     System.out.println (e);   }  } \r\n是windows下的换行 \n是UNIX下的

79 //BufferedStream.java import java.io.*; public class BufferedStream { public static void main(String[] args){ try{ BufferedWriter out=new BufferedWriter(new FileWriter("D:\\test.txt")); out.write("Hello,World"); out.close(); BufferedReader in=new BufferedReader(new FileReader("D:\\test.txt")); String s; s = in.readLine(); System.out.println(s); in.close(); }catch(Exception e){ System.out.println("error"); }

80 对象串行化(Serialization)
对象(object)的寿命通常随着生成该对象的程序的终止而终止。某些时候,需要将对象的状态保存下来,将来需要的时候可以恢复。 对象的这种能记录自己的状态以便将来再生的能力,叫做对象的 持续性(persistence)。 对象通过写出描述自己状态的数值来记录自己的过程,叫做对象的串行化(Serialization)。 串行化的主要任务是写出对象实例变量的数值。如果实例变量是另一对象的一引用,则引用的对象也要串行化。这个过程是递归的。 对象串行化机制就是将程序中对象的状态转化为一个字节流,存储在文件中,作为这个对象的一个副本,之后再从文件中把对象读取出来重新建立。

81 public interface Serializable{ }
在java.io包中,接口Serializable用来作为实现对象串行化的工具,只有实现了Serializable接口的类的对象才可以被串行化。 Serializable接口中不含有任何的方法声明,是个空接口。其定义如下: public interface Serializable{ } 实现Serializable接口,不需要编写任何的实现代码。这个接口只是一个特殊的标记,用来表示一个类可以被串行化。 如果一个类可以串行化,它的所有子类都可以串行化。

82 if(obj instanceof Serializable) {………}
Java标记接口 标识接口是没有任何方法和属性的接口. 它仅仅表明实现它的类属于一个特定的类型,供其他代码来测试允许做一些事情. 使用标记接口的唯一目的是使得可以用instanceof进行类型查询,例如:             if(obj instanceof Serializable) {………}

83 对象串行化(Serialization)
不参与串行化的数据可以用关键字transient(瞬时的)来修饰。 比如:通常出于安全性的考虑,某些不宜公开的数据(如用户的密码)用transient来修饰,能够使其不被串行化。 用static修饰的静态成员变量与类对象无关,串行化过程也与之无关。 有些对象,如Thread、FileInputStream、FileOutputStream等对象,其对象状态也是瞬时的,也不能进行串行化。

84 //Example: Serializable接口
import java.io.Serializable; public class Student implements Serializable { private static final long serialVersionUID = L; int id; String name; int age; String department; public Student(){ } public Student(int id, String name, int age, String department){ this.id = id; this.name = name; this.age = age; this.department = department; }

85 读写对象流 ObjectInputStream和 ObjectOutputStream
java.io包中,提供了ObjectInputStream (对象输入流)和ObjectOutputStream(对象输出流),可读、写对象。 对象串行化(serialization) 通过ObjectOutputStream将对象状态保存下来(将对象保存到文件中,或者通过网络传送到其他地方); 反串行化(deserialization) 再通过ObjectInputStream将对象状态恢复。

86 serialVersionUID 实现Serializable接口,需要定义域:serialVersionUID。
serialVersionUID是为了反序列化的时候JVM比对类的版本。有两种生成方式: 一个是默认的1L,比如: private static final long serialVersionUID = 1L; 一个是根据类名、接口名、成员方法及属性等来生成一个64位的哈希字段,比如: private static final long serialVersionUID = xxxxL; 在反序列化的时候,即:将流转换为类的实例的时候,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。 当一个类实现了Serializable接口,如果没有定义serialVersionUID,Eclipse会提供这个提示功能告诉你去定义 。在Eclipse中点击类中warning的图标一下,Eclipse就会自动给定两种生成的方式。如果不想定义它,在Eclipse的设置中也可以把它关掉的,或者全部默认为1L.

87 写对象流 ObjectOutputStream中用writeObject()方法可以直接将对象保存到输出流中。
写出了重构一个类对象所需要的信息:对象的类、类的标记和非transient的对象成员,如果对象包含其他对象的引用,则这些对象也会被串行化。 串行化能保存的元素 只能保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量,而且串行化保存的只是变量的值,对于变量的任何修饰符,都不能保存。

88 读对象流 在ObjectInputStream中用readObject()方法可以直接读取一个对象,
对象的字节流并不包含类的字节码,只是包含类名及其签名,当readObject( )读取对象时,Java虚拟机需要装载指定的类(恢复的对象的类),如果找不到这个类,则此方法会抛出ClassNotFoundException异常。

89 反串行化--恢复对象状态 import java.io.*; public class TestSeria {
public static void main(String[] args){ Student stu=new Student(981036,"Liu Ming",18, "CSD"); try{ FileOutputStream fo=new FileOutputStream("data.ser"); ObjectOutputStream so=new ObjectOutputStream(fo); so.writeObject(stu); so.close(); }catch(IOException e){ System.out.println(e); }

90 import java.io.*; public class test { public static void main(String[] args) throws IOException,ClassNotFoundException { //串行化 Student s1 = new Student(1,"Mar", 20, "Computer_Science"); Student s3 = new Student(2,"Cathy", 21, "Software_Engineering"); FileOutputStream fos = new FileOutputStream("D:\\serialization\\Student.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(s1); oos.writeObject(s3); //反串行化 FileInputStream fis = new FileInputStream("D:\\serialization\\Student.txt"); ObjectInputStream ois = new ObjectInputStream(fis); Student s2, s4; s2 = (Student) ois.readObject(); //必须添加强制类型转换 s4 = (Student) ois.readObject(); System.out.println("Student Information:"); System.out.println(s2.id+“ ”+s2.name+" “+s2.age+" “+s2.department); System.out.print(s4.id+" “+s4.name+" “+s4.age+" “+s4.department); oos.close(); ois.close(); }

91 定制串行化 默认的串行化机制,对象串行化首先写入类数据和类字段的信息,然后按照名称的上升排列顺序写入其数值。
如果想自己明确地控制这些数值的写入顺序和写入种类,必须定义自己的读取数据流的方式。就是在类的定义中重写writeObject()和readObject()方法。 例如:在一个可以串行化的类中有一个不可串行化的对象,但又想保存该对象的状态信息该如何是好? 例:ObjectSerialization.java

92 import java.io.*; //Student类实现Serializable接口 
public class Student implements Serializable { int id; String name; int age; String department; public Student(int id, String name, int age, String department){ this.id = id; this.name = name; this.age = age; this.department = department; }  //一般可不重写,定制串行化时需要重写writeObject()方法 private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(id); out.writeInt(age); out.writeUTF(name); out.writeUTF(department); //一般可不重写,定制串行化时需要重写readObject()方法     private void readObject(ObjectInputStream in) throws IOException { id=in.readInt(); age=in.readInt(); name=in.readUTF(); department=in.readUTF();

93 import java.io.*; public class ObjectSerialization{ public static void main(String[] args) throws IOException,ClassNotFoundException{ Student st=new Student( ,"黎明",20,"计算机系"); //创建可串行化的st对象 FileOutputStream fout=new FileOutputStream("data.txt"); ObjectOutputStream sout=new ObjectOutputStream(fout); try{ //输出流将对象状态存入文件"data.txt” sout.writeObject(st); sout.close(); }catch(IOException e){} st=null; // st对象与ObjectInputStream联系起来 FileInputStream fin=new FileInputStream("data.txt"); ObjectInputStream sin=new ObjectInputStream(fin); try{ //输入流将对象状态从文件"data.ser"读出 st=(Student) sin.readObject(); sin.close(); System.out.println("学生信息:"); //输出验证 System.out.print("学号: " + st.id +"; 姓名: " + st.name+"; 年龄: " + st.age); System.out.println("; 院系: " + st.department); }

94 定制串行化:(参考) 调用重写的writeObject()和readObject()方法
如果在Student 类里面重写该方法,它将会被ObjectOutputStream调用而不是默认的序列化进程。 如果你是第一次看见它,你会很惊奇尽管它们被外部类调用但事实上这是两个private的方法。并且它们既不存在于java.lang.Object,也没有在Serializable中声明。那么ObjectOutputStream如何使用它们的呢?因为ObjectOutputStream使用了反射来寻找是否声明了这两个方法。因为ObjectOutputStream使用getPrivateMethod,所以这些方法不得不被声明为priate以至于供ObjectOutputStream来使用。


Download ppt "Java Programming Spring, 2013"

Similar presentations


Ads by Google