JSP

网页应用程序开发

JSP教学05 文件操作

教学目的:了解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) {}
}

评论:

发表评论:
该文章禁用评论功能。