JSP
网页应用程序开发
网页应用程序开发
教学目的:了解JSP中对文件操作的实现方法
5.1 File类
java.io.File类用来获取文件/目录本身的信息,如所在目录、文件长度、读写权限等。
File类的构造方法:
- File(String filename) filename是文件名字或绝对路径(注意:如不加路径,则默认文件位于Tomcat安装目录下的bin目录中)
- File(String directoryPath, String filename) directoryPath是文件所在目录路径,filename是文件名字
- File(File f, String filename) f是目录对象,filename是文件名字
File类的常用方法:
- String getName() 获取文件名字
- String getAbsolutePath() 获取文件的绝对路径
- boolean exists() 判断文件是否存在
- long length() 获取文件的长度(以字节为单位)
- boolean isFile() 判断文件是否为真正的文件而非目录
- boolean isDirectory() 判断文件是否为目录
- boolean canRead() 判断文件是否可读
- boolean canWrite() 判断文件是否可写
列出文件——如果File对象为目录,则可调用listFiles方法列出该目录下的文件和子目录
- public File[] listFiles() 获取目录下的全部File对象
例:列出指定目录下的文件
<h3>在线文件柜</h3> <% String myfiles = application.getRealPath("/files/"); File dir = new File(myfiles); File file[] = dir.listFiles(); for (int i = 0; i < file.length; i++) { if (file[i].isFile()) { out.print(file[i].getName().toString() + " - " + file[i].length() + "字节<br />"); } } %>
创建文件——调用createNewFile方法创建文件,mkdir方法创建目录
- boolean createNewFile() 创建文件,成功则返回true,否则返回false
- boolean mkdir() 创建目录,成功则返回true,否则返回false
例:根据用户提交的名字新建文件
<% String newname = request.getParameter("newname"); if (newname != null && newname != "" ) { File newFile = new File(myfiles, newname); newFile.createNewFile(); } %>
删除文件——调用delete方法删除对象代表的文件或目录(目录必须为空才可删除)
- boolean delete() 删除文件或目录,成功则返回true,否则返回false
例:根据用户提交的名字删除文件或目录
<% String delname = request.getParameter("delname"); if (delname != null && delname != "" ) { File delFile = new File(myfiles, delname); delFile.delete(); } %>
5.2 使用字节流读写文件
Java使用输入输出流读取和写入数据,常用的输入输出流类是文件输入/输出流FileInputStream/FileOutputStream
FileInputStream/FileOutputStream以字节为单位顺序地读取/写入文件
FileInputStream类的构造方法:
- FileInputStream(File file) file是文件对象
FileInputStream类的常用方法:
- int read(byte[] b) 读取输入流并存入字节数组
- void close() 关闭输入流
FileOutputStream类的构造方法:
- FileOutputStream(File file) file是文件对象
FileOutputStream类的常用方法:
- void write(byte[] b) 将字节数组写入输出流
- void close() 关闭输出流
为了提高读写效率,FileInputStream/FileOutputStream需要与缓存输入/输出流BufferedInputStream/BufferedOutputStream配合使用
BufferedInputStream类的构造方法:
- BufferedInputStream(InputStream in) in是输入流对象
BufferedInputStream类的常用方法:
- int read(byte[] b) 读取缓存输入流并存入字节数组
- void close() 关闭缓存输入流
BufferedOutputStream类的构造方法:
- BufferedOutputStream(OutputStream out) out是输出流对象
BufferedOutputStream类的常用方法:
- void write(byte[] b) 将字节数组写入缓存输出流
- void flush() 刷新缓存即把缓存内容发送到文件输出流
- void close() 关闭缓存输出流
例:根据用户提交的名字,使用字节流读取文件内容并显示
<% String filename = request.getParameter("filename"); if (filename != null && filename != "" ) { File f = new File(myfiles, filename); try { FileInputStream i = new FileInputStream(f); BufferedInputStream bi = new BufferedInputStream(i); byte b[] = new byte[100]; int n = 0; while ((n = bi.read(b)) != -1) { String temp = new String(b, 0, n); out.print(temp); } bi.close(); i.close(); } catch(IOException e) {} } %>
例:根据用户提交的内容,使用字节流写入文件内容
<% String content = request.getParameter("content"); if (content != null) { File f = new File(myfiles, filename); try { FileOutputStream o = new FileOutputStream(f); BufferedOutputStream bo = new BufferedOutputStream(o); byte c[] = content.getBytes(); bo.write(c); bo.flush(); bo.close(); o.close(); } catch(IOException e) {} } %>
5.3 使用字符流读写文件
字符流类以Unicode字符为单位读写数据。在Unicode编码方式下,一个英文字母和一个汉字都是一个字符。常用的字符流类是输入/输出字符流InputStreamReader/InputStreamWriter及其子类文件字符流FileReader/FileWriter。
(注意:FileWriter/FileReader不支持通过参数指定字符编码方式,因此无法用于utf-8字符编码的文件)
为了提高读写效率,字符流需要与缓存读取/写入流BufferedReader/BufferedWriter配合使用。
例:使用字符流读取文件内容
<% if (filename != null && filename != "" ) { File f = new File(myfiles, filename); StringBuffer mess = new StringBuffer(); try { InputStreamReader r = new InputStreamReader(new FileInputStream(f), "utf-8"); BufferedReader br = new BufferedReader(r); String temp; while ((temp = br.readLine()) != null) { mess.append(temp + "\n"); } br.close(); r.close(); } catch(IOException e) {} out.print(new String(mess)); } %>
例:使用字符流写入文件内容
<% String content = request.getParameter("content"); if (content != null) { byte b[] = content.getBytes("iso-8859-1"); content = new String(b, "utf-8"); File f = new File(myfiles, filename); try { OutputStreamWriter w = new OutputStreamWriter(new FileOutputStream(f), "utf-8"); BufferedWriter bw = new BufferedWriter(w); bw.write(content); bw.close(); w.close(); } catch(IOException e) {} } %>5.4 文件上传
上传文件需要使用包含文件域的表单(表单的编码类型应为multipart/form-data),让内置对象request调用getInputStream方法即可获得一个用户上传信息的输入流并输出到指定的文件。
例:上传文件并保存为指定的名字
<% try { InputStream i = request.getInputStream(); File upFile = new File(myfiles, "upFile.txt"); FileOutputStream o = new FileOutputStream(upFile); byte b[] = new byte[1000]; int n; while ((n = i.read(b)) != -1) { o.write(b, 0, n); } o.close(); i.close(); out.print("文件上传成功!"); } catch(IOException e) { out.print("文件上传失败!"); } %>
注意:以上程序保存的文件不仅包含原文件,还有用户提交的其他信息(文件的前4行和末5行内容),应该去除这些内容才能得到原文件。
例:上传文件程序修正版(本例使用更灵活的随机存取文件类RandomAccessFile进行文件读写,该类的seek方法可自由指定当前流的读写位置,getFilePointer方法可获取当前流的读写位置)
<% try { //建立临时文件,文件名为用户会话ID String tempFile = (String)session.getId(); File f1 = new File(myfiles, tempFile); FileOutputStream o = new FileOutputStream(f1); //将用户上传的全部信息存入临时文件 InputStream i = request.getInputStream(); byte b[] = new byte[10000]; int n; while ((n = i.read(b)) != -1) { o.write(b, 0, n); } o.close(); i.close(); //读取临时文件 RandomAccessFile random = new RandomAccessFile(f1, "r"); //从第2行最后一个=字符之后获取原文件的名字 int second = 1; String secondLine = null; while (second <= 2) { secondLine = random.readLine(); second++; } int position = secondLine.lastIndexOf('='); String fileName = secondLine.substring(position + 2, secondLine.length() - 1); //确定原文件的开始:从第4行的回车符起 long forthEndPosition = 0; int forth = 1; while((n = random.readByte()) != -1 && (forth <= 4)) { if (n == '\n') { forthEndPosition = random.getFilePointer(); forth++; } } //保存原文件 byte cc[] = fileName.getBytes("iso-8859-1"); fileName = new String(cc, "utf-8"); File f2 = new File(myfiles, fileName); RandomAccessFile random2 = new RandomAccessFile(f2, "rw"); //确定原文件的末尾:到倒数第6行止 random.seek(random.length()); long endPosition = random.getFilePointer(); long mark = endPosition; int j = 1; while ((mark >= 0) && (j <= 6)) { mark--; random.seek(mark); n = random.readByte(); if (n == '\n') { endPosition = random.getFilePointer(); j++; } } //将random流指向原文件第4行结束的位置 random.seek(forthEndPosition); long startPoint = random.getFilePointer(); //读取临时文件存入新文件 while (startPoint < endPosition - 1) { n = random.readByte(); random2.write(n); startPoint = random.getFilePointer(); } random2.close(); random.close(); //删除临时文件 f1.delete(); out.print("文件上传成功!"); } catch(IOException e) { out.print("文件上传失败!"); } %>
5.5 文件下载
使用response对象的setHerader方法即可向客户端发送下载文件的HTTP头信息。
response.setHeader("Content-disposition","attachment;filename=<下载文件名>");
例:根据用户提交的名字下载文件
String down = request.getParameter("down"); if (down != null && down != "" ) { byte d[] = down.getBytes("iso-8859-1"); down = new String(d, "utf-8"); response.setHeader("Content-disposition","attachment;filename=" + down); try { File dl = new File(myfiles, down); FileInputStream i = new FileInputStream(dl); OutputStream o = response.getOutputStream(); int n = 0; byte b[] = new byte[1000]; while((n = i.read(b)) != -1) { o.write(b, 0, n); } o.close(); i.close(); } catch(Exception e) {} }
博主 in 教程 01:59下午 10月 13, 2012
Tags: 教学