对文本文件的存取
要看书得有书才行,不可能把书本认为分段以String的形式体现,那样也太……了,呵呵。随便选了文章用UltraEdit把它存储为unicode编码格式,因为me印象中java是直接支持unicode的。
印象中MIDP中好像有存取资源的函数,既然可以 Image img = Image.createImage(imgpath); Image类中对createImage的声明:public static Image createImage(String name) throws IOException 那想来文本等资源也是可以通过类似的方法存取的。在docs中找了找,果不其然,系统支持对资源的存取,并且自动生成了InputStream,具体声明如下: 类Class中 public InputStream getResourceAsStream(String name) Finds a resource with a given name. This method returns null if no resource with this name is found. The rules for searching resources associated with a given class are profile specific. 如果文件不存在,返回null;如果存在,就打开为InputStream。寻找资源的规则是在profile中有定义的,具体me就管不了那么多了。
既然生成的是InputStream,那可得详细看看java.io包是怎么回事。InputStream是以byte为单位进行读取处理的,这效率可真有点低。DataInputStream可以读取指定的类型,如char、int等,还能对特定的编码解码,如utf,另外readChar读出的字符默认是unicode。java真是个基于unicode的语言,爽。做了个测试用的MIDlet,嘿嘿,不成,读出的都是乱码。问题出在哪里了呢?!再次查看docs,没错,DataInputStream实现了DataInput接口,其中readChar是读取的unicode字符。 在接口DataInput中对readChar的定义: public char readChar() throws IOExceptionReads an input char and returns the char value. A Unicode char is made up of two bytes. Let a be the first byte read and b be the second byte. The value returned is: (char)((a << 8) | (b & 0xff)) This method is suitable for reading bytes written by the writeChar method of interface DataOutput. Returns:the Unicode char read. 不死心,再试,仍然不行!闷……是不是me对接口以及抽象类的掌握还不够?莫不成还要me继承一个DataInputStream手动对readChar进行实现?不管那么多,试试再说,毕竟项目还得继续下去 构造了一个DataInputStream对象,一个个读取byte,然后按照上面的规则手动对连续读取的两个字节进行处理。测试,输出正确的中文字符。怪事,不过不管怎么怪,先放放再说。
???测试继续中,发现了一个问题,以unicode格式存储的文件,前两个byte为FF FE(十六进制),又用UE存了几个文件测试,只要是unicode编码方式存储,头两个字节都是FF FE。不知道是不是unicode编码文本文件的识别文件头?!
手动测试DataInputStream支不支持mark和rewind。一运行就出错,说明j2me中对资源文件存取生成的InputStream不支持mark,当然reset也不支持了。幸亏支持skipBytes,呵呵,要不麻烦真大了。因为必须实现对该文件的向前向后读取,这时候需要移动文件指针。不支持reset、rewind功能带来了一些障碍,me后来通过其他方法实现了这些功能。具体来讲就是定义一个FileLib类,其中实现了类似windows系统中对file文件读取的功能,如读取字节、reset、close,关键在于根据构建器参数(文件名)构造InputStream,在获取文件大小的函数中,先记录当前位置,关闭InputStream,重新打开(此时文件指针在文件头部),遍历到文件尾部(read的结果为负1),关闭,然后再打开,skip到原来的位置。很是麻烦,但功能毕竟实现了。 示例代码如下: /* * FileLib.java * * Created on 2004年10月7日, 下午1:21 */
package heart5.lib;
import java.io.DataInputStream; import java.io.InputStream;
/** * FileLib,对文件进行操作的库;此处文件指资源包中以文件形式存在的资源 * 是否存在,大小 * @author heart5 * @version start */ public class FileLib { /** * InputStream,通过getResource获取输入流 */ InputStream is; /** * DataInputStream,数据输入流,支持readByte等功能 * 实现了DataInput接口 */ DataInputStream dis; /** * 数据输入流的指针 */ public int disIdx = 0; /** * 文件名称,String */ String fileName; /** * 构建器,通过参数文件名生成该类 * @param filename 文件名称,字符串,String */ public FileLib(String filename){ fileName = filename; is = getClass().getResourceAsStream(fileName); dis = new DataInputStream(is); } /** * isOk(),检查文件是否正常 * @return 返回布林值,看文件是否准备好了 */ public boolean isOk(){ boolean ok = false; if(is != null){ ok = true; } return ok; } /** * readChar(),读取一个UNICODE格式字符的值 * @return 返回读取的Unicode字符,整数值 */ public int readChar(){ int ch = -1; try{ byte[] barray = new byte[2]; int pp = dis.read(barray); if((pp != barray.length)||(pp == -1)){ return ch; }else{ ch = (barray[1] << 8)|(barray[0] & 0xff); disIdx += barray.length; } }catch(Exception e){ e.printStackTrace(); } return ch; } /** * readString(),读取指定个数个字符,返回字符串 */ public String readString(int length){ StringBuffer strbuf = new StringBuffer(length); int tmp = readChar(); if(tmp == -1){ return null; } for(int i = 0 ; (i < length)&(tmp != -1) ; i++){ strbuf.append((char)tmp); tmp = readChar(); } return strbuf.toString(); } /** * reachAt(),到达指定的位置,准备读取下一个字节 * @param pos 位置,整数值 */ public void reachAt(int pos){ close(); is = getClass().getResourceAsStream(fileName); dis = new DataInputStream(is); try{ dis.skipBytes(pos); }catch(Exception e){ e.printStackTrace(); } } /** * test(),对InputStream等类的功能进行测试 */ public void test(){ close(); is = getClass().getResourceAsStream(fileName); dis = new DataInputStream(is); int size = 0; try{ if(dis.markSupported()){ System.out.println(fileName+" is mark supported."); } System.out.println("aviable bytes are "+dis.available()); //dis.reset(); }catch(Exception e){ e.printStackTrace(); } close(); is = getClass().getResourceAsStream(fileName); dis = new DataInputStream(is); reachAt(disIdx); } /** * getSize(),通过对文件的遍历得到文件的大小,单位为字节byte。 * 重建一个DataInputStream对象,遍历后关闭。 * @return 文件大小,整数值 */ public int getSize() { close(); is = getClass().getResourceAsStream(fileName); dis = new DataInputStream(is); int size = 0; try{ while(dis.read() != -1){ size++; } close(); is = getClass().getResourceAsStream(fileName); dis = new DataInputStream(is); reachAt(disIdx); }catch(Exception e){ e.printStackTrace(); } return size; } /** * close(),关闭文件 */ public void close(){ try{ if(dis == null){ System.out.println(fileName+" has not benn opened now!"); return ; } dis.close(); }catch(Exception e){ e.printStackTrace(); } } } 
|