java - 将文件放在 linux 服务器上时,ObjectStream header 中的魔数(Magic Number)被更改

标签 java json linux objectinputstream objectoutputstream

希望你一切顺利。 从昨天开始,奇怪的事情发生在我身上。

我有以下用于保存 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),然后我的“前端”部分下载它并尝试读取。

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

java.io.StreamCorruptedException: invalid stream header:

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

ObjectOutputStream 类中有一个 MAGIC_NUMBER,用于 header 。

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

然后,在 ObjectInputStream 类中调用以下方法。

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 天前有效。我记得,我的服务器没有任何变化。

所以,我的主要问题是

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

谢谢。

更新

上传前文件中的前 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 都在尝试进行某种重新编码,可能涉及 UTF-8 或 UTF-16,但我无法确定它正在尝试做什么。

还有一个字节顺序问题,因为它颠倒了 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 字节的二进制值也被替换。

关于java - 将文件放在 linux 服务器上时,ObjectStream header 中的魔数(Magic Number)被更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56034839/

相关文章:

javascript - 如何在javascript中合并具有相同值的json数组

Javascript,未捕获的类型错误 : Cannot read property "cells" of undefined

java循环存储数据库并回调错误

java - Spring Security 3.0.2 x Spring 3.0.1 的错误 - 未创建代理

javascript - 如何解析包含多种数据类型的json数组?

c - 为什么仅在多用户系统中锁定文件是不够的?

regex - 在egrep中查找某组数字

c++ - C++ 中 ubuntu 中的密码屏蔽

java求助新手问题

java - 服务器自动发现节点的算法?