#java
#java
Вопрос:
Я написал небольшую программу, которая просто считывает содержимое файлов и записывает его в новую копию. Это отлично работает с текстовыми файлами, но с PNG и видеофайлами не удается правильно создать файл (изображение полностью черное или видео не воспроизводится). Я знаю, что есть API, которые могут копировать файлы с помощью одной строки, но я хотел бы знать, почему это не работает. Вот код:
import java.io.*;
public class CopyFile
{
public static void main(String[] args) throws Exception
{
File file = new File("test.mp4");
File copy = new File("copy.mp4");
InputStreamReader input = new InputStreamReader(new FileInputStream(file));
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(copy));
System.out.println(input.ready());
while(input.ready())
{
int i = input.read();
//System.out.print( (char) ( (byte) i));
out.write(i);
}
input.close();
out.flush();
out.close();
}
}
Комментарии:
1. Не используйте
input.ready
, полагайтесь на то, чтоinput.read
говорит
Ответ №1:
- Не используйте
Reader
иWriter
, если вы не знаете, что ввод — это текст. ИспользуйтеInputStream
иOutputStream.
- Также не используйте
ready(),
or, в интересах Sotirios.available()
Ни один из них не является допустимым тестом для end of stream. Оба они касаются того, можно ли читать входные данные без блокировки, что совсем не одно и то же. См. Javadoc. - Вы неправильно определяете конец потока. Если
read()
возвращает -1, вы все равно копируете это на вывод. - Копирование одного символа или одного байта за раз выполняется чрезвычайно медленно.
Канонический способ копирования потоков в Java заключается в следующем:
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
где count
— это int,
и buffer
— byte[]
любой размер, больший нуля, обычно 8192.
Ответ №2:
Reader
s и Writer
s предназначены для чтения потоков символов (т. Е. Текста). Изображения и видео представляют собой двоичные данные, а не текст, и, вероятно, будут повреждены, если вы передадите их через потоки символов. Это связано с тем, что в зависимости от набора символов не обязательно существует обратимое сопоставление между байтами и символами. Некоторые последовательности байтов являются тарабарщиной, если интерпретируются как символы, затем тарабарщина записывается обратно в файл.
Используйте InputStream
and OutputStream
, которые вы открываете напрямую, вместо того, чтобы оборачивать их как Reader
and Writer
, и это будет работать правильно. Это потоки байтов, и они могут обрабатывать данные любого типа.
Например.,
InputStream input = new FileInputStream(file);
OutputStream out = new FileOutputStream(copy);
PS Это все равно будет довольно медленно. Вы можете обернуть потоки в BufferedInputStream
и BufferedOutputStream
для простого способа повышения производительности, хотя API-интерфейсы однострочного копирования, вероятно, все равно будут быстрее.
Комментарии:
1. Вы определили одну проблему из как минимум четырех.
2. @EJP 2 из 3 по моим подсчетам, но да.