Почему валидатор не пропускает вот такое решение?
public void createZip(Path source) throws Exception{
ZipOutputStream zos = null;
InputStream in = null;
try {
zos = new ZipOutputStream(Files.newOutputStream(zipFile));
String[] arr = String.valueOf(source).split("/");
String file = arr[arr.length - 1];
ZipEntry ze = new ZipEntry(file);
zos.putNextEntry(ze);
in = Files.newInputStream(source);
byte[] bytes = new byte[1000];
while (in.available() > 0) {
in.read(bytes);
zos.write(bytes);
}
}finally {
in.close();
zos.close();
}
}
А вот такое пропускает
public void createZip(Path source) throws Exception{
ZipOutputStream zos = null;
InputStream in = null;
try {
zos = new ZipOutputStream(Files.newOutputStream(zipFile));
String[] arr = String.valueOf(source).split("/");
String file = arr[arr.length - 1];
ZipEntry ze = new ZipEntry(file);
zos.putNextEntry(ze);
in = Files.newInputStream(source);
while (in.available() > 0) {
int b = in.read();
zos.write(b);
}
}finally {
in.close();
zos.close();
}
}
Если я ничего не путаю, то в предыдущих лекциях говорилось, что предпочтительнее использовать массив байт, чем читать и писать по одному байту. Что я упустил?
Александр Колосов
36 уровень
Вопрос к администрации
Обсуждается
Комментарии (5)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Дмитрий К.
23 марта 2019, 08:41
в 1 варианте while не нужен, операции чтения в байтовый массив будет совершенна единожды, можно сделать проверку только чтобы файл был не пуст
0
Александр Колосов
23 марта 2019, 09:32
Ну, если есть 100%-я уверенность в том, что одного массива хватит, то можно обойтись и if - ом. Хотя, если думать наперед, то можно предположить, что попадутся файлы, данные которых не уместятся в массив и тогда мы получим не полный вывод. Так что я бы не торопился отказываться от whail.
Для чего писать (in.available > -1) ? Для того, чтобы сжимать еще и пустые файлы?
Я нашел предыдущую лекцию по этой теме, там сказано, что при записи нужно указывать еще и индекс байта в массиве, до которого следует писать.
То есть, код должен выглядеть вот так:
byte[] bytes = new byte[1000];
while (in.available() > 0) {
int count = in.read(bytes);
zos.write(bytes, 0, count);
}
Вот ссылка на лекцию:
https://javarush.com/quests/lectures/questcore.level08.lecture04
0
Дмитрий К.
23 марта 2019, 10:01
да с -1 опечатлся я =) там 0.
Да у меня немного не правильно, это действительно для маленьких файлов когда создаешь массив так
Немного допилим твой код =)
0
Александр Колосов
23 марта 2019, 14:10
А зачем start высчитывать? Если старт будет больше 0, то чтение массива будет начинаться не с 0 байта, то есть не с начала. А в твоем решении и вовсе, начальная позиция будет за пределами массива. Соответственно будет ошибка: IndexOutOfBoundsException, так как стартовый индекс + длина будут больше, чем длина массива.
(file:///D:/Java/J11SE/jdk-11_doc-all/docs/api/java.base/java/io/OutputStream.html#write(byte%5B%5D,int,int)
Зачем flush()? Ведь по условию наш цикл помещен в блок try-with-resources. И в части finally мы вызываем метод close(). А в этом случае метод flush() вызывается по умолчанию. В лекции по ссылке об этом говорится.
(https://javarush.com/quests/lectures/questcore.level08.lecture04).
Таким образом мы возвращаемся к моему коду. Но, если очень хочется его допилить, то лучше это сделать вот так:
byte[] bytes = new byte[1000]; (размер можно поменять)
int count;
while ((count = in.read(bytes) > 0) {
in.write(bytes, 0, count);
}
0
Дмитрий К.
25 марта 2019, 11:08
подзабыл уже все, пришлось лезть в джавадок )
про flush() согласен в данном случае он не нужен, его надо применять например при синхронной передачи данных на удаленный хост, т.к. он даст команду потоку вывода не ждать заполнения буфера а отправит все что есть в буфере.
В данном случае при записи в файл нет необходимости такой.
и про write я ошибся =)
public void write(byte[] b, int off, int len) записывает len byte начиная с позиции b[off]
а все увидел где у тебя косяк в первом варианте.
у тебя массива byte записывается всегда полностью, то есть при последнее операции массив bytes может прочитаться не 1000 байт а например 100, в итоге получится что на последней итерации ты будешь записывать в файл массив состоящий из 100 байт новой информации и 900 старой.
Последний твой вариант годный - считываем количество байт которое прочитали из потока чтения и записываем именно такое количества из массива.
Вот пример для теста:
вывод
0