Java 从文件中读短片和角色

Java 从文件中读短片和角色,java,file-io,unicode,Java,File Io,Unicode,我有一个二进制文件,它是一个2字节整数和UTF-8字符对的列表。我现在做的是 InputStream stream = ...; InputStreamReader in = new InputStreamReader(stream); while(...){ stream.read(...); in.read(); } 也就是说,我直接从InputStream读取字节,从同一文件流的InputStreamReader读取字符。这对我来说似乎是一个奇怪的(糟糕的?)想法,但我看不

我有一个二进制文件,它是一个2字节整数和UTF-8字符对的列表。我现在做的是

InputStream stream = ...;
InputStreamReader in = new InputStreamReader(stream);

while(...){
   stream.read(...);
   in.read();
}
也就是说,我直接从InputStream读取字节,从同一文件流的InputStreamReader读取字符。这对我来说似乎是一个奇怪的(糟糕的?)想法,但我看不出另一种方式。DataInputStream将只读取UTF-16字符,我不知道自己从字节读取UTF-8字符需要多少字节(我不想重新发明InputStreamReader)。同样的方案也适用于输出

我的问题是,在读取第一对之后,InputStream.read返回-1(当然,文件比这个长)


我想知道是否有更好的替代方案,或者是否可能有其他导致EOF的原因。另外,如果这个方案没有问题,我应该关闭读取器还是InputStream?

您是对的,您不想同时访问InputStreamReader及其底层InputStream。您可能需要编写自己版本的InputStreamReader,但编写起来并不多:

byte[] bytes = new byte[4];

DataInputStream dataStream = new DataInputStream(stream);
while (dataStream.available() > 0) {
    int intValue = dataStream.readUnsignedShort();

    int charValue;
    int b = dataStream.read();
    if (b < 0x80) {
        charValue = b;
    }
    else {
        int byteCount;
        if (b >= 0xf0) {
            byteCount = 4;
        } else if (b >= 0xe0) {
            byteCount = 3;
        } else {
            byteCount = 2;
        }

        bytes[0] = (byte) b;
        dataStream.readFully(bytes, 1, byteCount - 1);
        String s = new String(bytes, 0, byteCount, 
            StandardCharsets.UTF_8);
        charValue = s.codePointAt(0);
    }

    // Do something with intValue and charValue
}
byte[]bytes=新字节[4];
DataInputStream数据流=新的DataInputStream(流);
while(dataStream.available()>0){
int intValue=dataStream.readUnsignedShort();
int值;
int b=dataStream.read();
如果(b<0x80){
charValue=b;
}
否则{
int字节数;
如果(b>=0xf0){
字节数=4;
}否则如果(b>=0xe0){
字节数=3;
}否则{
字节数=2;
}
字节[0]=(字节)b;
dataStream.readFully(字节,1,字节计数-1);
字符串s=新字符串(字节、0、字节数、,
标准字符集(UTF_8);
charValue=s.codePointAt(0);
}
//用intValue和charValue做一些事情
}

您不想同时访问InputStreamReader及其底层InputStream,这是对的。您可能需要编写自己版本的InputStreamReader,但编写起来并不多:

byte[] bytes = new byte[4];

DataInputStream dataStream = new DataInputStream(stream);
while (dataStream.available() > 0) {
    int intValue = dataStream.readUnsignedShort();

    int charValue;
    int b = dataStream.read();
    if (b < 0x80) {
        charValue = b;
    }
    else {
        int byteCount;
        if (b >= 0xf0) {
            byteCount = 4;
        } else if (b >= 0xe0) {
            byteCount = 3;
        } else {
            byteCount = 2;
        }

        bytes[0] = (byte) b;
        dataStream.readFully(bytes, 1, byteCount - 1);
        String s = new String(bytes, 0, byteCount, 
            StandardCharsets.UTF_8);
        charValue = s.codePointAt(0);
    }

    // Do something with intValue and charValue
}
byte[]bytes=新字节[4];
DataInputStream数据流=新的DataInputStream(流);
while(dataStream.available()>0){
int intValue=dataStream.readUnsignedShort();
int值;
int b=dataStream.read();
如果(b<0x80){
charValue=b;
}
否则{
int字节数;
如果(b>=0xf0){
字节数=4;
}否则如果(b>=0xe0){
字节数=3;
}否则{
字节数=2;
}
字节[0]=(字节)b;
dataStream.readFully(字节,1,字节计数-1);
字符串s=新字符串(字节、0、字节数、,
标准字符集(UTF_8);
charValue=s.codePointAt(0);
}
//用intValue和charValue做一些事情
}

谢谢。您的意思可能是
readUnsignedByte()
,因为在
DataInputStream
中似乎没有类似的
read
。方法是文档化的。
readUnsignedShort
方法。DataInputStream从InputStream继承read()方法。据我所知,read()和readUnsignedByte()之间的唯一区别在于readUnsignedByte()不能返回-1,因此您正确地认为readUnsignedByte()是一个更好的选择。谢谢。您的意思可能是
readUnsignedByte()
,因为在
DataInputStream
中似乎没有类似的
read
。方法是文档化的。
readUnsignedShort
方法。DataInputStream从InputStream继承read()方法。据我所知,read()和readUnsignedByte()之间的唯一区别是readUnsignedByte()不能返回-1,因此您认为readUnsignedByte()是一个更好的选择是正确的。