Моя проблема в том, что мне было назначено модифицировать и улучшать программу, которая выполняет сжатие LZW. Моя программа, насколько мне известно, работает нормально, но полагается на перенаправление System.in и System.out для входного файла и выходного файла. Для моей тестовой программы я запускаю папку с файлами и для каждого файла, запускаю 4 разных теста в программе. Для эмуляции ввода командной строки/перенаправление вывода, на первой итерации цикла для каждого файла я делаю следующее:Сброс FileInputStream в Java, поэтому я могу запускать несколько экземпляров другой программы в тестовой программе
FileOutputStream fos = new FileOutputStream(compressOut); // compressOut is compressed file
PrintStream ps = new PrintStream(fos);
System.setOut(ps);
FileInputStream fis = new FileInputStream(file); // file is file to be compressed
System.setIn(fis);
fis.mark(0);// mark not supported so this is actually left over from my test code -- wanted to show I tried to do this
В первый раз он запускает программу я тестирование, это работает блестяще и возвращает сжатия и готовится записать его в выходной файл программы.
Однако, после второго вызова программы (и, если бы я должен был устранить все дополнительные вызовы, вторую итерацию цикла for), он сработает и возвращает, что входной поток пуст. Я еще не получил возможность увидеть, будет ли поток вывода делать то же самое, но то, что я попытался сделать для сброса потока, выглядит следующим образом:
Перед каждым вызовом программы вызова у меня есть следующие блоки кода, который я ** думал бы исправить эту проблему, но безрезультатно:
//System.setIn(null); // Tried - didn't work
//System.setOut(null); // Tried - didn't work
fos.close();
ps.close();
fis.close();
fos = new FileOutputStream(compressOut);
ps = new PrintStream(fos);
System.setOut(ps);
fis = new FileInputStream(file);
System.setIn(fis);
//fis.reset(); // Tried - didn't work
я пробовал все виды комбинаций различных способов сброса потока ввода, но каждое решение по-прежнему возвращает тот же результат, сообщение об ошибке, указывающее, что оно считывается из пустого потока ввода - ошибка, которая означает, что поток находится в конце файла (или в файле ничего нет).
Единственная другая ошибка, которую я могу получить, заключается в том, что mark() не поддерживается, когда я вызываю сброс, если я пытаюсь отметить (0); и reset(); методы.
Я сделал чтение и не могу найти твердых ответов относительно того, как заставить это работать. Программа превращает StdIn
в BufferedInputStream
и StdOut
в BufferedOutputStream
, поэтому мне нужен способ, который будет совместим и обеспечит производительность, аналогичную перенаправлению StdIn/StdOut.
TL; DR: Мне нужно сбросить мой FileInputStream
и не может сделать это с помощью метки() сброс(), ни, если я переинициализировать FileInputStream
Update: попытался обертывание ФИС в BufferedInputStream
как предложенный на аналогичной должности, где поддерживается знак(). Однако методы mark()
и reset()
хороши только для размера BufferedInputStream
(который я считаю 4096 байтов), что в значительной степени исключает потенциальную полезность функции отметки/сброса во всех моих файлах. Они все больше 4kB :(
Update 2: я решил опубликовать полный фрагмент кода, с которого я начинаю по-цикл в котором происходит пустая ошибка потока, в случае, если кто может увидеть что-то я . не могу это код в вопросе:.
public static void main(String[] args) throws IOException, InterruptedException {
File programOutputPath = new File("-- the compression file path --");
File folderPath = new File("-- the relative folder path --");
File compressOut = new File(folderPath + "compressed.lzw");
File[] allFiles = folderPath.listFiles(); // get an array of all files
FileWriter fw = new FileWriter(programOutputPath);
for(File file : allFiles) {
FileOutputStream fos = new FileOutputStream(compressOut);
PrintStream ps = new PrintStream(fos);
System.setOut(ps);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
System.setIn(bis);
String[] cArgs = new String[2];
cArgs[0] = "-"; cArgs[1] = "-n";
String[] dArgs = new String[1];
dArgs[0] = "+";
String[] LZWArgs = new String[1];
LZWArgs[0] = "-";
System.err.println("File: " + file.toString());
if(!file.canWrite()) {
System.err.println("SKIPPED FILE");
}
if(file.getName().equalsIgnoreCase(".gitignore") || file.getName().equalsIgnoreCase("compressed.lzw")) continue;
MyLZW.main(cArgs); // runs fine
if(decompress) {
//MyLZW.main(dArgs); // not executing this
}
long sizeUnc = file.length();
long sizeC = compressOut.length();
double ratio = (double)sizeUnc/(double)sizeC; // compression ratio is correct
System.err.println("java MyLZW - -r <" + file.getName() + "> " + " compressed.lzw compression ratio:" + ratio); // works fine
fw.write("java MyLZW - -n <" + file.getName() + "> " + " compressed.lzw compression ratio:" + ratio + "\n");
cArgs[1] = "-r";
bis.close(); // close BufferedInputStream
bis = new BufferedInputStream(new FileInputStream(file)); // reinitialize BIS
System.setIn(bis); // setIn to newly initialized BufferedInputStream
MyLZW.main(cArgs); // crashes here b/c empty input stream
«Моя программа ... полагается на System.in и System.out ...» Измените ее, чтобы полагаться на InputStream и OutputStream. Это будет значительно более гибким, и вы сможете передавать новые потоки каждому вызову. – VGR
@VGR Спасибо за предложение, и если все остальное не получится, я попробую это, но я бы предпочел, чтобы не пришлось изменять зависимости, в которых работает программа, поскольку мне давали зависимости как есть, и сказали, чтобы они не редактировали их. Единственный файл, который я должен коснуться, - это исходный файл, который управляет сжатием. Это стало скорее любопытством выяснить, как заставить мою программу работать таким образом, а не абсолютную необходимость заставить ее работать таким образом. В двух словах, я пытаюсь выяснить, в первую очередь, как динамически изменять StdOut и StdIn, как требуется для будущих работ. Большое спасибо за предложение :) – dddJewelsbbb
Если вы хотите перезапустить FileInputStream, просто создайте новый (или переключитесь на RandomAccessFile). Потоки по дизайну предназначены для чтения только один раз - система маркировки/сброса - это всего лишь костыль для ситуации, когда альтернатив нет или вам просто нужно перемотать несколько байтов. – Robert