Łatwy sposób zapisu zawartości strumienia wejściowego Java do strumienia wyjściowego
Byłem zaskoczony, że dzisiaj nie mogłem wyśledzić żadnego prostego sposobu zapisu zawartości InputStream
do OutputStream
w Javie. Oczywiście kod bufora bajtowego nie jest trudny do napisania, ale podejrzewam, że brakuje mi czegoś, co ułatwiłoby mi życie (a kod jaśniejszy).
Więc, biorąc pod uwagę InputStream
in
oraz OutputStream
out
, czy istnieje prostszy sposób na napisanie następujących rzeczy?
byte[] buffer = new byte[1024];
int len = in.read(buffer);
while (len != -1) {
out.write(buffer, 0, len);
len = in.read(buffer);
}
20 answers
Jeśli używasz Java 7, Files (w bibliotece standardowej) jest najlepszym podejściem:
/* You can get Path from file also: file.toPath() */
Files.copy(InputStream in, Path target)
Files.copy(Path source, OutputStream out)
Edit: oczywiście jest to po prostu przydatne, gdy tworzysz jeden z InputStream lub OutputStream z pliku. Użyj file.toPath()
, Aby pobrać ścieżkę z pliku.
Aby zapisać w istniejącym pliku (np. utworzonym za pomocą File.createTempFile()
), musisz przekazać opcję kopiowania REPLACE_EXISTING
(w przeciwnym razie zostanie wyrzucone FileAlreadyExistsException
):
Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-22 12:57:56
Jak wspomniano WMR, org.apache.commons.io.IOUtils
z Apache ma metodę zwaną copy(InputStream,OutputStream)
co robi dokładnie to, czego szukasz.
Więc masz:
InputStream in;
OutputStream out;
IOUtils.copy(in,out);
in.close();
out.close();
...w Twoim kodzie.
Czy jest jakiś powód, dla którego unikasz IOUtils
?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-23 15:36:50
Myślę, że to zadziała, ale upewnij się, że przetestujesz... niewielka "poprawa", ale może to być trochę koszt czytelności.
byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-04 03:58:20
Java 9
Od wersji Java 9, InputStream
dostarcza metodę o nazwie transferTo
z następującym podpisem:
public long transferTo(OutputStream out) throws IOException
Jak stwierdza dokumentacja, transferTo
będzie:
Odczytuje wszystkie bajty z tego strumienia wejściowego i zapisuje bajty do podany strumień wyjściowy w kolejności, w jakiej są odczytywane. Po powrocie, to strumień wejściowy będzie na końcu strumienia. Ta metoda nie zamyka albo strumień.
Ta metoda może blokować w nieskończoność odczyt z wejście stream lub zapis do strumienia wyjściowego. Zachowanie dla przypadek, w którym strumień wejściowy lub wyjściowy jest asynchronicznie zamknięty, lub wątek przerwany podczas transferu, jest wysoce wejściowy i wyjściowy strumień specyficzny, a zatem nie określony
Więc aby napisać zawartość Javy InputStream
do OutputStream
, możesz napisać:
input.transferTo(output);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-07 09:46:25
Używanie guawy ByteStreams.copy()
:
ByteStreams.copy(inputStream, outputStream);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-25 00:00:28
Prosta Funkcja
Jeśli potrzebujesz tego tylko do napisania InputStream
do File
, możesz użyć tej prostej funkcji:
private void copyInputStreamToFile( InputStream in, File file ) {
try {
OutputStream out = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while((len=in.read(buf))>0){
out.write(buf,0,len);
}
out.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-24 23:11:15
PipedInputStream
i PipedOutputStream
powinny być używane tylko wtedy, gdy masz wiele wątków, jak zauważył Javadoc .
Należy również pamiętać, że strumienie wejściowe i wyjściowe nie zawierają przerw w wątku za pomocą IOException
s... Dlatego powinieneś rozważyć włączenie polityki przerwania do swojego kodu:
byte[] buffer = new byte[1024];
int len = in.read(buffer);
while (len != -1) {
out.write(buffer, 0, len);
len = in.read(buffer);
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
Byłoby to przydatne, jeśli spodziewasz się używać tego API do kopiowania dużych ilości danych lub danych ze strumieni, które utkną przez nietolerancyjnie długi czas.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-19 16:27:14
JDK
używa tego samego kodu, więc wydaje się, że nie ma "łatwiejszego" sposobu bez niezgrabnych bibliotek stron trzecich (które i tak pewnie nic nie robią inaczej). Poniżej jest bezpośrednio skopiowane z java.nio.file.Files.java
:
// buffer size used for reading and writing
private static final int BUFFER_SIZE = 8192;
/**
* Reads all bytes from an input stream and writes them to an output stream.
*/
private static long copy(InputStream source, OutputStream sink)
throws IOException
{
long nread = 0L;
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = source.read(buf)) > 0) {
sink.write(buf, 0, n);
nread += n;
}
return nread;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-13 11:10:11
Nie ma sposobu, aby zrobić to dużo łatwiej z metodami JDK, ale jak Apocalisp już zauważył, nie jesteś jedynym z tym pomysłem: możesz użyć IOUtils z Jakarta Commons IO, ma również wiele innych przydatnych rzeczy, które IMO powinny być częścią JDK...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-04 10:50:10
Korzystanie z Java7 i try-with-resources , pochodzi z uproszczoną i czytelną wersją.
try(InputStream inputStream = new FileInputStream("C:\\mov.mp4");
OutputStream outputStream = new FileOutputStream("D:\\mov.mp4")){
byte[] buffer = new byte[10*1024];
for (int length; (length = inputStream.read(buffer)) != -1; ){
outputStream.write(buffer, 0, length);
}
}catch (FileNotFoundException exception){
exception.printStackTrace();
}catch (IOException ioException){
ioException.printStackTrace();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-29 11:12:31
Dla tych, którzy używają Spring framework istnieje przydatna StreamUtils klasa:
StreamUtils.copy(in, out);
Powyższe nie zamyka strumieni. Jeśli chcesz, aby strumienie były zamknięte po skopiowaniu, Użyj klasy FileCopyUtils :
FileCopyUtils.copy(in, out);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-02 14:33:08
Użyj klasy Util Commons Net:
import org.apache.commons.net.io.Util;
...
Util.copyStream(in, out);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-11 20:56:35
Oto jak sobie radzę z najprostszą pętlą for.
private void copy(final InputStream in, final OutputStream out)
throws IOException {
final byte[] b = new byte[8192];
for (int r; (r = in.read(b)) != -1;) {
out.write(b, 0, r);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-22 01:17:50
Myślę, że lepiej jest użyć dużego bufora, ponieważ większość plików jest większa niż 1024 bajty. Dobrą praktyką jest również sprawdzanie, czy liczba odczytanych bajtów jest dodatnia.
byte[] buffer = new byte[4096];
int n;
while ((n = in.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
out.close();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-13 14:24:37
IMHO bardziej minimalistyczny snippet (który również wąsko zakreśla zmienną długości):
byte[] buffer = new byte[2048];
for (int n = in.read(buffer); n >= 0; n = in.read(buffer))
out.write(buffer, 0, n);
Na marginesie, nie rozumiem, dlaczego więcej osób nie używa pętli for
, zamiast tego decyduje się na while
z wyrażeniem assign-and-test, które jest uważane przez niektórych za "kiepski" styl.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-08 04:27:43
PipedInputStream i PipedOutputStream mogą być przydatne, ponieważ można je połączyć z innymi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-04 04:04:07
Innym możliwym kandydatem są narzędzia I/O Guava:
Http://code.google.com/p/guava-libraries/wiki/IOExplained
Pomyślałem, że skorzystam z nich, ponieważ Guava jest już niezwykle przydatna w moim projekcie, zamiast dodawać kolejną bibliotekę dla jednej funkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-11 05:42:34
Try Cactoos :
new LengthOf(new TeeInput(input, output)).value();
Więcej szczegółów tutaj: http://www.yegor256.com/2017/06/22/object-oriented-input-output-in-cactoos.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-21 16:06:09
public static boolean copyFile(InputStream inputStream, OutputStream out) {
byte buf[] = new byte[1024];
int len;
long startTime=System.currentTimeMillis();
try {
while ((len = inputStream.read(buf)) != -1) {
out.write(buf, 0, len);
}
long endTime=System.currentTimeMillis()-startTime;
Log.v("","Time taken to transfer all bytes is : "+endTime);
out.close();
inputStream.close();
} catch (IOException e) {
return false;
}
return true;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-02 18:48:24
Możesz użyć tej metody
public static void copyStream(InputStream is, OutputStream os)
{
final int buffer_size=1024;
try
{
byte[] bytes=new byte[buffer_size];
for(;;)
{
int count=is.read(bytes, 0, buffer_size);
if(count==-1)
break;
os.write(bytes, 0, count);
}
}
catch(Exception ex){}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-06 11:23:20