《读艺》开发志(三)

类别:Java 点击:0 评论:0 推荐:


 对文本文件的存取


 要看书得有书才行,不可能把书本认为分段以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();
        }
    }
   
}

本文地址:http://com.8s8s.com/it/it14344.htm