• 1. 本章内容Java 流式输入/输出原理 Java流类的分类 输入/输出流类 常见的节点流和处理流 文件流 缓冲流 数据流 转换流 Print流 PrintWriter
  • 2. Java流式输入/输出原理在Java程序中,对于数据的输入/输出操作以“流” (stream) 方式进行;J2SDK提供了各种各样的“流”类,用以获取不同种类的数据;程序中通过标准的方法输入或输出数据。文件00101… … …程序文件… … …00101程序网路连接程序0010111… … …程序程序010…010…文件010…程序“hello”
  • 3. 输入/输出流的分类 java.io 包中定义了多个流类型(类或抽象类)来实 现输入/输出功能;可以从不同的角度对其进行分 类: 按数据流的方向不同可以分为输入流和输出流。 按处理数据的单位不同可以分为字节流和字符流。 按照功能不同可以分为节点流和处理流。
  • 4. 输入/输出流的分类J2SDK 所提供的所有流类型位于包java.io内都分别继承自以下四种抽象流类型。 字节流字符流输入流InputStreamReader输出流OutputStream Writer
  • 5. 输入/输出流的分类InputStream是表示字节输入流的所有类的超类。需要定义InputStream的子类的应用程序必须始终提供返回下一个输入字节的方法,也就是以字节作为基本处理单位。 直接已知子类:AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, StringBufferInputStream
  • 6. 输入/输出流的分类OutputStream是表示输出字节流的所有类的超类。输出流接受输出字节并将这些字节发送到某个接收器,需要定义 OutputStream 子类的应用程序必须始终提供至少一种可写入一个输出字节的方法。 直接已知子类: ByteArrayOutputStream, FileOutputStream, FilterOutputStream, ObjectOutputStream, OutputStream, PipedOutputStream
  • 7. 输入/输出流的分类Reader用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。 直接已知子类: BufferedReader, CharArrayReader, FilterReader, InputStreamReader, PipedReader, StringReader
  • 8. 输入/输出流的分类Writer写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。 直接已知子类: BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter, PipedWriter, PrintWriter, StringWriter
  • 9. 节点流和处理流节点流为可以从一个特定的数据源(节点)读写数据(如:文件,内存)数据源程序处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。节点流数据源数据源程序程序
  • 10. InputStream继承自InputSteam的流都是用于向程序中输入数据,且数据的单位为字节(8 bit);下图中深色的为节点流,浅色的为处理流。
  • 11. InputStream的基本方法//读取一个字节并以整数的形式返回(0~255), //如果返回-1已到输入流的末尾。 int read() throws IOException //读取一系列字节并存储到一个数组buffer, //返回实际读取的字节数,如果读取前已到输入流的末尾返回-1 int read(byte[] buffer) throws IOException //读取length个字节 //并存储到一个字节数组buffer,从offset位置开始 //返回实际读取的字节数,如果读取前以到输入流的末尾返回-1 int read(byte[] buffer, int offset, int length) throws IOException //关闭流释放内存资源 void close() throws IOException // 跳过n个字节不读,返回实际跳过的字节数 long skip(long n) throws IOException
  • 12. OutputStream继承自OutputSteam的流都是用于程序中输出数据,且数据的单位为字节(8 bit);下图中深色的为节点流,浅色的为处理流。
  • 13. OutputStream的基本方法//向输出流中写入一个字节数据,该字节数据为参数b的低8位 void write(int b) throws IOException //将一个字节类型的数组中的数据写入输出流 void write(byte[] b) throws IOException //将一个字节类型的数组中的从指定位置(off)开始的 //len个字节写入到输出流 void write(byte[] b, int off, int len) throws IOException //关闭流释放内存资源 void close() throws IOException //将输出流中缓冲的数据全部写出到目的地 void flush() throws IOException
  • 14. Reader继承自Reader的流都是用于向程序中输入数据,且数据的单位为字符(16 bit);下图中深色的为节点流,浅色的为处理流。
  • 15. Reader 的基本方法//读取一个字符并以整数的形式返回(0~255), //如果返回-1已到输入流的末尾。 int read() throws IOException //读取一系列字符并存储到一个数组buffer, //返回实际读取的字符数,如果读取前已到输入流的末尾返回-1 int read(char[] cbuf) throws IOException //读取length个字符 //并存储到一个数组buffer,从offset位置开始 //返回实际读取的字符数,如果读取前以到输入流的末尾返回-1 int read(char[] cbuf, int offset, int length) throws IOException //关闭流释放内存资源 void close() throws IOException //跳过 n 个字符不读,返回实际跳过的字节数 long skip(long n) throws IOException
  • 16. Writer继承自Writer的流都是用于程序中输入数据,且数据的单位为字符(16 bit);下图中深色的为节点流,浅色的为处理流。
  • 17. Writer 的基本方法//向输出流中写入一个字符数据,该字节数据为参数b的低16位 void write(int c) throws IOException //将一个字符类型的数组中的数据写入输出流, void write(char[] cbuf) throws IOException //将一个字符类型的数组中的从指定位置(offset)开始的 //length个字符写入到输出流 void write(char[] cbuf, int offset, int length) throws IOException //将一个字符串中的字符写入到输出流 void write(String string) throws IOException //将一个字符串从offset开始的length个字符写入到输出流 void write(String string, int offset, int length) throws IOException //关闭流释放内存资源 void close() throws IOException //将输出流中缓冲的数据全部写出到目的地 void flush() throws IOException
  • 18. 节点流类型类 型 字 符 流字 节 流File(文件)FileReader FileWriterFileInputStream FileOutputStreamMemory ArrayCharArrayReader CharArrayWriterByteArrayInputStream ByteArrayOutputStreamMemory StringStringReader StringWriter-Pipe(管道)PipedReader PipedWriterPipedInputStream PipedOutputStream
  • 19. 访问文件FileInputStream和FileOutputStream分别继承自InputStream和OutputStream用于向文件中输入和输出字节。 FileInputStream和FileOutputStream的常用构造方法: FileInputStream(String name) throws FileNotFoundException FileInputStream(File file) throws FileNotFoundException FileOutputStream(String name) throws FileNotFoundException FileOutputStream(File file) throws FileNotFoundException FileOutputStream(File file, boolean append) throws FileNotFoundException
  • 20. File 类java.io.File类代表系统文件名(路径和文件名)。 File类的常见构造方法: public File(String pathname) 以pathname为路径创建File对象,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。 public File(String parent,String child) 以parent为父路径,child为子路径创建File对象。 File的静态属性String separator存储了当前系统的路径名分隔符。
  • 21. File 类常用方法通过File对象可以访问文件的属性。 public boolean canRead() public boolean canWrite() public boolean exists() public boolean isDirectory() public boolean isFile() public boolean isHidden() public long lastModified() public long length() public String getName() public String getPath() 通过File对象创建空文件或目录(在该对象所指的文件或目录不存在的情况下)。 public boolean createNewFile()throws IOException public boolean delete() public void deleteOnExit()//VM退出时删除 public boolean mkdir() public boolean mkdirs()//创建在路径中的一系列目录
  • 22. File 类举例 import java.io.*; public class Test { public static void main(String[] args) { String separator = File.separator; String filename = "myfile.txt"; String directory = "mydir1" + separator + "mydir2"; File f = new File(directory, filename); if (f.exists()) { System.out.println("文件名:" + f.getAbsolutePath()); System.out.println("文件大小:" + f.length()); } else { f.getParentFile().mkdirs(); try { f.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } } }
  • 23. RandomAccessFile 类java.io.RandomAccessFile类的对象可以用于对文件的随机读取。 RandomAccessFile类的常见构造方法: RandomAccessFile(File file,String mode) throws FileNotFoundException RandomAccessFile(String name,String mode) throws FileNotFoundException mode值可以为: “r”-该对象对文件的访问权限为只读,如果文件不存在则抛出异常。 “rw”-该对象对文件的访问权限为可读写,如果文件不存在则试图建立该文件。
  • 24. RandomAccessFile 方法RandomAccessFile类提供多种 read×××(…)和 write×××(…)方法,用于多种数据类型的读写,例如: 其他方法:public int read() throws IOException public int read(byte[] b,int off,int len) throws IOException public final double readDouble()throws IOException public final void readFully(byte[] b) throws IOException public void write(int b)throws IOException public final void writeDouble(double v) throws IOException … … …public long length() throws IOException//返回文件长度 public void seek(long pos) throws IOException //定位文件指针 public int skipBytes(int n) throws IOException//跳过若干字节 public long getFilePointer() throws IOException //获取当前的文件指针 … … …
  • 25. RandomAccessFile 举例 import java.io.*; public class Test { public static void main(String[] args) { File f = new File("data.dat"); try { RandomAccessFile frw = new RandomAccessFile(f,"rw"); double d1 = 123.456, d2 = 456.789; frw.writeDouble(d1);frw.writeDouble(d2); frw.writeDouble(d1+d2); frw.writeDouble(d1-d2); System.out.println(frw.length()); frw.seek(0+8*2); System.out.println(frw.readDouble()); System.out.println(frw.readDouble()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
  • 26. 访问文件FileInputSteam 和 FileOutputStream 类支持其父类InputStream 和OutputStream 所提供的数据读写方法。 注意: 在实例化FileInputStream和FileOutputSteam流时要用try-catch语句以处理其可能抛出的FileNotFoundException。 在读写数据时也要用try-catch语句以处理可能抛出的 IOException。 FileNotFoundException是IOException的子类
  • 27. import java.io.*; public class Test{ public static void main(String[] args){ int b = 0; FileInputStream in = null; long num = 0; try{ in = new FileInputStream("c:/mouse.bmp"); num = 0; while ((b = in.read()) != -1){ System.out.print(b + " "); num++; } }catch (FileNotFoundException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); }finally{ try { in.close(); }catch(IOException e){ e.printStackTrace(); } System.out.println(); System.out.println("共读取了 " + num + " 个字节"); } } }FileInputStream(例-1)
  • 28. import java.io.*; public class Test { public static void main(String[] args) { int b = 0; FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream("d:\\bak\\bak.bmp"); out = new FileOutputStream("d:\\bak\\bak1.bmp"); while((b=in.read())!=-1){ out.write(b); } in.close(); out.close(); } catch (FileNotFoundException e2) { System.out.println("找不到指定文件"); System.exit(-1); } catch (IOException e1) { System.out.println("文件复制错误"); System.exit(-1); } System.out.println("文件已复制"); } }FileOutputStream(例-1)
  • 29. import java.io.*; import java.util.Random; public class Test { public static void main(String[] args) { byte[] b = new byte[100]; Random random = new Random(); FileInputStream in = null; FileOutputStream out = null; try { in = new FileInputStream("d:\\bak\\bak.bmp"); out = new FileOutputStream("d:\\bak\\bak2.bmp"); if(in.read(b)!=-1) out.write(b); for(int i =0;i<=10000;i++){ out.write(random.nextInt(128)); } in.close(); out.close(); } catch (FileNotFoundException e2) { System.out.println("找不到指定文件"); System.exit(-1); } catch (IOException e1) { System.out.println("文件读写错误"); System.exit(-1); } } }FileOutputStream(例-2)
  • 30. 作业1一次从C:\test.txt读10个bytes,将读入的结果输出到标准输出设备,直到文件结束。 public class Fin { public Fin() { try { FileInputStream fis = new FileInputStream("e:/in.txt"); while (fis.available() > 0) { byte[] b = new byte[10]; int nResult = fis.read(b); if (nResult == -1)break; System.out.println(new String(b)); } fis.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { Fin fIn = new Fin(); } }
  • 31. 作业2将上面的例子改成:写入一个文档。 public class FOut { public FOut() { try { FileInputStream fIn = new FileInputStream("e:/in.txt"); FileOutputStream fOut = new FileOutputStream("e:/out.txt"); while (fIn.available() > 0) { byte[] b = new byte[10]; int nResult = fIn.read(b); if (nResult == -1)break; fOut.write(b, 0, nResult); } fIn.close(); fOut.close(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { FOut FOut1 = new FOut(); } }
  • 32. 访问文件FileReader 和 FileWriter 分别继承自Reader和Writer,FileInputSteam与FileOutputStream类似,所不同的时FileReader和FileWriter向文件输入和输出的数据单位为字符。 FileReader和FileWriter的常用构造方法:public FileWriter(File file) throws IOException public FileWriter(File file, boolean append) throws IOException public FileWriter(String fileName)throws IOException public FileWriter(String fileName,boolean append) throws IOException public FileReader(String fileName) throws FileNotFoundException public FileReader(File file) throws FileNotFoundException
  • 33. FileWriter (例) import java.io.*; public class Test { public static void main(String[] args) { FileWriter fw = null; try { fw = new FileWriter("d:\\bak\\unicode.dat"); for(int c=0;c<=50000;c++){ fw.write(c); } fw.close(); } catch (IOException e1) { System.out.println("文件写入错误"); System.exit(-1); } } }
  • 34. FileReader (例) import java.io.*; public class Test { public static void main(String[] args) { FileReader fr = null; int c = 0; try { fr = new FileReader("d:\\bak\\unicode.dat"); int ln = 0; while ((c = fr.read()) != -1) { char ch = (char) fr.read(); System.out.print(ch + " "); if (++ln >= 100) { System.out.println(); ln = 0;} } fr.close(); } catch (FileNotFoundException e) { System.out.println("找不到指定文件"); } catch (IOException e) { System.out.println("文件读取错误"); } } }
  • 35. 作业实现文件拷贝功能。例如将java.txt文件拷贝到j2se.txt中。利用Reader和Writer
  • 36. 参考答案 public class ReadWriteFile { public static void main(String[] args){ try{ File read = new File("c:\\java.txt"); File write = new File("c:\\j2se.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"); temp = br.readLine(); } bw.close(); br.close(); }catch(FileNotFoundException e){ //文件未找到 System.out.println (e); }catch(IOException e){ System.out.println (e); } } }
  • 37. 综合举例 import java.awt.*; import java.awt.event.*; import java.io.*; public class Test extends Frame implements ActionListener { private TextArea tx; private Button save, open; Test(int x, int y, int w, int h) { super("MyFrame"); setBackground(new Color(204, 204, 255)); setLayout(new BorderLayout()); setBounds(x, y, w, h); tx = new TextArea(); Panel p1 = new Panel( new FlowLayout(FlowLayout.CENTER, 30, 5)); save = new Button("保存"); open = new Button("打开"); p1.add(save); p1.add(open); add(new Label("编辑文件:"), BorderLayout.NORTH); add(p1, BorderLayout.SOUTH);add(tx, BorderLayout.CENTER); save.addActionListener(this); open.addActionListener(this); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(-1); } }); setVisible(true); } public static void main(String[] args) { Test f = new Test(400, 100, 300, 350) }
  • 38. 综合举例 -续 … … … public void actionPerformed(ActionEvent e) { FileDialog fd = null; File file = null; FileOutputStream out = null; FileReader in = null; if(e.getSource()==save) { fd = new FileDialog(this,"保存文件",FileDialog.SAVE); fd.setVisible(true); file = new File(fd.getDirectory(),fd.getFile()); byte[] text = tx.getText().getBytes(); try { out = new FileOutputStream(file); out.write(text); out.close(); } catch (IOException e1) {e1.printStackTrace();} } else if(e.getSource()==open){ fd = new FileDialog(this,"打开文件",FileDialog.LOAD); fd.setVisible(true); file = new File(fd.getDirectory(),fd.getFile()); try { in = new FileReader(file); char[] textBuffer = new char[1000]; tx.setText(""); while(in.read(textBuffer)!=-1) { tx.append(String.valueOf(textBuffer)); } in.close(); } catch (IOException e1) {e1.printStackTrace();} } } }
  • 39. 处理流类型处理类型 字 符 流字 节 流BufferingBufferedReader BufferedWriterBufferedInputStream BufferedOutputStreamFilteringFilterReader FilterWriterFilterInputStream FilterOutputStreamConverting between bytes and characterInputStreamReader OutputStreamWriterObject Serialization-ObjectInputStream ObjectOutputStreamData conversion-DataInputStream DataOutputStreamCountingLineNumberReaderLineNumberInputStreamPeeking aheadPusbackReaderPushbackInputStreamPintingPrintWriterPrintStream
  • 40. 缓冲流缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法。 J2SDK提供了四种缓存流,其常用的构造方法为:BufferedReader(Reader in) BufferedReader(Reader in,int sz) sz 为自定义缓存区的大小 BufferedWriter(Writer out) BufferedWriter(Writer out,int sz) BufferedInputStream(InputStream in) BufferedInputStream(InputStream in,int size) BufferedOutputStream(OutputStream out) BufferedOutputStream(OutputStream out,int size)
  • 41. 缓冲流提供的方法缓冲输入流支持其父类的mark和reset方法。 mark用于“标记”当前位置,可以使用reset方法返回这个标记重新读取数据。 BufferedReader提供了readLine方法用于读取一行字符串(以\r或\n分隔)。 BufferedWriter提供了newLine用于写入一个行分隔符。 对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush方法将会使内存中的数据立刻写出。
  • 42. 缓冲流举例(1) import java.io.*; public class Test { public static void main(String[] args) { try { FileInputStream fis = new FileInputStream("d:\\bak\\dat.txt"); BufferedInputStream bis = new BufferedInputStream(fis); int c = 0; System.out.println(bis.read()); System.out.println(bis.read()); bis.mark(100); for(int i=0;i<=10 && (c=bis.read())!=-1;i++){ System.out.print(c+" "); } System.out.println(); bis.reset(); for(int i=0;i<=10 && (c=bis.read())!=-1;i++){ System.out.print(c+" "); } bis.close(); } catch (IOException e) {e.printStackTrace();} } }
  • 43. 缓冲流举例(2) import java.io.*; public class Test { public static void main(String[] args) { try { BufferedWriter bw = new BufferedWriter( new FileWriter("d:\\bak\\string.dat")); BufferedReader br = new BufferedReader( new FileReader("d:\\bak\\string.dat")); String s = null; for(int i=1;i<=100;i++){ s = String.valueOf(Math.random()); bw.write(s);bw.newLine(); } bw.flush(); while((s=br.readLine())!=null){ System.out.println(s); } bw.close(); br.close(); } catch (IOException e) { e.printStackTrace();} } }
  • 44. 转换流InputStreamReader和OutputStreamWriter用与字节数据到字符数据之间的转换。 InputStreamReader 需要和 InputStream “套接” 。 OutputStreamWriter 需要和 OutputStream “套接” 。 转换流在构造时可以制定其编码集合,例如: InputStream isr = new InputStreamReader (System.in, “ISO8859_1”)
  • 45. 转换流举例(1) import java.io.*; public class Test { public static void main(String[] args) { try { OutputStreamWriter osw = new OutputStreamWriter( new FileOutputStream("d:\\bak\\char.txt")); osw.write("mircosoftibmsunapplehp"); System.out.println(osw.getEncoding()); osw.close(); osw = new OutputStreamWriter(new FileOutputStream ("d:\\bak\\char.txt",true),"ISO8859_1"); osw.write("mircosoftibmsunapplehp"); System.out.println(osw.getEncoding()); osw.close(); } catch (IOException e) { e.printStackTrace(); } } }
  • 46. 转换流举例(2) import java.io.*; public class Test { public static void main(String args[]) { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String s = null; try { s = br.readLine(); while(s!=null){ if(s.equalsIgnoreCase("exit")) break; System.out.println(s.toUpperCase()); s = br.readLine(); } br.close(); } catch (IOException e) { e.printStackTrace(); } } }
  • 47. 转换流举例(3) import java.io.*; public class Test { public static void main(String[] args) { LineNumberReader lnr = new LineNumberReader( new InputStreamReader( System.in)); lnr.setLineNumber(10); String s = null; try { while ((s = lnr.readLine()) != null) { if (s.equalsIgnoreCase("exit")) break; System.out.println(lnr.getLineNumber()); } } catch (IOException e) { e.printStackTrace(); } } }
  • 48. DataInputStream 和 DataOutputStream 分别继承自InputSteam 和 OutputStream,它属于处理流,需要分别“套接”在InputStream 和OutputStream类型的节点流上。 DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类型数据(如:int,double 等)的方法。 DataInputStream和DataOutputStream的构造方法为: DataInputStream ( InputStream in ) DataOutputStream ( OutputStream out )数据流
  • 49. 数据流举例 import java.io.*; public class Test { public static void main(String[] args) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); try { dos.writeDouble(Math.random()); dos.writeBoolean(true); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); System.out.println(bais.available()); DataInputStream dis = new DataInputStream(bais); System.out.println(dis.readDouble()); System.out.println(dis.readBoolean()); dos.close(); dis.close(); } catch (IOException e) { e.printStackTrace(); } } }
  • 50. PrintWriter和PrintStream 都属于输出流,分别针对与字符和字节。 PrintWriter和PrintStream提供了重载的print Println方法用于多种数据类型的输出。 PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息。 PrintWriter和PrintStream有自动flush的功能。Print 流
  • 51. PrintWriter(Writer out) PrintWriter(Writer out,boolean autoFlush) PrintWriter(OutputStream out) PrintWriter(OutputStream out,boolean autoFlush) PrintStream(OutputStream out) PrintStream(OutputStream out,booleanautoFlush)Print 流构造方法
  • 52. Print 流举例(1) import java.io.*; public class Test { public static void main(String[] args) { PrintStream ps = null; try { FileOutputStream fos = new FileOutputStream("d:\\bak\\log.dat"); ps = new PrintStream(fos); } catch (IOException e) { e.printStackTrace(); } if(ps != null){ System.setOut(ps); } int ln = 0; for(char c = 0; c <= 60000; c++){ System.out.print(c+ " "); if(ln++ >=100){ System.out.println(); ln = 0;} } } }
  • 53. Print 流举例(2) import java.io.*; public class Test { public static void main(String[] args) { String filename = args[0]; if(filename!=null){list(filename,System.out);} } public static void list(String f,PrintStream fs){ try { BufferedReader br = new BufferedReader(new FileReader(f)); String s = null; while((s=br.readLine())!=null){ fs.println(s); } br.close(); } catch (IOException e) { fs.println("无法读取文件"); } } }
  • 54. Print 流举例(3) import java.util.*; import java.io.*; public class Test { public static void main(String[] args) { String s = null; BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); try { FileWriter fw = new FileWriter ("d:\\bak\\logfile.log", true); PrintWriter log = new PrintWriter(fw); while ((s = br.readLine())!=null) { if(s.equalsIgnoreCase("exit")) break; System.out.println(s.toUpperCase()); log.println("-----"); log.println(s.toUpperCase()); log.flush(); } log.println("==="+new Date()+"==="); log.flush(); log.close(); } catch (IOException e) { e.printStackTrace(); } } }
  • 55. 作业对二进制文件进行操作,打开一个JPEG格式的文件,通过三种不同的方式读取内容,并生成一个新的文件。(三种方式分别是利用read(),read(buffer),read(buffer,offset,length))
  • 56. 利用流来解压缩文件Zip:广泛应用于Windows平台的一种压缩方式 Gzip:主要在Unix/Linux/BSD等类Unix平台上使用的一种文件压缩方式。 Jar:Java Archives,主要用于java类文件的打包和压缩。
  • 57. 在java中对文件进行zip格式的解压缩与zip压缩相关的java类: ZipEntry ZipOutputStream 和zip文件解压相关的类: ZipInputStream ZipEntry ZipFile
  • 58. 压缩成Zip文件ZipEntry Java中进行压缩和解压的单位。用来标识ZIP压缩文件中每个原始文件的入口 getCompressedSize():获取压缩文件大小 isDerectory():该压缩入口标识是否代表目录 getName():返回压缩入口标识的名称 ZipOutputStream 创建ZIP压缩文件 ZipOutputStream(OutputStream out)
  • 59. 压缩成Zip文件close():关闭ZIP输出流对象 closeEntry():关闭当前ZIP输出流对象指定的Entry,并移动到下一Entry putNextEntry(ZipEntry e):在ZIP压缩文件中创建新的压缩原始文件入口
  • 60. 案例1创建一个名为myZIP.zip的zip文件。其中源数据文件是当前工作目录下的所有文件。
  • 61. public class Zip { static final int BUFFER = 2048; public static void main (String argv[]) { try { BufferedInputStream origin = null; FileOutputStream dest = new FileOutputStream("c:\zip\myfigs.zip"); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest)); // out.setMethod(ZipOutputStream.DEFLATED); byte data[] = new byte[BUFFER]; // get a list of files from current directory File f = new File("."); String files[] = f.list(); for (int i=0; i < files.length; i++) { System.out.println("Adding: "+files[i]); FileInputStream fi = new FileInputStream(files[i]); origin = new BufferedInputStream(fi, BUFFER); ZipEntry entry = new ZipEntry(files[i]); out.putNextEntry(entry); int count; while((count = origin.read(data, 0, BUFFER)) != -1) { out.write(data, 0, count); } origin.close(); } out.close(); } catch(Exception e) { e.printStackTrace(); } } }
  • 62. 压缩文件的步骤第一步是创建一个ZipOutputStream对象,我们将要写入输出流的文件作为参数传给它 一但目标输出流创建后,下一步就是打开数据源文件 为读出的数据创建一个ZIP条目列表 在你将数据写入ZIP输出流之前,你必须使用putNextEntry方法将ZIP条目列表写入输出流 将数据写入ZIP文件 最后关闭所有的输入输出流
  • 63. 解压缩Zip文件ZipEntry 进行解压的单位 ZipInputStream 用于从ZIP压缩文件中创建输入流对象 方法与ZipOutputStream对比 ZipFile 用于读取压缩文件 构造方法 常用方法
  • 64. 案例1解压缩并从ZIP档案中将文件释放出来。
  • 65. public class UnZip { static final int BUFFER = 2048; public static void main(String argv[]) { try { BufferedOutputStream dest = null; FileInputStream fis = new FileInputStream(argv[0]); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis)); ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { System.out.println("Extracting: " + entry); int count; byte data[] = new byte[BUFFER]; // write the files to the disk FileOutputStream fos = new FileOutputStream(entry.getName()); dest = new BufferedOutputStream(fos, BUFFER); while ((count = zis.read(data, 0, BUFFER))!= -1) { dest.write(data, 0, count); } dest.flush(); dest.close(); } zis.close(); } catch (Exception e) { e.printStackTrace(); } } }
  • 66. Gzip压缩文件建立Gzip类 使用FileInputStream和FileOutputStream以及 GZipOutputStream
  • 67. Gzip的应用public class GZip { public static void main(String[] args) { if (args.length != 2) { System.out.println("Usage:java gzip "); System.exit(1); } try { // 打开需压缩文件作为文件输入流 FileInputStream fin = new FileInputStream(args[0]); // 建立压缩文件输出流 FileOutputStream fout = new FileOutputStream(args[1]); // 建立gzip压缩输出流 GZIPOutputStream gzout = new GZIPOutputStream(fout); byte[] buf = new byte[1024];// 设定读入缓冲区尺寸 int num; while ((num = fin.read(buf)) != -1) { gzout.write(buf, 0, num); } gzout.close();// fout.close(); fin.close(); } catch (IOException e) { System.out.println(e); } } }
  • 68. Gzip解压文件建立UnGZip类 使用FileInputStream和FileOutputStream以及 GZipInputStream
  • 69. public class UnGZip { public static void main(String[] args) { if (args.length !=2) { System.out.println("Usage:java ungzip "); System.exit(1); } try { // 建立gzip压缩文件输入流 FileInputStream fin=new FileInputStream(args[0]); // 建立gzip解压工作流 GZIPInputStream gzin=new GZIPInputStream(fin); // 建立解压文件输出流 FileOutputStream fout=new FileOutputStream(args[1]); byte[] buf=new byte[1024]; int num; while ((num=gzin.read(buf,0,buf.length)) != -1) { fout.write(buf,0,num); } gzin.close(); fout.close(); fin.close(); }catch(IOException e) { System.out.println(e.getMessage()); } } }
  • 70. 在java中对文件进行jar格式的压缩/解压缩和jar压缩相关的类 java.util.jar.JarOutputStream java.util.jar.JarEntry java.util.jar.Attributes/java.util.jar.Attributes.Name 和jar解压相关的类 java.util.jar.JarInputStream java.util.jar.JarEntry java.util.jar.JarFile java.util.jar.Attribute/java.util.jar.Attribute.Name
  • 71. NIO和“流”中对数据处理方式不同,在NIO中通过“块 ”读取方式来处理数据 通过NIO,可以让 Java 程序员实现高速 I/O 而无 需编写自定义的本机代码
  • 72. Buffer类Buffer类表示的是一个容器,它可以看成是一个数组 有八种常用的缓冲区类: ByteBuffer CharBuffer ShortBuffer IntBuffer LongBuffer FloatBuffer DoubleBuffer MappedByteBuffer只是一种特殊的 ByteBuffer。它将文件所在区域直接映射到内存
  • 73. capacity/position/limit在Buffer中,有三个重要的概念:容量(capacity)、界限(limit)和位置(position): 容量(capacity):缓冲区的 容量(capacity) 表示可以储存在缓冲区中的最大数据容量。缓冲区的容量不可能为负值,在创建后也不能改变; 界限(limit):第一个不应该被读出或者写入的缓冲区位置索引; 位置(position):用于指明下一个可以被读出的或者写入的缓冲区位置索引。在从通道读取时,position 变量跟踪已经写了多少数据。更准确地说,它指定了下一个字节将放到数组的哪一个元素中。 0 <= position <= limit <= capacity
  • 74. Buffer中常用方法int capacity():返回缓冲区的capacity大小; Buffer clear():"清空"缓冲区:它将limit设置成和capacity一样,而将position设置成0。注意这个方法并不会将缓冲区中的数据清除掉; Buffer flip():它将界限(limit)设置成当前的位置值(position),然后将位置值(position)回复到0,并返回重新设定limit和position后的缓冲区; boolean hasRemaining():判断当前位置(position)和界限(limit)之间是否还有元素可供处理; int limit():返回缓冲区的界限(limit); Buffer limit(int newLt):重新设置界限(limit)的值,并返回一个具有新的limit的缓冲区对象;
  • 75. Buffer常用方法Buffer mark():设置缓冲区的书签(mark),它只能在0和位置(position)之间做书签(mark),mark值和前面的limit、position、capacity的值的大小关系是:0 <= mark <= position <= limit <= capacity; int position():返回缓冲区中的当前位置(position); Buffer position(int newPs):设置缓冲区的新位置,并返回一个具有新的位置的缓冲区对象; int remaining():返回当前位置和界限(limit)之间的元素个数; Buffer reset():将位置回复到使用mark()方法设置的书签处; Buffer rewind():将位置(position)设置成0,取消设置的书签。
  • 76. Buffer例子CharBuffer buff = CharBuffer.allocate(9); //1 buff.put('a'); //2 buff.put('b'); //3 buff.put('c'); //4 buff.flip(); //5 System.out.println(buff.get()); //6 buff.clear(); //7
  • 77. Buffer例子aaaaaaaaaabaaaaaaacapacitylimitpositionpositioncapacitylimitabcaaaaaapositioncapacitylimitabcaaaaaapositioncapacitylimitabcaaaaaapositioncapacitylimitabcaaaaaapositioncapacitylimit//1//2//4//5//6//7
  • 78. Channel可以通过Channel读取或者写入对象 和流类似,但Channel是双向的,而流是单向的 在JDK1.4中对java.io包中的很多的类都进行了改写,其中的很多类都加入了获得对应的通道的功能,如FileInputStream/FileOutputStream的getChannel()
  • 79. 字符集Java中编码采用Unicode方式,而很多操作系统并不使用Unicode,那么在从系统中读取数据,在Java中进行处理的时候,可能会出现乱码等问题 Java中,通过字符集的编码器和解码器(Character-set encoders and decoders),使得我们可以直接访问操作系统内置的字符集。
  • 80. Charset和字符集相关的包: java.nio.charset:用于处理字符集的类 java.nio.charset.spi:用于提供字符集处理的服务的类:CharsetProvider 通过给Charset的forName()方法传递一个相应字符集的名字,就可以获得一个Charset对象: Charset cs = Charset.forName("ISO-8859-1"); Charset cs1 = Charset.forName("GBK");
  • 81. Charset在Java中提供了两个类用于编码和解码:CharsetDecoder和CharsetEncoder。 CharsetDecoder用于解码,根据特定的编码格式将一系列的字节数据转化成一系列的16位Unicode表示的字符 CharsetEncoder用于编码,根据特定的编码将一系列的用16位Unicode表示的字符转换成一系列的字节数据
  • 82. 文件锁现代的操作系统都提供了文件锁定功能 可以通过FileChannel的lock()/tryLock()方法来获得文件锁FileLock对象,从而锁定文件 记得处理完文件后通过FileLock的release()方法释放文件锁