StringBuilders заканчивающиеся символами массы ноль - PullRequest
2 голосов
/ 22 марта 2011

Мне очень трудно отладить проблему с приложением, которое я создавал. Сама проблема, которую я не могу воспроизвести с помощью программы репрезентативного тестирования с той же проблемой, которую трудно продемонстрировать. К сожалению, я не могу поделиться своим фактическим источником из-за безопасности, однако следующий тест довольно хорошо отражает то, что я делаю, тот факт, что файлы и данные имеют формат EOL в стиле Unix, запись в zip-файл с помощью PrintWriter и использование StringBuilders :

public class Tester {

    public static void main(String[] args) {
        // variables
        File target = new File("TESTSAVE.zip");
        PrintWriter printout1;
        ZipOutputStream zipStream;
        ZipEntry ent1;
        StringBuilder testtext1 = new StringBuilder();
        StringBuilder replacetext = new StringBuilder();
        // ensure file replace
        if (target.exists()) {
            target.delete();
        }
        try {
            // open the streams
            zipStream = new ZipOutputStream(new FileOutputStream(target, true));
            printout1 = new PrintWriter(zipStream);
            ent1 = new ZipEntry("testfile.txt");
            zipStream.putNextEntry(ent1);

            // construct the data
            for (int i = 0; i < 30; i++) {
            testtext1.append("Testing 1 2 3 Many! \n");
            }
            replacetext.append("Testing 4 5 6 LOTS! \n");
            replacetext.append("Testing 4 5 6 LOTS! \n");

            // the replace operation
            testtext1.replace(21, 42, replacetext.toString());

            // write it
            printout1 = new PrintWriter(zipStream);
            printout1.println(testtext1);
            // save it
            printout1.flush();
            zipStream.closeEntry();
            printout1.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Суть проблемы в том, что файл, который я вижу на моей стороне, создает файл длиной 16,3 тыс. Символов. Мой друг, независимо от того, использует ли он приложение на своем компьютере или он просматривает тот же файл, что и я, видит файл с 19,999 тыс. Символов, дополнительные символы - CRLF, за которым следует огромное количество нулевых символов. Независимо от того, какое приложение, кодировку или представления я использую, я вообще не могу видеть эти нулевые символы, я вижу только один LF в последней строке, но я вижу файл размером 20 КБ. Во всех случаях существует разница между тем, что видно с одинаковыми файлами на двух компьютерах, даже если оба являются компьютерами Windows, и оба используют одни и те же программы для редактирования.

Я еще не смог воспроизвести это поведение с любым количеством фиктивных программ. Тем не менее, я смог проследить отклонение CRLF в последней строке до моего использования println на PrintWriter. Когда я заменил println(s) на print(s + '\n'), проблема, казалось, исчезла (размер файла 16,3 КБ). Однако, когда я вернул программу в println (s), проблема, похоже, не возвращается. В настоящее время я проверяю файлы, полученные от друга во Франции, чтобы выяснить, действительно ли проблема исчезла (поскольку я не вижу nuls, но он может), но это поведение было полностью запутано.

Я также заметил, что функция замены StringBuilder сообщает: «Эта последовательность будет удлинена, чтобы приспособить указанную строку при необходимости». Принимая во внимание тот факт, что функция setLength для строителей строк дополняется нулевыми символами и что функция sureCapacity устанавливает емкость на большее из входного значения или (currentCapacity*2)+2, я подозревал где-то отношение. Тем не менее, я только один раз, когда тестировал с этой идеей, смог получить результат, который представлял то, что я видел, и не смог воспроизвести его с тех пор.

Кто-нибудь знает, что может быть причиной этой ошибки, или, по крайней мере, есть предложение о том, в каком направлении следует проводить тестирование?

Изменить, так как раздел комментариев для меня не работает: Просто чтобы прояснить, вывод должен быть в формате Unix независимо от ОС, следовательно, использование '\ n' напрямую, а не через форматтер. Оригинальный StringBuilder, который вставлен в, на самом деле не сгенерирован для меня, а представляет собой содержимое файла, считываемого программой. Я рад, что процесс чтения работает, так как информация в нем интенсивно используется во всем приложении. Я также провел небольшое исследование и обнаружил, что непосредственно перед сохранением буфер является правильной емкостью, а вывод при вызове toString () имеет правильную длину (то есть он не содержит нулевых символов и имеет длину 16 363, а не 19 999). ). Это приведет к возникновению ошибки где-то между генерацией строки и сохранением zip-файла.

1 Ответ

2 голосов
/ 24 марта 2011

Наконец-то нашли причину.Удалось воспроизвести проблему несколько раз и отследить причину не на стороне вывода кода, а на стороне ввода.Моя функция чтения файлов была по существу такой:

char[] buf;
int charcount = 0;
StringBuilder line = new StringBuilder(2048);
InputStreamReader reader = new InputStreamReader(stream);// provides a line-wise read
BufferedReader file = new BufferedReader(reader);
do { // capture loop
    try {
    buf = new char[2048];
    charcount = file.read(buf, 0, 2048);
    } catch (IOException e) {
    return null; // unknown IO error
    }
    line.append(buf);
} while (charcount != -1);
// close and output

проблема была при добавлении буфера, который не был заполнен, поэтому более поздние значения были все еще в их начальных значениях нуля.Причина, по которой я не смог воспроизвести это, заключалась в том, что некоторые данные хорошо заполняли буферы, а некоторые - нет.

Почему я не могу увидеть проблему в моих текстовых редакторах, о которых я до сих пор не знаю, но я должен быть в состоянии решить эту проблему сейчас.Любые предложения о том, как это сделать, приветствуются, так как это часть одной из моих долгосрочных служебных библиотек, и я хочу сделать ее как можно более универсальной и оптимизированной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...