1 / 47

第十章 输入 / 输出处理

第十章 输入 / 输出处理. 输入输出概述. 输入 / 输出处理: 从键盘读取数据; 向屏幕中输出数据; 从文件中读或者向文件中写数据 在一个网络连接上进行读写操作等。 在 Java 中,把这些不同类型的输入、输出抽象为 流 ( Stream ) ,用统一的接口来表示,从而使程序设计简单明了。. 输入流和输出流. 流是程序和外界进行数据交换的通道 输入流 (InputStream) 程序通过输入流从数据源读取数据 输出流 (OutputStream) 通过输出流向目的地写数据。. java.io 包.

daryl
Download Presentation

第十章 输入 / 输出处理

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十章 输入/输出处理

  2. 输入输出概述 • 输入/输出处理: • 从键盘读取数据; • 向屏幕中输出数据; • 从文件中读或者向文件中写数据 • 在一个网络连接上进行读写操作等。 • 在Java中,把这些不同类型的输入、输出抽象为流(Stream),用统一的接口来表示,从而使程序设计简单明了。

  3. 输入流和输出流 • 流是程序和外界进行数据交换的通道 • 输入流(InputStream) • 程序通过输入流从数据源读取数据 • 输出流(OutputStream) • 通过输出流向目的地写数据。

  4. java.io包 • 在Java开发环境中,主要是由包java.io中提供的一系列的类和接口来实现输入/输出处理。 • 标准输入/输出(System.out和System.in)处理则是由包java.lang中提供的类来处理的,但这些类又都是从包java.io中的类继承而来。

  5. 字节流和字符流 • 输入输出流的类型 • 字节输入/输出流:以字节为读写单位 • 字符输入/输出流:以字符为读写单位

  6. InputStream ByteArrayInputStream FileInputStream FilterInputStream BufferedInputStream DataInputStream PushbackInputStream ObjectInputStream PipedInputStream SequenceInputStream OutputStream ByteArrayOutputStream FileOutputStream FilterOutputStream BufferedOutputStream DataOutputStream PrintStream ObjectOutputStream PipedOutputStream 字节流 • InputStream类是所有字节输入流的父类 • OutputStream类是所有字节输出流的父类

  7. InputStream类的方法 (1) • InputStream是一个抽象类,不能被实例化。它提供了一系列和读取数据有关的方法。 int read() //从数据源读入一个字节的数据,当读到流的末尾时,返回-1 int read(byte[ ] b) //从输入流中读取若干个字节到字节数组b,返回值为实际读取的字节数,当读到流的末尾时,返回-1 int read(byte[ ] b,int off, int len) //从输入流中读取长度为len的数据,写入数组b中从索引off开始的位置,并返回读取得字节数。当读到流的末尾时,返回-1 void close() //当完成读操作后,应该关闭输入流。

  8. InputStream类的方法(2) • skip():跳过流中若干字节数 • available():返回流中可用字节数 • mark():在流中标记一个位置 • reset():返回标记过得位置 • markSupport():是否支持标记和复位操作

  9. OutputStream类的方法 • OutputStream类是所有字节输出流的父类,它是一个抽象类,不能被实例化。它提供了一系列和写数据有关的方法。 void write(int), //向输出流写一个字节数据。 void write(byte[] b) //向输出流写一个字节数组的数据 void close() //当完成写操作后,应该关闭输出流。 void flush() OutputStream类本身的flush()方法不执行任何操作,它的一些带有缓冲区的子类(比如BufferedOutputStream和PrintStream类)覆盖了flush()方法。通过带缓冲区的输出流写数据时,数据先保存在缓冲区中,积累到一定程度才会真正写到输出流中。缓冲区通常用字节数组实现,实际上是指一块内存空间。flush()方法强制把缓冲区内的数据写到输出流中。

  10. InputStream和OutputStream示例 • 把输入流中的所有内容复制到输出流中 public void copy(InputStream in, OutputStream out) throws IOException { byte[] buf = new byte[4096]; int len = in.read(buf); //read方法可能抛出IOException while (len != -1) { out.write(buf, 0, len); //write方法可能抛出IOException len = in.read(buf); } }

  11. 字节流——文件流 • FileInputStream类: • 用来打开一个输入文件,若要打开的文件不存在,则会产生FileNotFoundException异常,这是一个已检查异常,必须捕获或抛出; • FileOutputStream类: • 用来打开一个输出文件,若要打开的文件不存在,则会创建一个新的文件,否则原文件的内容会被新写入的内容所覆盖。 • 在进行文件的读/写操作时,可能会产生已检查异常IOException,必须捕获或抛出(其它的输入/输出流处理时也同样需要进行输入/输出异常处理)。

  12. 文件字节流的构造方法 • 文件流的构造方法: • FileInputStream(String name) • 打开一个文件路径名为name的文件作为输入。 • FileOutputStream(String name) • 创建一个文件路径名为name的文件作为输出,文件如果已经存在,则其内容被清空。 • FileOutputStream(String name, boolean append) • 创建一个文件路径名为name的文件作为输出,文件如果已经存在,则在该输出流上输出的内容被接到原有内容之后还是覆盖取决于append的值。

  13. 文件流示例1 • 把一个文件的内容加到另一个文件后 public void cat(String fsrc, String fdest) { try { InputStream in = new FileInputStream(fsrc); OutputStream out = new FileOutputStream(fdest, true); copy(in, out); out.close(); in.close(); } catch (IOException ex) { System.err.println(ex); } }

  14. 文件流示例2 功能:将文件中的内容显示在控制台。 import java.io.*; class FileReaderSample { public static void main(String agrs[])throws IOException{ FileInputStream in=new FileInputStream(“e:\\in.txt"); int data; while((data=in.read())!=-1) System.out.print(data +“”); //以ASCII码的形式显示文件中的内容 in.close(); } } 演示FileReaderSample.java

  15. 文件流示例3 功能:将字符串写入文件 import java.io.*; public class FileWriterSample{ public static void main(String args[]) { try { FileOutputStream fileOut = new FileOutputStream(“E:\\out.txt"); fileOut.write(“你好”.getBytes()); //调用String.getByte()方法返回字符串数组 fileOut.close(); } catch(FileNotFoundException e) { } catch(IOException e) { } } } 演示FileWriterSample.java

  16. 字节流—过滤流 • FilterInputStream和FilterOutputStream: • 用于扩展字节输入/输出流功能的装饰器,它有好几个子类,分别用来扩展字节输入/输出流的某一种功能 • 要使用过滤流,首先必须把它连接到某个输入/输出流上,通常在构造方法的参数中指定所要连接的流: • FilterInputStream(InputStream in); • FilterOutputStream(OutputStream out);

  17. 过滤流子类:DataInputStream类 • DataInputStream: 用于读取基本类型数据,如int、float、long、double和boolean等,以及采用UTF-8编码的字符串。DataInputStream类的所有读方法都都以“read”开头,比如: • byte readByte():从输入流中读取1个字节,把它转换为byte类型的数据。 • long readLong():从输入流中读取8个字节,把它转换为long类型的数据。 • float readFloat():从输入流中读取4个字节,把它转换为float类型的数据。 • String readUTF():从输入流中读取1到3个字节,把它转换为采用UTF-8编码的字符串。

  18. 过滤流子类:DataOutputStream类 • DataOutputStream:用于写入基本类型数据,如int、float、long、double和boolean等和UTF编码的字符串 • writeByte():写入1个字节到输出流。 • writeLong():写一个long类型的数据到输出流。 • writeFloat():写一个long类型的数据到输出流。 • writeUTF():写入一个用UTF-8编码的字符串。

  19. DataInputStream和DataOutputStream示例 FileOutputStream out1=new FileOutputStream("D:\\test.txt"); BufferedOutputStream out2=new BufferedOutputStream(out1); //装饰文件输出流 DataOutputStream out=new DataOutputStream(out2); //装饰带缓冲输出流 out.writeByte(-12); out.writeLong(12); out.writeChar('1'); out.writeUTF("好"); out.close(); InputStream in1=new FileInputStream("D:\\test.txt"); BufferedInputStream in2=new BufferedInputStream(in1); //装饰文件输入流 DataInputStream in=new DataInputStream(in2); //装饰缓冲输入流 System.out.print(in.readByte()+" "); System.out.print(in.readLong()+" "); System.out.print(in.readChar()+" "); System.out.print(in.readUTF()+" "); in.close(); 演示FormatDataIO.java

  20. 过滤流子类:缓冲流 • 类BufferedInputStream和BufferedOutputStream实现了带缓冲的过滤流,它提供了缓冲机制,把任意的I/O流“捆绑”到缓冲流上,可以提高读写效率。 • 在初始化时,除了要指定所连接的输入输出流之外,还可以指定缓冲区的大小。 • BufferedInputStream(InputStream in[, int size]) • BufferedOutputStream(OutputStream out[, int size])

  21. 过滤流子类:缓冲流示例 public void copy(InputStream in, OutputStream out) throws IOException { out = new BufferedOutputStream(out, 4096); byte[] buf = new byte[4096]; int len = in.read(buf); while (len != -1) { out.write(buf, 0, len); len = in.read(buf); } out.flush(); //强制将尚未填满的缓冲区中的数据送出。 }

  22. 过滤流:其它 • PushBackInputStream:它提供了一个方法将刚刚读入的一个或多个字节退回到输入流中去。 • PrintStream:其作用是将Java语言中的不同类型的数据以字符表示形式输出到相应的输出流中去。

  23. 字节流——标准流 语言包java.lang中的System类管理标准输入/输出流和错误流。 • System.in • 继承InputStream, • 用于从标准输入设备中获取输入数据(通常是键盘)。 • System.out, • 继承PrintStream,把输出送到缺省的显示设备(通常是控制台)。 • System.err, • 继承PrintStream,把错误信息送到缺省的显示设备(通常是控制台)。 • 每当main方法被执行时,就自动生成上述三个对象。

  24. 标准输入输出示例 public static void main(String args[]) { try { byte bArray[]=new byte[128]; String str; System.out.println(“Please enter something:"); System.in.read(bArray); str = new String(bArray); System.out.print("You entered:"); System.out.println(str); } catch(IOException ioe) { System.err.println(ioe.toString()); } } 见SysIOSample.java

  25. URL输入流(java.net.URL) InputStream is = null; try { URL url= new URL("http://www.javathinker.org/weiqin/sole.htm"); is = url.openStream(); byte buffer[] = new byte[2048]; is.read(buffer,0,buffer.length); System.out.println(new String(buffer)); } catch (IOException e){} 演示URLTest.java

  26. 字符输入输出流 • 在JDK1.1之前,java.io包中的流只有普通的字节流(以byte为基本处理单位的流),这种流对于以16位的Unicode码表示的字符流处理很不方便。从JDK1.1开始, java.io包中加入了专门用于字符流处理的类,它们是以Reader和Writer为基础派生的一系列类。 • 同InputStream和OutputStream一样,Reader和Writer也是抽象类,只提供了一系列用于字符流处理的接口。它们的方法与类InputStream和OutputStream类似,只不过其中的参数换成字符或字符数组。

  27. Reader BufferedReader LineNumberReader CharArrayReader FilterReader PushbackReader InputStreamReader FileReader PipedReader StringReader Writer BufferedWriter CharArrayWriter FilterWriter OutputStreamWriter FileWriter PipedWriter StringWriter PrintWriter Reader和Writer类 • Reader:是所有字符输入流的父类 • Writer: 是所有字符输出流的父类。

  28. 输入输出字符流的构造 • 默认情况下,如果你构造了一个连接到字符流的Reader和Writer,那么转换规则会对本地平台默认的字符编码和Unicode进行转换。 • 在构造InputStreamReader类和OutputStreamWriter类的实例时,你可以指定输出流或输入流的字符编码。 InputStreamReader reader=new InputStreamReader(new FileInputStream("D:\\test.txt"), "UTF-8" ); char c=(char)reader.read();

  29. 关于字符编码 • 系统属性file.encoding表示本地平台的字符编码,,中文系统一般是GBK (参见propertyTester.java) • 字符串的相关方法 String(byte[] bytes, String enc) //按指定的字符编码enc构造字符串 byte[] getBytes(String enc) //获得按指定的字符编码的字节数组

  30. 如何获得本地平台的编码类型 Properties p=System.getProperties(); //Properties类封装了与java运行环境相关的系统属性集,在java.util包中 Enumeration k=p.keys(); Enumeration e=p.elements(); String userName= (String)p.get("user.name"); while(k.hasMoreElements()){ System.out.println(k.nextElement()+ " :"+ e.nextElement()); } (参见propertyTester.java)

  31. 字符流——与字节流连用 • InputStreamReader OutputStreamWriter • 用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字节方式表示的流转换为特定平台上的字符表示。 • InputStreamReader(InputStream in); //缺省规范 • InputStreamReader(InputStream in, String enc); //指定规范enc • OutputStreamWriter(OutputStream out); //缺省规范 • OutputStreamWriter(OutputStream out, String enc); //指定规范enc

  32. 字节流与字符流连用示例 import java.util.*; import java.io.*; public class ReadFile{ public static void main(String args[]) throws Exception{ MyReaderWriter rw=new MyReaderWriter(); rw.copyfile(“E:\\hello.txt”,“E:\\hello1.txt"); } public void copyfile(String from, String to)throws Exception{ char[] cbuf=new char[2064]; FileInputStream fin=new FileInputStream(from); InputStreamReader ir=new InputStreamReader(fin); FileOutputStream fo=new FileOutputStream(to); OutputStreamWriter ow=new OutputStreamWriter(fo,"MS950"); int length=0; while((length=ir.read(cbuf, 0, 2064))!=-1){ System.out.println(cbuf); } ir.close(); ow.close(); } 演示ReadFile.java

  33. BuffereReader和PrintWriter • BfferedReader • PrintWriter

  34. BufferedReader • BufferedReader • 带有缓冲区,可以先把一批数据读到缓冲区内,接下来的读操作都是从缓冲区内获取数据,避免每次都从数据源读取数据并进行字符编码转换,从而提高读操作的效率。 • 可采用BufferedReader来装饰其他Reader,以提高效率。 • 构造方法: • BufferedReader(Reader in) :参数in指定被装饰的Reader类。 • BufferedReader(Reader in, int sz) :参数in指定被装饰的Reader类,参数sz指定缓冲区的大小,以字符为单位。 • 提供了整行字符处理方法: • public String readLine(): BufferedReader的方法,从输入流中读取一行字符,行结束标志为‘\n’、‘\r’或两者一起。

  35. println(“hello”); 等价于: print(“hello”) print(“\n”) PrintWriter • PrintWriter能输出格式化的数据,PrintWriter的写数据的方法都以print开头,比如: • print(int i):向输出流写入一个int类型的数据。 • print(long l): 向输出流写入一个long类型的数据。 • print(float f): 向输出流写入一个float类型的数据。 • print(String s): 向输出流写入一个String类型的数据。 • println(int i): 向输出流写入一个int类型的数据和换行符。 • println(long l): 向输出流写入一个long类型的数据和换行符。 • println(float f): 向输出流写入一个float类型的数据和换行符。 • println(String s): 向输出流写入一个String类型的数据和换行符

  36. 字符流——其它 • CharArrayReader & CharArrayWriter • 对字符数组进行处理 • StringReader & StringWriter • 对字符串进行处理 • FilterReader & FilterWriter • 过滤字符流 • PipedReader & PipedWriter • 管道字符流 • LineNumberReader • 行处理字符输入流

  37. 文件类 • File:以文件路径名的形式代表一个文件或目录 • FileDescriptor:代表一个打开文件的文件描述 • FileFilter & FilenameFilter:用于列出满足条件的文件 • File.list(FilenameFilter fnf) • File.listFiles(FileFilter ff) • FileDialog.setFilenameFilter(FilenameFilter fnf) • FileInputStream & FileReader:顺序读文件 • FileOutputStream & FileWriter:顺序写文件 • RandomAccessFile:提供对文件的随机访问支持。

  38. File类 • File类(在java.io包中)提供了若干创建文和处理文件、目录和获取它们基本信息的方法。 • File 类的构造方法: 1. File(String pathname) //pathname为文件或目录的路径 2. File(String parent, String child) 3. File(File parent, String child)

  39. File类的方法 • 查看文件属性: boolean canRead() boolean isFile() long lastModified(): //可强制转化为Date类型 • 创建或删除目录: mkdir(), delete() //若为目录,必须为空目录,才可以删除 • 列出目录下的所有文件: String[] list() • 判断文件是否存在: boolean exists() • 重新命名文件: renameTo()

  40. File类的方法 • 创建新文件: createNewFile() • 返回文件名或最后一级目录名 String getName() • 返回文件所在目录的路径或本目录的上级目录路径 String getParent() System.out.println("getParent="+new File ("E:\\Dir1\\Dir2\\test.txt").getParent()); System.out.println("getName="+new File ("E:\\Dir1\\Dir2\\test.txt").getName()); 结果: E:\Dir1\Dir2 test.txt

  41. 创建目录和文件示例 File dir1=new File("D:\\dir1"); if(!dir1.exists())dir1.mkdir(); File dir2=new File(dir1,"dir2"); if(!dir2.exists())dir2.mkdirs(); File dir3=new File(dir1,"dir3"); if(!dir3.exists())dir3.mkdirs(); File dir4=new File(dir1,"dir3\\dir4"); if(!dir4.exists())dir4.mkdirs(); File file=new File(dir2,"test.txt"); if(!file.exists())file.createNewFile(); 创建文件系统 见UseFile.java

  42. 打印目录和文件示例 public static void listDir(File dir){ File[ ] lists=dir.listFiles(); //打印当前目录下包含的所有子目录和文件的名字 String info="目录:"+dir.getName()+"("; for(int i=0;i<lists.length;i++) info+=lists[i].getName()+" "; info+=")"; System.out.println(info); } 见UseFile.java

  43. 删除目录或文件示例 /** 删除目录或文件,如果参数file代表目录,会删除当前目录以及目录下的所有内容*/ public static void deleteDir(File file){ //如果file代表文件,就删除该文件 if(file.isFile()){ file.delete(); return; } //如果file代表目录,先删除目录下的所有子目录和文件 File[] lists=file.listFiles(); for(int i=0;i<lists.length;i++) deleteDir(lists[i]); //递归删除当前目录下的所有子目录和文件 //最后删除当前目录 file.delete(); } 见UseFile.java

  44. RandomAccessFile类 • RandomAccessFile类: • 用来随机读取和写入文件 (即可以写入文件中任何一个地方) • 实现了DataInput和DataOutput 接口 • readBoolean(), readByte(), readChar(), readLine()… • writeBoolean(), writeByte(), writeChar(), writeLine()… • 提供了定位文件的方法

  45. RandomAccessFile类的构造方法 • RandomAccessFile(File file, String mode) RandomAccessFile(String name, String mode) • mode 的取值: • “r”只读. 任何写操作都将抛出IOException。 • “rw”读写. 文件不存在时会创建该文件,文件存在时,原文件内容不变,通过写操作改变文件内容。 • “rws”同步读写. 等同于读写,但是任何协操作的内容都被直接写入物理文件,包括文件内容和文件属性。 • “rwd”数据同步读写. 等同于读写,但任何内容写操作都直接写到物理文件。

  46. RandomAccessFile类的方法 • DataInput和DataOutput中的方法 • readInt(), writeDouble()… • int skipBytes(int n):将指针向下移动若干字节 • length():返回文件长度 • long getFilePointer():返回指针当前位置 • void seek(long pos):将指针调到所需位置 • void setLength(long newLength):设定文件长度

  47. RandomTester.java import java.io.*; public class RandomTester { public static void main(String args[])throws IOException{ RandomAccessFile rf=new RandomAccessFile("D:\\test.dat","rw"); for(int i=0;i<10;i++) rf.writeLong(i*1000); rf.seek(5*8); //从文件开头开始,跳过第5个long数据,接下来写第6个long数据 rf.writeLong(1234); rf.seek(0); //把读写指针定位到文件开头 for(int i=0;i<10;i++) System.out.println("Value"+i+":"+rf.readLong()); rf.close(); } Value0:0 Value1:1000 Value2:2000 Value3:3000 Value4:4000 Value5:1234 Value6:6000 Value7:7000 Value8:8000 Value9:9000

More Related