使用Java 随机读写文件RandomAccessFile类和String类遇到的问题

来源:互联网 发布:2004nba总决赛数据 编辑:程序博客网 时间:2024/05/16 11:13
2016/1/19 21:35:23

1. String类:
    以前可能没有注意到String类的一些编码的细节,这里简单说明一下
    注意,常见的几个构造函数:

构造方法摘要String() 
          初始化一个新创建的 String 对象,使其表示一个空字符序列。String(byte[] bytes) 
          通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 StringString(byte[] bytes, Charset charset) 
          通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String


使用字节数组的时候,需要指定解码的方式,若是不指定的话,使用平台默认的字符集,这里在不同的平台可能产生不同的结果。最终,生成的String的字符类型,都是Unicode的;类型,当然不同的平台的实现方式可能是不一样的,但是这些细节对我们用户来说是透明的、屏蔽的!!


2. RandomAccessFile类:
    这个类是比较独立的一个类,不能使用装饰器,进行读写的时候绑定编码。
这个类的主要官方说明:


此类的实例支持对随机访问文件的读取和写入。随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。

通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出 EOFException(是一种 IOException)。如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出 IOException,而不是 EOFException。需要特别指出的是,如果流已被关闭,则可能抛出 IOException





几个重要的函数:

 longgetFilePointer() 
          返回此文件中的当前偏移量。 longlength() 
          返回此文件的长度。注意:这里的长度是文件的原始字节码长度 intread() 
          从此文件中读取一个数据字节。 intread(byte[] b) 
          将最多 b.length 个数据字节从此文件读入 byte 数组。
来源: http://192.168.0.107:8086/java_api/java/io/RandomAccessFile.html#read()
 StringreadLine() 
          从此文件读取文本的下一行。
 voidseek(long pos) 
          设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作。
这里需要说明一下:
    

readLine

public final String readLine()                      throws IOException
从此文件读取文本的下一行。此方法可以从该文件的当前文件指针处成功地读取字节,直到到达行结束符或文件的末尾。每个字节都转换为一个字符,方法是采用该字符的低八位字节值,并将该字符的高八位设置为零。因此,此方法不支持完整的 Unicode 字符集。

文本行由回车符 ('\r') 和一个换行符 ('\n') 结束,回车符后面紧跟一个换行符,或者是文件的末尾。不使用行结束符,并且在返回的字符串中不包括结束符。

在读取了一个换行符、读取了一个回车符和它后面的字节(查看是否为一个新行),到达文件的末尾或者抛出异常之前,此方法一直阻塞。

指定者:
接口 DataInput 中的 readLine
返回:
此文件文本的下一行,如果连一个字节也没有读取就已到达文件的末尾,则返回 null。
抛出:
IOException - 如果发生 I/O 错误。

readLine的读取的是一个字符串,但是,这个字符串的生成方式如上所示,实际上就是对文件的原始字节码进行了“ISO-8856-1”的解码(这里有点费解),因此,若想不出现乱码,读取的方式应该是这样的:
String line = new String(readLine.getBytes("ISO-8859-1"), 文件编码方式);
这里,首先是使用"ISO-8859-1"编码byte 序列,这样就恢复成了原始文件的字节流,这些字节流是使用原始文件的编码方式,所以,要使用原始文件的编码方式进行解码成Unicode字符串!!

 byte[]getBytes() 
          使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。 byte[]getBytes(Charset charset) 
          使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组。 voidgetBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) 
          已过时。 该方法无法将字符正确转换为字节。从 JDK 1.1 起,完成该转换的首选方法是通过 getBytes() 方法,该方法使用平台的默认字符集。 byte[]getBytes(String charsetName) 
          使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
    
3. LineNumberReader类:
    注意,这个类纯属是一个坑,因为

跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。

默认情况下,行编号从 0 开始。该行号随数据读取在每个行结束符处递增,并且可以通过调用 setLineNumber(int) 更改行号。但要注意的是,setLineNumber(int) 不会实际更改流中的当前位置;它只更改将由getLineNumber() 返回的值。

可认为行在遇到以下符号之一时结束:换行符('\n')、回车符('\r')、回车后紧跟换行符。


4. Byte
    java中的byte字节跟C++/C中的char类似,是一个8位的二进制,而对应英文的字符,可以转化为这个对应的byte或者整数,这样,可以惊醒ASCII字符与byte的比较(整数值),使用“==”
1 0