如何解析未知编码文件?

时间:2017-11-15 17:37:41

标签: java encoding utf-8

我正在尝试使用vmd(Vocaloid Motion Data 0002)解析扩展名的文件。我不知道它使用什么编码。我曾尝试使用UTF-8,UTF-16,CS_ASCII和Windows-31j(Shift JIS),但它们都没有工作(但根据我所知,大多数UTF-8应解决,因为大多数字节为2字符)。

String testFile = rawFilePath+"/test.vmd";
BufferedWriter bw = null;
FileWriter fw = null;
fw = new FileWriter(outputPath+"/newFile.txt");
bw = new BufferedWriter(fw);
BufferedReader fBr = new BufferedReader(new InputStreamReader(
    new FileInputStream(testFile), "UTF-8"));  //US-ASCII windows-31j
int count=0;
String line;
while ((line = fBr.readLine()) != null) {
    System.out.println(line);
    bw.write(line);
    bw.write("\r\n");
    count++;
    if(count > 3) { //print small portion of a larger file for testing
        break;
    }
    ...
}

print和输出文件都写如下:

???~?N ??????????P ?Z???^?[    ??kkkkkkkk

我想知道这是编码问题还是其他问题?如何从中解析可读数据?

2 个答案:

答案 0 :(得分:1)

Vocaloid Motion数据是二进制数据(如您提供的链接中所述),因此您无法将其转换为文本并希望获得最佳效果。这意味着,您无法使用读者,但必须使用InputStreams。有一个名为DataInputStream的InputStream可以读取整数和浮点数(如果它们在VMD中编码的方式与Java期望的相同)。您可以尝试一下,如果合理的值出现,您就会变黄,否则您必须读取单个字节并使用值计算以自己创建相应的结果(例如,如果数据是最不重要的字节首先排序等等。)

因此,在VMD中读取的代码可能看起来像这样(缺少真实文件,这应该只是被视为插图。有些东西缺失,比如检查我们实际读取数组中的字节数或者是否达到了过早结束流等等。

try (FileInputStream fis = new FileInputStream(new File("rawFilePath", "test.vmd"))) {
    DataInputStream dis = new DataInputStream(fis);
    byte[] nameBytes = new byte[15];
    dis.read(nameBytes);
    int index = 0;
    for (int i = 0; i < nameBytes.length; i++) {
        if (nameBytes[i] == 0) {
            index = i;
            break;
        }
    }
    String name = new String(nameBytes, 0, index, "8859_1");
    // Java ints are signed, so to keep an unsigned int we need long
    long frameNumber = dis.readInt() & 0xffffffff;
    float boneXPosCoordinate = dis.readFloat();
    float boneYPosCoordinate = dis.readFloat();
    float boneZPosCoordinate = dis.readFloat();
    float boneXRotCoordinate = dis.readFloat();
    float boneYRotCoordinate = dis.readFloat();
    float boneZRotCoordinate = dis.readFloat();
    float boneWRotCoordinate = dis.readFloat();
    byte[] interpolationData = new byte[64];
    dis.read(interpolationData);
}

答案 1 :(得分:0)

您可能希望将其检查为byte流。在检查期间,根据编码方式,手动解码前几个字节。有关开始使用UTF编码的一些有用信息,请参阅https://en.wikipedia.org/wiki/Byte_order_mark