Магическое число ObjectStream в заголовке изменяется при помещении файла на сервер Linux - PullRequest
0 голосов
/ 08 мая 2019

Надеюсь, у тебя все хорошо.Со мной произошла странная вещь со вчерашнего дня.

У меня есть следующий код для сохранения 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;
    }

Я пишу JSON через saveCacheJson и затем помещаю файл на мой Сервер (Linux), а затем моя часть 'front end' загружает его и пытается прочитать.

Со вчерашнего дня я начал получать следующее исключение.

java.io.StreamCorruptedException: invalid stream header:

После некоторых исследований и попыток понять, что происходит, я обнаружил следующее.

В классе ObjectOutputStream есть MAGIC_NUMBER, который используется для заголовка.

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 ???

Спасибо.

ОБНОВЛЕНИЕ

Первые 2 шорта в файле ПЕРЕД ЗАГРУЗКОЙ.

ac ed 00 05 ...

Что верно.

Первые 2 шорта вфайл ПОСЛЕ ЗАГРУЗКИ в linux с Mac:

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

Ответы [ 2 ]

2 голосов
/ 08 мая 2019

Похоже, что все, что вы используете для передачи данных с 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, что неверно, поток данных является двоичным.Значения байтов 0xAC и 0xED недопустимы в UTF-8, поэтому они заменяются символом замены Unicode, закодированным в UTF-8.Другие двоичные значения, которые представляют недопустимые байты UTF-8, также заменяются.

0 голосов
/ 08 мая 2019

ОК, я нашел, что вызывает проблему.Пока не знаю, почему, но нашел решение.

Я использовал mypath/myfile.txt в качестве параметра pathToCache для метода saveCacheJson.Итак, я обнаружил, что проблема из-за расширения .txt.Я вообще удалил расширение и проблема решилась.Кажется, расширение .txt является причиной того, что система Mac не понимает, что файл является двоичным, и пытается закодировать его содержимое во время копирования.Не уверен, почему система вообще пытается изменить содержимое файла во время копирования))

...