header 中的 ObjectStream 幻数在将文件放在 linux 服务器上时发生了变化

ObjectStream's magic number in the header is changed while putting file on a linux server

希望你一切顺利。 从昨天开始就发生了奇怪的事情。

我有以下用于保存 JSON 的代码。

 public static boolean saveCacheJson(String pathToCache, JSONObject json) {
        boolean isSaveSuccess = false;
        ObjectOutputStream outputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            File file = new File(pathToCache);
            if (!file.exists()) {
                file.getParentFile().mkdirs();
                new FileWriter(file);
            } else {
                file.delete();
            }
            fileOutputStream = new FileOutputStream(pathToCache);
            outputStream = new ObjectOutputStream(fileOutputStream);
            outputStream.writeObject(json.toString());
            isSaveSuccess = true;
        } catch (IOException e) {
            IsoGame.$().crossPlatformManager.getCrossPlatformUtilsInstance().sendLog(e);

            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (Exception e1) {
                IsoGame.$().crossPlatformManager.getCrossPlatformUtilsInstance().sendLog(e1);
                e1.printStackTrace();
            }
            try {
                fileOutputStream.close();
            } catch (Exception e1) {
                IsoGame.$().crossPlatformManager.getCrossPlatformUtilsInstance().sendLog(e1);
                e1.printStackTrace();
            }
        }
        return isSaveSuccess;
    }

和下面的阅读代码。

public static JSONObject getCacheJson(String pathToCache, boolean throwException) throws Exception {
        JSONObject result = null;
        String resultString;
        ObjectInputStream inputStream = null;
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(pathToCache);
            inputStream = new ObjectInputStream(fileInputStream);
            resultString = (String) inputStream.readObject();
            result = new JSONObject(resultString);
        } catch (ClassNotFoundException | IOException | JSONException e) {
            e.printStackTrace();
            if (throwException && e instanceof FileNotFoundException) {
                throw e;
            }
        } finally {
            try {
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }

        return result;
    }

我正在通过 saveCacheJson 编写 JSON 然后将文件放到我的服务器 (Linux) 然后我的 'front end' 部分下载它并尝试读。

从昨天开始,我开始收到以下异常。

java.io.StreamCorruptedException: invalid stream header:

经过一些研究并试图了解发生了什么,我发现了以下内容。

ObjectOutputStreamclass中有一个MAGIC_NUMBER,用于header。

protected void writeStreamHeader() throws IOException {
        this.bout.writeShort(-21267);
        this.bout.writeShort(5);
    }

然后,在ObjectInputStreamclass下面的方法被调用。

protected void readStreamHeader() throws IOException, StreamCorruptedException {
        short var1 = this.bin.readShort();
        short var2 = this.bin.readShort();
        if (var1 != -21267 || var2 != 5) {
            throw new StreamCorruptedException(String.format("invalid stream header: %04X%04X", var1, var2));
        }
    }

并且这里抛出了异常。

所以,我打开了我在本地机器上写的文件 (Mac OS),发现前 2 个字节如下

¨Ì

然后我在终端中尝试了以下操作。

hexdump myfile

发现前2个字节是对的。 在这里。

ac ed ... 

所以,我尝试对下载的文件(从 Linux 服务器,我之前放在那里)做同样的事情,发现前 2 个字节是错误的。 于是,我查看了流程,发现在将文件复制到服务器的过程中,它们发生了变化。

总的来说这很奇怪,但最奇怪的是它在大约 10 天前有效。我记得,我的服务器没有任何变化。

所以,我的主要问题是

关于为什么流 HEADER 在上传到 LINUX 服务器期间发生变化的任何想法???

谢谢。

更新

上传前文件中的前 2 条短裤是。

ac ed 00 05 ...

哪个是对的。

从 Mac 上传到 linux 后文件中的前 2 条短裤是。

bfef efbd ...

这是错误的。

更新 2.

正确文件的结果。

0000000 ac ed 00 05 7c 00 00 00 00 00 0f 26 fe 7b 22 64
0000010 65 22 3a 7b 22 6e 70 63 22 3a 5b 7b 22 63 6f 64
0000020 65 22 3a 22 64 65 22 2c 22 6e 70 63 5f 69 64 22
0000030 3a 32 2c 22 6c 61 6e 67 5f 69 64 22 3a 36 2c 22
0000040 69 64 22 3a 31 32 2c 22 6c 61 6e 67 75 61 67 65
0000050 5f 69 64 22 3a 36 2c 22 64 69 61 6c 6f 67 73 22
0000060 3a 5b 22 53 63 68 61 75 20 6d 61 6c 2c 20 64 61
0000070 73 20 69 73 74 20 49 72 69 73 2c 20 64 65 72 20
0000080 42 6f 74 65 20 64 65 72 20 47 c3 b6 74 74 65 72
0000090 2e 20 53 69 65 20 68 61 74 20 75 6e 73 20 6d 61
..........

来自错误的文件。

0000000 ef bf bd ef bf bd 00 05 7c 00 00 00 00 00 0f 26
0000010 ef bf bd 7b 22 64 65 22 3a 7b 22 6e 70 63 22 3a
0000020 5b 7b 22 63 6f 64 65 22 3a 22 64 65 22 2c 22 6e
0000030 70 63 5f 69 64 22 3a 32 2c 22 6c 61 6e 67 5f 69
0000040 64 22 3a 36 2c 22 69 64 22 3a 31 32 2c 22 6c 61
0000050 6e 67 75 61 67 65 5f 69 64 22 3a 36 2c 22 64 69
0000060 61 6c 6f 67 73 22 3a 5b 22 53 63 68 61 75 20 6d
0000070 61 6c 2c 20 64 61 73 20 69 73 74 20 49 72 69 73
0000080 2c 20 64 65 72 20 42 6f 74 65 20 64 65 72 20 47
0000090 c3 b6 74 74 65 72 2e 20 53 69 65 20 68 61 74 20

看起来你用来将数据从 Mac 传输到 Linux 的任何东西都在尝试做某种 re-encoding,可能涉及 UTF-8 或 UTF-16,但我无法确定它到底想做什么。

还有一个 byte-order 问题,因为它颠倒了 16 位字中的字节顺序。请注意正确十六进制的第一行序列 0x0f26。乱码文件中序列为0x260f.

我建议您仔细检查用于将文件从 Mac 传输到 Linux 的过程,并尝试找到任何控制文件编码和字节顺序的选项。

更新

我明白了。首先,转换器确定某些字符无效并将其替换为 Unicode 代码点 0xfffd 或替换字符。然后,它将生成的流编码为 UTF-8。 0xfffd在UTF-8中的编码是0xefbfbd.

AC ED --(replace)-> FFFD FFFD --(utf8 encode)-> EF BF BD EF BF BD

处理传输的任何进程都假设输入是 UTF-8,这是不正确的,数据流是二进制的。字节值 0xAC0xED 在 UTF-8 中无效,因此它们被替换为以 UTF-8 编码的 Unicode 替换字符。其他碰巧代表无效 UTF-8 字节的二进制值也被替换。

好的,我找到了导致问题的原因。还不知道为什么,但找到了解决方法。

我使用 mypath/myfile.txt 作为 pathToCache 方法的 pathToCache 参数。所以,我发现问题出在 .txt 扩展名上。 我完全删除了一个扩展,问题就解决了。 .txt 扩展名似乎是原因,Mac 的系统不理解该文件是二进制文件并试图在复制过程中对其内容进行编码。 不确定为什么系统会在复制过程中尝试更改文件的内容))