这一篇是前面几篇的综合,前面几篇是基础,文件浏览器无非就是遍历目录,查看文件。J2ME文件浏览器的源码网上已经有了,是MIDP写的,我把它改造为LWUIT版本。这两种方式的文件浏览器我都在真机上测试通过,不过MIDP版本的在读取文本文件时,中文出现乱码,原因是它采用的是GBK编码形式,在源码中把格式换成UTF-8就可以了。
文件浏览器的原理比较简单,手机需要支持JSR75,根据前面的知识还是比较容易做出来的。
下面是简单的流程图:
用LWUIT做文件浏览器只需要3个Form:
- ListForm,包含List组件,用于显示文件和文件夹列表
- ImageForm,包含Button组件,Button用于盛装图片
- TextForm,包含TextArea组件,用户盛装文本
无图无真相,还是先看看效果:
源代码下载地址(通过测试)
代码:
IconHelper.java图标帮助类,根据文件扩展名显示相应图标
package main;
/*
File:
IconHelper.java
Purpose:
图标帮助类
Functions:
getIconByExt public 按照扩展名(不包括'.'符号)获取文件的图标对象
History:
%yongsongw% @ 2008-8-1: created.
Copyright (C) 2008 Fool studio.
All rights reserved.
*/
import java.util.Hashtable;
import com.sun.lwuit.Image;
import java.io.IOException;
public class IconHelper {
//图标资源
private Image imgFolder;
private Image unknownImage;
private Image textImage;
//Audio
private Image audioImage;
//Picture
private Image picImage;
private Image jpgImage;
//Video
private Image sgpImage;
private Image aviImage;
private Image wmvImage;
private Image mpgImage;
//Web
private Image zipImage;
private Image htmlImage;
private Image xmlImage;
//Source
private Image cImage;
private Image cppImage;
private Image headerImage;
//图标管理容器
private Hashtable iconTable;
//-------------------------------------------------------------------------
public IconHelper() {
iconTable = new Hashtable();
try {
//载入图标资源
imgFolder = Image.createImage("/filetype/folder.png");
unknownImage = Image.createImage("/filetype/unknown.png");
textImage = Image.createImage("/filetype/text.png");
//Audio
audioImage = Image.createImage("/filetype/audio.png");
//Picture
picImage = Image.createImage("/filetype/pic.png");
jpgImage = Image.createImage("/filetype/jpg.png");
//Video
sgpImage = Image.createImage("/filetype/3gp.png");
aviImage = Image.createImage("/filetype/avi.png");
wmvImage = Image.createImage("/filetype/wmv.png");
mpgImage = Image.createImage("/filetype/mpg.png");
//Web
zipImage = Image.createImage("/filetype/zip.png");
htmlImage = Image.createImage("/filetype/html.png");
xmlImage = Image.createImage("/filetype/xml.png");
//Source
cImage = Image.createImage("/filetype/c.png");
cppImage = Image.createImage("/filetype/cpp.png");
headerImage = Image.createImage("/filetype/header.png");
}
catch (IOException e) {
//图标资源
imgFolder = null;
unknownImage = null;
textImage = null;
//Audio
audioImage = null;
//Picture
picImage = null;
jpgImage = null;
//Video
sgpImage = null;
aviImage = null;
wmvImage = null;
mpgImage = null;
//Web
zipImage = null;
htmlImage = null;
xmlImage = null;
//Source
cImage = null;
cppImage = null;
headerImage = null;
e.printStackTrace();
}
initTable();
}
//-------------------------------------------------------------------------
private void initTable() {
//Key为扩展名(不包括'.'符号),值为content type
iconTable.put("/", imgFolder);
iconTable.put("", unknownImage);
iconTable.put("txt", textImage);
//Source
iconTable.put("c", cImage);
iconTable.put("cpp", cppImage);
iconTable.put("h", headerImage);
//Web
iconTable.put("html", htmlImage);
iconTable.put("htm", htmlImage);
iconTable.put("xml", xmlImage);
iconTable.put("zip", zipImage);
iconTable.put("jar", zipImage);
//Video
iconTable.put("mp3", audioImage);
iconTable.put("wma", audioImage);
iconTable.put("mid", audioImage);
iconTable.put("wav", audioImage);
//Picture
iconTable.put("gif", picImage);
iconTable.put("png", picImage);
iconTable.put("jpg", jpgImage);
iconTable.put("jepg", jpgImage);
//Video
iconTable.put("3gp", sgpImage);
iconTable.put("avi", aviImage);
iconTable.put("wmv", wmvImage);
iconTable.put("mpeg", mpgImage);
iconTable.put("mpg", mpgImage);
iconTable.put("mp4", mpgImage);
}
//-------------------------------------------------------------------------
//按照扩展名(不包括'.'符号)获取文件的图标对象
public Image getIconByExt(final String extension) {
Image temp = (Image)iconTable.get(extension);
//是否为空,则使用默认图标替代
return( (temp == null) ? unknownImage : temp);
}
//-------------------------------------------------------------------------
}
MainPanel主面板,显示文件、文件夹列表,浏览文件:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package main;
import com.sun.lwuit.Button;
import com.sun.lwuit.Command;
import com.sun.lwuit.Component;
import com.sun.lwuit.Container;
import com.sun.lwuit.Dialog;
import com.sun.lwuit.Form;
import com.sun.lwuit.Image;
import com.sun.lwuit.Label;
import com.sun.lwuit.List;
import com.sun.lwuit.TextArea;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.layouts.BorderLayout;
import com.sun.lwuit.list.ListCellRenderer;
import com.sun.lwuit.plaf.Border;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.io.file.FileSystemRegistry;
/**
*
* @author Sunny
*/
public class MainPanel implements ActionListener {
//常量定义
private final String UP_DIR = "..";
private final String SEPS_STR = "/";
private final int SEPS_CHAR = '/';
private final String ROOT = "/";
private final String RES_PREFIX = "file://";
private final int BLOCK_SIZE = 256;
//扩展名
private final String TEXT_EXT[] = {".TXT", ".H", ".HPP", ".C", ".CPP", ".INC"};
private final String IMAGE_EXT[] = {".JPG", ".JPEG", ".PNG", ".GIF"};
private final String WEB_EXT[] = {".HTM", ".HTML", ".XML", ".CSS"};
//字符编码
private final String CHARACTER_CODE = "UTF-8";
//主MIDlet
private MainMIDlet let = null;
//主界面
private Form listForm = null;
//内容列表
private List contentList = null;
//显示文件用窗体
private Form textForm = null;
//装载文本项目用
private TextArea text = null;
//显示图片用的窗体
private Form imageForm = null;
//命令
private Command cmdExit = null;//退出程序
private Command cmdView = null;//浏览目录/文件
private Command cmdDone = null;//退出浏览文件内容
//图标帮助类
private IconHelper helper = null;
//当前目录路径
private String currentDir = null;
public MainPanel(MainMIDlet __let) {
let = __let;
//初始化当前目录为根目录
currentDir = ROOT;
//初始化图标帮助实例
helper = new IconHelper();
listForm = new Form("");
listForm.setLayout(new BorderLayout());
//主显示为List
// contentList = new List();
// contentList.setListCellRenderer(new MyRenderer());
// listForm.addComponent(BorderLayout.CENTER, contentList);
//文本显示窗体
textForm = new Form("");
//文本装载项目
text = new TextArea();
text.setWidestChar('一');
//图像显示窗体
imageForm = new Form("");
//创建命令
cmdExit = new Command("退出");
cmdView = new Command("浏览");
cmdDone = new Command("返回");
//添加命令绑定
listForm.addCommand(cmdExit);
listForm.addCommand(cmdView);
listForm.addCommandListener(this);
//添加文字处理框
textForm.setLayout(new BorderLayout());
textForm.addComponent(BorderLayout.CENTER, text);
//设置文本浏览器窗体的绑定命令
textForm.addCommand(cmdDone);
textForm.addCommandListener(this);
//设置图像浏览窗体的命令绑定
imageForm.addCommand(cmdDone);
imageForm.addCommandListener(this);
//初始化显示
new BrowseThread(currentDir, true).start();
}
class MyContainer extends Container {
private Label name;
public MyContainer(String source) {
name = new Label(source);
name.getStyle().setBgTransparency(0);
addComponent(name);
}
}
class MyRenderer implements ListCellRenderer {
private Label focus;
public MyRenderer() {
focus = new Label();
Border b = Border.createLineBorder(1, 0xff0000);
focus.getStyle().setBorder(b);
}
public Component getListCellRendererComponent(List list, Object value, int index, boolean selected) {
return (MyContainer) value;
}
public Component getListFocusComponent(List list) {
return focus;
}
}
public void actionPerformed(ActionEvent evt) {
Command c = evt.getCommand();
if (c == cmdExit) {
let.exit();
} else if (c == cmdView) {//查看命令
//当前列表中没有目录项
if (contentList.size() == 0) {
//启动线程来浏览指定目录
new BrowseThread(ROOT, true).start();
} else {
final String url = ((MyContainer) contentList.getSelectedItem()).name.getText();
if (url.endsWith(SEPS_STR) == true) {//当前项目为目录,则显示其子项目
//启动浏览线程来浏览指定目录
new BrowseThread(currentDir + url, true).start();
} else if (url.endsWith(UP_DIR) == true) {//当前项目为父目录,则需要回退
backward();
} else {//当前项目为文件
//启动浏览线程来浏览指定文件
new BrowseThread(currentDir + url, false).start();
}
}
} else if (c == cmdDone) {//关闭文本阅读,返回目录浏览
//启动浏览线程来浏览指定文件
new BrowseThread(currentDir, true).start();
}
}
//-------------------------------------------------------------------------
//回退浏览当前目录的父目录内容
private void backward() {
//获取当前目录的父目录名称
int pos = currentDir.lastIndexOf(SEPS_CHAR, currentDir.length() - 2);
if (pos != -1) { //存在上层目录
currentDir = currentDir.substring(0, pos + 1);
} else { //不存在上层目录即根目录
currentDir = ROOT;
}
//启动浏览线程来浏览指定目录
new BrowseThread(currentDir, true).start();
}
class BrowseThread extends Thread {
private String url = null;
private boolean isDirectory = false;
public BrowseThread(final String __url, final boolean __isDirectory) {
url = __url;
isDirectory = __isDirectory;
}
public void run() {
//浏览目录或文件
if (isDirectory) {
text.setText("");
imageForm.removeAll();
showDir(url);
} else {
showFile(url);
}
}
//显示指定目录
public void showDir(final String dir) {
//设置列表title
Enumeration em = null;
FileConnection fc = null;
//设置当前目录
currentDir = dir;
//初始化列表
listForm.removeAll();
contentList = new List();
contentList.setListCellRenderer(new MyRenderer());
listForm.addComponent(BorderLayout.CENTER, contentList);
try {
if (dir.equals(ROOT) == true) {
//枚举根目录列表
em = FileSystemRegistry.listRoots();
} else {//非根目录
fc = (FileConnection) Connector.open(RES_PREFIX + dir);
em = fc.list();
//添加上层根目录
MyContainer up = new MyContainer(UP_DIR);
up.name.setIcon(helper.getIconByExt("/"));
contentList.addItem(up);
}
while (em.hasMoreElements()) {
String fileName = (String) em.nextElement();
if (fileName.endsWith(SEPS_STR)) {//如果为目录
//v.addElement(fileName);
MyContainer c = new MyContainer(fileName);
c.name.setIcon(helper.getIconByExt("/"));
contentList.addItem(c);
System.out.println(fileName);
System.out.println("It's OK!");
} else {//非目录(文件)
MyContainer c = new MyContainer(fileName);
c.name.setIcon(helper.getIconByExt(extractExt(fileName)));
contentList.addItem(c);
}
}
listForm.revalidate();
//初始化选择
contentList.setSelectedIndex(0, true);
//关闭文件连接
if (fc != null) {
fc.close();
}
} catch (Exception ex) {
ex.printStackTrace();
}
listForm.show();
}
//---------------------------------------------------------------------
//显示指定文件内容
private void showFile(final String fileName) {
//Dialog.show(RES_PREFIX, fileName, "ok", "cancel");
String tempFileName = fileName.toUpperCase();
try {
FileConnection fc = (FileConnection) Connector.open(RES_PREFIX + fileName);
if (isEndWithIn(tempFileName, IMAGE_EXT) == true) {//图片文件
//创建流
InputStream is = fc.openInputStream();
Image img = Image.createImage(is);
//设置图片窗体Title
imageForm.setTitle(getRelativeName(fileName));
imageForm.setLayout(new BorderLayout());
imageForm.removeAll();
Button b = new Button(img);
imageForm.addComponent(BorderLayout.CENTER, b);
//关闭流
is.close();
//关闭文件连接
fc.close();
imageForm.show();
} else {//文本文件
int rawFileSize = (int) (fc.fileSize());
int fileSize = ((rawFileSize / BLOCK_SIZE) + 1) * BLOCK_SIZE;
//依据文件内容设置title
textForm.setTitle(getRelativeName(fileName) + ", " + rawFileSize + "/" + fileSize);
DataInputStream dis = fc.openDataInputStream();
byte[] buffer = new byte[rawFileSize];
//读取文件内容
dis.readFully(buffer);
textForm.setLayout(new BorderLayout());
textForm.removeAll();
text.setText(new String(buffer, "UTF-8"));
textForm.addComponent(BorderLayout.CENTER, text);
//关闭流
dis.close();
//关闭文件连接
fc.close();
textForm.show();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
//-------------------------------------------------------------------------
//指定文件名称是否以数组中内容结尾
private boolean isEndWithIn(final String fileName, final String[] extArray) {
for (int i = 0; i < extArray.length; ++i) {
if (fileName.endsWith(extArray[i]) == true) {
return (true);
}
}
return (false);
}
//-------------------------------------------------------------------------
//从完整文件名中提取相对文件名
private String getRelativeName(final String fileName) {
int pos = fileName.lastIndexOf(SEPS_CHAR);
if (pos == -1) {
return ("");
}
return (fileName.substring(pos + 1, fileName.length()));
}
//-------------------------------------------------------------------------
//获取扩展名(不包括'.'符号)
private String extractExt(final String fileName) {
int pos = fileName.lastIndexOf('.');
return (fileName.substring(pos + 1, fileName.length()).toLowerCase());
}
//---------------------------------------------------------------------
}
}
MIDlet启动类:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package main;
import com.sun.lwuit.Display;
import javax.microedition.midlet.*;
/**
* @author Sunny
*/
public class MainMIDlet extends MIDlet {
//主显示面板
private MainPanel panel = null;
public void startApp() {
Display.init(this);
panel = new MainPanel(this);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
public void exit(){
destroyApp(false);
notifyDestroyed();
}
}