Presentation is loading. Please wait.

Presentation is loading. Please wait.

第五讲 JSP中的文件操作(1) 教学目的 本讲主要讲述JSP中使用Java输入、输出流实现文件的读写 操作 。 知识要点

Similar presentations


Presentation on theme: "第五讲 JSP中的文件操作(1) 教学目的 本讲主要讲述JSP中使用Java输入、输出流实现文件的读写 操作 。 知识要点"— Presentation transcript:

1 第五讲 JSP中的文件操作(1) 教学目的 本讲主要讲述JSP中使用Java输入、输出流实现文件的读写 操作 。 知识要点
1 Flie 对象 2 字节输入、输出流对象 3 字符输入、输出流对象 4 随机文件流

2 第五讲 JSP中的文件操作(1) 有时服务器需要将客户提交的信息保存到文件或根据客户的要求将服务器上的文件的内容显示到客户端。JSP通过Java的输入输出流来实现文件的读写操作。

3 5.1 File 类 File类的对象主要用来获取文件本身的一些信息,例如文件所在的目录、文件的长度、文件读写权限等,不涉及对文件的读写操作。 创建一个File对象的构造方法有3个: File(String filename); File(String directoryPath,String filename); File(File f, String filename); 其中,filename是文件名字,directoryPath是文件的路径,f是指定成一个目录的文件。 使用File(String filename)创建文件时,该文件被认为是与当前应用程序在同一目录中,由于JSP引擎是在bin下启动执行的,所以该文件被认为在下列目录中: D:\Tomcat\jakarta-tomcat-4.0\bin\ 。

4 5.1.1 获取文件的属性 经常使用File类的下列方法获取文件本身的一些信息:
获取文件的属性 经常使用File类的下列方法获取文件本身的一些信息: 1. public String getName(): 获取文件的名字。 2. public boolean canRead(): 判断文件是否是可读的。 3. public boolean canWrite(): 判断文件是否可被写入。 4. public boolean exits(): 判断文件是否存在。 5. public long length(): 获取文件的长度(单位是字节)。 6. public String getAbsolutePath():获取文件的绝对路径。 7. public String getParent(): 获取文件的父目录。 8. public boolean isFile(): 判断文件是否是一个正常文件,而不是目录. 9. public boolean isDirectroy(): 判断文件是否是一个目录。 10. public boolean isHidden(): 判断文件是否是隐藏文件。 11. public long lastModified(): 获取文件最后修改的时间(时间是从1970年午夜至文件最后修改时刻的毫秒数)。

5 在下面的例子1中,我们使用上述的一些方法,获取某些文件的信息。
Example5_1.jsp page contentType="text/html;charset=GB2312" %> page import="java.io.*"%> <HTML> <BODY bgcolor=cyan><Font Size=1> <%File f1=new File("D:\\Tomcat\\jakarta-tomcat-4.0\\webapps\\root","Example5_1.jsp"); File f2=new File("jasper.sh"); %> <P> 文件 Example5-1. jsp是可读的吗? <%=f1.canRead()%> <BR> <P>文件Example5_1.jsp的长度: <%=f1.length()%>字节 <P> jasper.sh是目录吗? <%=f2.isDirectory()%> <P> Example5-1.jsp的父目录是: <%=f1.getParent()%> <P>jasper.sh的绝对路径是: <%=f2.getAbsolutePath()%> </Font> </BODY> </HTML>

6 创建目录 (1)创建目录 File对象调用方法:public boolean mkdir()创建一个目录,如果创建成功返回true,否则返回false(如果该目录已经存在将返回false)。 在下面的例子2中,我们在Root下创建一个名字是Students的目录. page contentType="text/html;charset=GB2312" %> page import="java.io.*"%> <HTML> <BODY><Font Size=2> <% File dir=new File("D:/Tomcat/jakarta-tomcat-4.0/webapps/root","Students"); %> <P> 在root下创建一个新的目录:Student,<BR>成功创建了吗? <%=dir.mkdir()%> <P> Student是目录吗? <%=dir.isDirectory()%> </Font> </BODY> </HTML> 例子2

7 如果File对象是一个目录,那么该对象可以调用下述方法列出该目录下的文件和子目录:
(2)列出目录中的文件 如果File对象是一个目录,那么该对象可以调用下述方法列出该目录下的文件和子目录: public String[] list(): 用字符串形式返回目录下的全部文件, public File [] listFiles():用File对象形式返回目录下的全部文件。 在下面的例子3中,输出了Root下的全部文件中的5个和全部子目录。 例子3 page contentType="text/html;charset=GB2312" %> page import="java.io.*"%> <HTML> <BODY><Font Size=2>

8 <% File dir=new File("D:/Tomcat/jakarta-tomcat-4.0/webapps/root");
File file[]=dir.listFiles(); %> <P> 列出root下的5个长度大于1000字节的文件和全部目录: <BR>目录有: <% for(int i=0;i<file.length;i++) {if(file[i].isDirectory()) out.print("<BR>"+file[i].toString()); } <P> 5个长度大于1000 字节的文件名字: <% for(int i=0,number=0;(i<file.length)&&(number<=5);i++) {if(file[i].length()>=1000) {out.print("<BR>"+file[i].toString()); number++; </Font> </BODY> </HTML> 续前页:

9 删除文件和目录 File对象调用方法public boolean delete()可以删除当前对象代表的文件或目录,如果File对象表示的是一个目录,则该目录必须是一个空目录,删除成功返回true。 下面的例子4删除Root目录下的A.java文件和Students目录。

10 例子4 <%@ page contentType="text/html;charset=GB2312" %>
page import ="java.io.*" %> <HTML> <BODY> <%File f=new File("d:/Tomcat/Jakarta-tomcat-4.0/webapps/root/","A.java"); File dir=new File("d:/Tomcat/Jakarta-tomcat-4.0/webapps/root","Students"); boolean b1=f.delete(); boolean b2=dir.delete(); %> <P>文件A.java成功删除了吗? <%=b1%> <P>目录Students成功删除了吗? <%=b2%> </BODY> </HTML>

11 使用字节流读写文件 Java的I/O流提供一条通道程序,可以使用这条通道把源中的数据送给目的地。把输入流的指向称做源,程序从指向源的输入流中读取源中的数据。而输出流的指向是数据要去的一个目的地,程序通过向输出流中写入数据把信息传递到目的地,如下图5.1、5.2所示。java.io包提供大量的流类。所有字节输入流类都是InputStream(输入流)抽象类的子类,而所有字节输出流都是OutputStream(输出流)抽象类的子类。

12 输入流通过使用read()方法从输入流读出 来自源中的数据 图5.1 输入流示意图 目的地 输出流通过使用write()方法把数据写入输出流到达目的地 图5.2输出流示意图

13 InputStream类的常用方法: int read(): 输入流调用该方法从源中读取单个字节的数据,该方法返 回字节值(0~255之间的一个整数),如果未读出字节就返回-1。 int read(byte b[]): 输入流调用该方法从源中试图读取b.length个字节到 b中,返回实际读取的字节数目。如果到达文件的末尾,则返回-1。 int read(byte b[], int off, int len): 输入流调用该方法从源中试图读取 len个字节到b中,并返回实际读取的字节数目。如果到达文件的末尾, 则返回-1,参数off指定从字节数组的某个位置开始存放读取的数据。 void close(): 输入流调用该方法关闭输入流。 long skip(long numBytes): 输入流调用该方法跳过numBytes个字节,并 返回实际跳过的字节数目。

14 OutputStream类的常用方法: void write(int n): 输出流调用该方法向输出流写入单个字节。 void write(byte b[]): 输出流调用该方法向输出流写入一个字节数组。 void write(byte b[],int off,int len): 从给定字节数组中起始于偏移量off处 取len个字节写到输出流。 void close(): 关闭输出流。

15 5.2.1 FileInputStream 和FileOutputStream类
FileInputStream该类是从InputStream中派生出来的简单输入类。该类的所有方法都是从InputStream类继承来的。为了创建FileInputStream类的对象,用户可以调用它的构造方法。下面显示了两个构造方法: FileInputStream(String name); FileInputStream(File file); 第一个构造方法使用给定的文件名name创建一个FileInputStream对象,第二个构造方法使用File对象创建FileInputStream对象。参数name和file指定的文件称做输入流的源,输入流通过调用read方法读出源中的数据。 FileInpuStream文件输入流打开一个到达文件的输入流(源就是这个文件,输入流指向这个文件)例如,为了读取一个名为myfile.dat的文件,建立一个文件输入流对象,如下所示: try {FileInputStream ins = new FileInputStream("myfile.dat"); } catch (IOException e ) { //文件I/O错误 System.out.println("File read error: " +e );

16 与FileInputStream类相对应的类是FileOutputStream类。FileOutputStream提供了基本的文件写入能力。除了从FileOutputStream类继承来的方法以外,FileOutputStream类还有两个常用的构造方法,这两个构造方法如下所示: FileOutputStream(String name); FileOutputStream(File file);

17 5.2.2 BufferedInputStream和BufferedOutputStream类
为了提高读写的效率,FileInputStream流经常和BufferedInputStream流配合使用,FileOutputStream流经常和BufferedOutputStream流配合使用。 BufferedInputStream的一个常用的构造方法是: BufferedInputStream(InputStream in); 该构造方法创建缓存输入流,该输入流的指向是一个输入流。当我们要读取一个文件,比如A.txt时,可以先建立一个指向该文件的文件输入流: FileInputStream in=new FileInputStream(“A.txt”); 然后再创建一个指向文件输入流in的输入缓存流(就好象把两个输入水管接在一起): BufferedInputStream buffer=new BufferedInputStream(in);

18 这时,我们就可以让buffer调用read方法读取文件的内容,buffer在读取文件的过程中,会进行缓存处理,增加读取的效率。
同样,当要向一个文件,比如B.txt,写入字节时,可以先建立一个指向该文件的文件输出流: FileOutputStream out=new FileOutputStream(“B.txt”); 然后再创建一个指向输出流out的输出缓存流: BufferedOutputStream buffer=new BufferedOutputStream(out); 这时,buffer调用write方法向文件写入内容时会进行缓存处理,增加写入的效率。需要注意的是,写入完毕后,须调用flush方法将缓存中的数据存入文件。

19 在下面的例子5中,服务器将若干内容写入一个文件,然后读取这个文件,并将文件的内容显示给客户。
page contentType="text/html;charset=GB2312" %> page import ="java.io.*" %> <HTML> <BODY bgcolor=cyan><FONT size=1> <%File dir=new File("d:/Tomcat/Jakarta-tomcat-4.0/webapps/root","Students"); dir.mkdir(); File f=new File(dir,"hello.txt");

20 try{ FileOutputStream outfile=new FileOutputStream(f); 续前页:
BufferedOutputStream bufferout=new BufferedOutputStream(outfile); byte b[]="你们好,很高兴认识你们呀!<BR>nice to meet you".getBytes(); bufferout.write(b); bufferout.flush(); bufferout.close(); outfile.close(); FileInputStream in=new FileInputStream(f); BufferedInputStream bufferin=new BufferedInputStream(in); byte c[]=new byte[90]; int n=0; while((n=bufferin.read(c))!=-1) { String temp=new String(c,0,n); out.print(temp); } bufferin.close(); in.close(); catch(IOException e) { %> </BODY> </HTML> 续前页:

21 5.3 使用字符流读写文件 上面我们学习了使用字节流读写文件,字节流不能直接操作Unicode字符,所以Java提供了字符流,由于汉字在文件中占用2个字节,如果使用字节流,读取不当会出现乱码现象,采用字符流就可以避免这个现象,在Unicode字符中,一个汉字被看作一个字符。 所有字符输入流类都是Reader(输入流)抽象类的子类,而所有字符输出流都是Writer(输出流) 抽象类的子类。

22 Reader类中常用方法: int read(): 输入流调用该方法从源中读取一个字符,该方法返回一个整数(0~65535之间的一个整数,Unicode字符值),如果未读出字符就返回-1。 int read(char b[]): 输入流调用该方法从源中读取b.length个字符到字符数组b中,返回实际读取的字符数目。如果到达文件的末尾,则返回-1。 int read(char b[], int off, int len): 输入流调用该方法从源中读取len个字符并存放到字符数组b中,返回实际读取的字符数目。如果到达文件的末尾,则返回-1。其中,off 参数指定read方法从符数组b中的什么地方存放数据。 void close(): 输入流调用该方法关闭输入流。 long skip(long numBytes): 输入流调用该方法跳过numBytes个字符,并返回实际跳过的字符数目。

23 Writer类中 常用方法: void write(int n): 向输入流写入一个字符。 void write(char b[]): 向输入流写入一个字符数组。 void write(char b[],int off,int length): 从给定字符数组中起始于偏移量off处取len个字符写到输出流。 void close(): 关闭输出流。

24 5.3.1 FileReader 和FileWriter类
FileReader该类是从Reader中派生出来的简单输入类。该类的所有方法都是从Reader类继承来的。为了创建FileReader类的对象,用户可以调用它的构造方法。下面显示了两个构造方法: FileReader(String name); FileReader (File file) ; 与FileReader类相对应的类是FileWriter类。FileWriter提供了基本的文件写入能力。除了从FileWriter类继承来的方法以外,FileWriter类还有两个常用的构造方法,这两个构造方法如下所示: FileWriter(String name); FileWriter (File file);

25 5.3.2 BufferedReader和BufferedWriter类
为了提高读写的效率,FileReader流经常和BufferedReader流配合使用;FileWriter流经常和BufferedWriter流配合使用。BufferedReader流还可以使用方法String readLine()读取一行;BufferedWriter流还可以使用方法void write(String s,int off,int length)将字符串s的一部分写入文件,使用newLine()向文件写入一个行分隔符。 在下面的例子6中,服务器将若干内容写入一个文件,然后读取这个文件,并将文件的内容显示给客户。 例子6 page contentType="text/html;charset=GB2312" %> page import ="java.io.*" %> <HTML> <BODY> <% File dir=new File("d:/Tomcat/Jakarta-tomcat-4.0/webapps/root","Students");

26 dir.mkdir(); File f=new File(dir,"apple.txt");
try{FileWriter outfile=new FileWriter(f); BufferedWriter bufferout=new BufferedWriter(outfile); bufferout.write("你好:"); bufferout.newLine(); bufferout.write("好久不见了,近来在忙什么呢?"); bufferout.write("欢迎来玩"); bufferout.write("2002年8月8日"); bufferout.flush(); bufferout.close(); outfile.close(); FileReader in=new FileReader(f); BufferedReader bufferin=new BufferedReader(in); String str=null; while((str=bufferin.readLine())!=null) {out.print("<BR>"+str); } 续前页:

27 bufferin.close(); in.close(); } catch(IOException e) { %>
续前页: bufferin.close(); in.close(); } catch(IOException e) { %> </BODY> </HTML>

28 5.4 RandomAccessFile类 前面我们学习了用来处理文件的几个文件输入流、文件输出流,而且通过一些例子,已经了解了那些流的功能。 RandomAccessFile类创建的流与前面的输入、输出流不同,RandomAccessFile类既不是输入流类InputStream类的子类,也不是输出流类OutputStram类的子类流。习惯上,仍然称RandomAccessFile类创建的对象为一个流,RandomAccessFile流的指向既可以作为源也可以作为目的地,换句话说,当我们想对一个文件进行读写操作时,我们可以创建一个指向该文件的RandomAccessFile流即可,这样我们既可以从这个流中读取这个文件的数据,也通过这个流写入数据给这个文件。

29 RandomAccessFile类的两个构造方法:
RandomAccessFile(String name,String mode):参数name用来确定一个文件名,给出创建的流的源(也是流目的地),参数mode取“r”(只读)或“rw”(可读写),决定创建的流对文件的访问权利。 RandomAccessFile(File file,String mode): 参数file是一个File对象,给出创建的流的源(也是流目的地),参数mode取“r”(只读)或“rw”(可读写),决定创建的流对文件的访问权利。创建对象时应捕获FileNotFoundException异常,当流进行读写操作时,应捕获IOException异常。

30 表5.1 RandomAccessFile类的常用方法
RandomAccessFile类中有一个方法seek(long a),用来移动RandomAccessFile流指向的文件的指针,其中参数 a 确定文件指针距离文件开头的字节位置。另外流还可以调用getFilePointer()方法获取当前文件的指针的位置(RandomAccessFile类的一些方法见下表),RandomAccessFile流对文件的读写比顺序读写的文件输入输出流更为灵活。 表5.1 RandomAccessFile类的常用方法

31

32 下面的例子实现网上小说创作,每个客户都可以参与一部小说的写作,也就是说一个客户需接着前一个客户的写作内容继续写作。在服务器的某个目录下有4部小说,小说的内容完全由客户来决定。客户首先在Example5_7.jsp页面选择一部小说的名字,然后连接到continueWrite.jsp页面,该页面显示小说的已有内容,客户可以在该页面输入续写的内容,再提交给continue.jsp页面,该页面负责将续写的内容存入文件,并通知客户续写是否成功,如果其他用户正在保存续写的内容到该小说,就通知该客户等待。

33 图5.4 编辑、提交续写的内容 图5.3 选择续写的小说 图5.5 续写内容成功提示

34 例子7(效果如图5.3、5.4、5.5所示) Example5_7.jsp:
page contentType="text/html;charset=GB2312" %> page import ="java.io.*" %> <HTML> <BODY bgcolor=cyan><Font size=1> <% String str=response.encodeURL("continueWrite.jsp"); %> <P>选择您想续写小说的名字:<BR> <FORM action="<%=str%>" method=post name=form> <BR><INPUT type="radio" name="R" value="spring.doc" >美丽的故事 <BR><INPUT type="radio" name="R" value="summer.doc" >火热的夏天 <BR><INPUT type="radio" name="R" value="autumn.doc" >秋天的收获 <BR><INPUT type="radio" name="R" value="winter.doc" >冬天的大雪 <BR> <INPUT type=submit name ="g" value="提交"> </FORM> </BODY> </HTML>

35 continueWrite.jsp: page contentType="text/html;charset=GB2312" %> page import ="java.io.*" %> <HTML> <BODY bgcolor=cyan><Font size=1> <P>小说已有内容: <Font size=1 Color=Navy> <%String str=response.encodeURL("continue.jsp"); %> <%--获取客户提交的小说的名字--%> <%String name=(String)request.getParameter("R"); if(name==null) {name=""; } byte c[]=name.getBytes("ISO "); name=new String(c); session.setAttribute("name",name); File storyFileDir=new File("F:/2000","story"); storyFileDir.mkdir(); File f=new File(storyFileDir,name); //列出小说的内容:

36 try{ RandomAccessFile file=
new RandomAccessFile(f,"r"); String temp=null; while((temp=file.readUTF())!=null) { byte d[]=temp.getBytes("ISO "); temp=new String(d); out.print("<BR>"+temp); } file.close(); catch(IOException e){} %> </Font> <P>请输入续写的新内容: <Form action="<%=str%>" method=post name=form> <TEXTAREA name="messages" ROWs="12" COLS=80 WRAP="physical"> </TEXTAREA> <BR> <INPUT type="submit" value="提交信息" name="submit"> </FORM> 续前页:

37 continue.jsp: <%@ page contentType="text/html;charset=GB2312" %>
page import ="java.io.*" %> page import ="java.util.*" %> <HTML> <BODY> <%! //声明一个需同步处理的文件: File f=null; String use="yes"; %> <%--获取客户提交的小说的名字--%> <% String name=(String)session.getAttribute("name"); byte c[]=name.getBytes("ISO "); name=new String(c); //获取客户续写的内容: String content=(String)request.getParameter("messages"); if(content==null) {content=" "; } <%File storyFileDir=new File("F:/2000","story"); storyFileDir.mkdir(); f=new File(storyFileDir,name);

38 //把对文件的操作放入一个同步块中,并通知 //其它用户该文件正在被操作中: if(use.startsWith("yes"))
{ synchronized(f) { use="beisusing"; try{ RandomAccessFile file=new RandomAccessFile(f,"rw"); file.seek(file.length()); //定位到文件的末尾。 file.writeUTF(content); file.close(); use="yes"; out.print("<BR>"+"内容已经写入"); } catch(IOException e){} //如果该小说正在被续写,就通知客户等待: else {out.print("该小说正在被续写,请等待"); %> </BODY> </HTML> 续前页:


Download ppt "第五讲 JSP中的文件操作(1) 教学目的 本讲主要讲述JSP中使用Java输入、输出流实现文件的读写 操作 。 知识要点"

Similar presentations


Ads by Google