RandomAccessFile readUTF与我自己写的方法对比,官方为什么那么复杂?

本文深入探讨了Java中使用RandomAccessFile读取UTF-8编码字符串的方法及源码解析,详细解释了如何处理不同编码情况下的字节转换,并针对可能出现的异常情况进行了说明。
我写的

RandomAccessFile raf=。。。
int len=raf.readShort()&0xffff;
byte[] name=new byte[len];
raf.read(name);
return new String(name,"utf-8");


readUTF源码

int utflen = in.readUnsignedShort();
byte[] bytearr = null;
char[] chararr = null;
if (in instanceof DataInputStream) {
DataInputStream dis = (DataInputStream)in;
if (dis.bytearr.length < utflen){
dis.bytearr = new byte[utflen*2];
dis.chararr = new char[utflen*2];
}
chararr = dis.chararr;
bytearr = dis.bytearr;
} else {
bytearr = new byte[utflen];
chararr = new char[utflen];
}

int c, char2, char3;
int count = 0;
int chararr_count=0;

in.readFully(bytearr, 0, utflen);

while (count < utflen) {
c = (int) bytearr[count] & 0xff;
if (c > 127) break;
count++;
chararr[chararr_count++]=(char)c;
}

while (count < utflen) {
c = (int) bytearr[count] & 0xff;
switch (c >> 4) {
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
/* 0xxxxxxx*/
count++;
chararr[chararr_count++]=(char)c;
break;
case 12: case 13:
/* 110x xxxx 10xx xxxx*/
count += 2;
if (count > utflen)
throw new UTFDataFormatException(
"malformed input: partial character at end");
char2 = (int) bytearr[count-1];
if ((char2 & 0xC0) != 0x80)
throw new UTFDataFormatException(
"malformed input around byte " + count);
chararr[chararr_count++]=(char)(((c & 0x1F) << 6) |
(char2 & 0x3F));
break;
case 14:
/* 1110 xxxx 10xx xxxx 10xx xxxx */
count += 3;
if (count > utflen)
throw new UTFDataFormatException(
"malformed input: partial character at end");
char2 = (int) bytearr[count-2];
char3 = (int) bytearr[count-1];
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
throw new UTFDataFormatException(
"malformed input around byte " + (count-1));
chararr[chararr_count++]=(char)(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
default:
/* 10xx xxxx, 1111 xxxx */
throw new UTFDataFormatException(
"malformed input around byte " + count);
}
}
// The number of chars produced may be less than utflen
return new String(chararr, 0, chararr_count);


为什么官方要这么复杂?
`InputStream` 的 `skip` 方法和 `RandomAccessFile` 的 `skipBytes` 方法在性能上存在一定差异,具体分析如下: ### 底层实现工作原理 - **`InputStream` 的 `skip` 方法**:`InputStream` 是字节输入流的抽象基类,其 `skip` 方法的实现通常是通过不断读取并丢弃字节来跳过指定数量的数据。这意味着在跳过数据时,它实际上会进行多次读取操作,直到跳过指定的字节数。例如,在 `FileInputStream` 中,`skip` 方法可能会调用底层的系统调用进行多次读取,以达到跳过的目的。 ```java import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; public class InputStreamSkipExample { public static void main(String[] args) { try (InputStream is = new FileInputStream("test.txt")) { long skipped = is.skip(10); System.out.println("Skipped " + skipped + " bytes."); } catch (IOException e) { e.printStackTrace(); } } } ``` - **`RandomAccessFile` 的 `skipBytes` 方法**:`RandomAccessFile` 支持随机访问文件,它的 `skipBytes` 方法是通过直接移动文件指针来跳过指定数量的字节。文件指针直接定位到要跳过的字节位置之后,不需要像 `InputStream` 那样进行多次读取操作。 ```java import java.io.IOException; import java.io.RandomAccessFile; public class RandomAccessFileSkipExample { public static void main(String[] args) { try (RandomAccessFile raf = new RandomAccessFile("test.txt", "r")) { int skipped = raf.skipBytes(10); System.out.println("Skipped " + skipped + " bytes."); } catch (IOException e) { e.printStackTrace(); } } } ``` ### 性能差异 - **小数据量跳过**:在跳过小数据量时,两者的性能差异可能不太明显。因为 `InputStream` 的多次读取操作开销相对较小,而 `RandomAccessFile` 的文件指针移动操作也比较快。 - **大数据量跳过**:当需要跳过大数据量时,`RandomAccessFile` 的 `skipBytes` 方法通常会比 `InputStream` 的 `skip` 方法快得多。因为 `InputStream` 需要进行大量的读取和丢弃操作,会消耗更多的时间和系统资源,而 `RandomAccessFile` 只需要简单地移动文件指针即可。 ### 不同文件系统和硬件环境的影响 - **文件系统**:某些文件系统可能对随机访问操作有更好的支持,这会使 `RandomAccessFile` 的性能优势更加明显。例如,一些现代的文件系统会对文件指针的移动进行优化,以提高随机访问的效率。 - **硬件环境**:如果硬件支持随机访问,如固态硬盘(SSD),`RandomAccessFile` 的性能会更有优势。因为 SSD 的随机访问速度比传统的机械硬盘快很多,能够更好地配合 `RandomAccessFile` 的文件指针移动操作。 ### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值