I use io scanner / System.out to copy text files. I tried using the same technique to copy pdf, video and image files. The result was that the files were copied, but they were corrupt (cannot open them). Also, the file size does not equal the original file size.
code
import java.awt.Desktop;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Scanner;
public class ScannerTest {
public static void main(String[] args) throws IOException {
PrintStream out =System.out;
long start = System.currentTimeMillis();
copyFile(new File("H:\\a.pdf"), new File("H:\\b.pdf"));// 2 file input, output
System.setOut(out);
System.out.println(System.currentTimeMillis()-start);
}
static String text=null;
public static void copyFile(File input,File output) throws IOException{
//Scanner read file
Scanner in= new Scanner(new FileInputStream(input));
StringBuilder builder =new StringBuilder();
try {
while(in.hasNextLine()){
text=in.nextLine();
builder.append(text);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
in.close();
}
//System.out
try {
OutputStream outputStream = new FileOutputStream(output);
PrintStream printStream = new PrintStream(outputStream);
System.setOut(printStream);
System.out.println(new String(builder));
Desktop.getDesktop().open(output);
} catch (Exception e) {
e.printStackTrace();
}
}
}
p/s: Not use IO other.(ex: BufferedInput/OutputStream)
There are two problems (at least):
you use nextLine() which will read up to the next "\r\n"', '\n', '\r', '\u2028', '\u2029' or '\u0085' and discard what ever it found as line separator (one or two characters). As you are not even using append(text).append('\n') I doubt that this will correctly copy multi-line text, let alone binary files where each of the possible line-terminators may have a different meaning.
you use Scanner and StringBuilder which are not safe for binary data. As the Documentation on new Scanner(java.io.InputStream) states:
Bytes from the stream are converted into characters using the underlying platform's default charset.
If any byte-sequence in you input file is not valid as e.g. UTF-8 (which is a common default charset) it is silently replaced by a generic 'could not read input'-character. For text-files this can mean, that a 'ä' is converted to '�', for binary files this can render the whole file unusable.
If you want to copy arbitrary (possibly binary) files I would recommend not taking any chances and stick to byte[] APIs. You could however also use a charset which is known to accept all byte-sequences unchanged like ISO-8859-1 when creating Scanner and PrintStream; you would than still need to refrain from using line-APIs that suppress the found line-separator.
This should do the trick:
import java.awt.Desktop;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
/**
* Created for http://stackoverflow.com/a/25351502/1266906
*/
public class CopyFile {
public static void main(String[] args) {
long start = System.currentTimeMillis();
copyFile(new File("H:\\a.pdf"), new File("H:\\b.pdf"));// 2 file input, output
System.out.println(System.currentTimeMillis() - start);
}
public static void copyFile(File input, File output) {
try {
try (FileInputStream inputStream = new FileInputStream(input);
OutputStream outputStream = new FileOutputStream(output)) {
byte[] buffer = new byte[4096];
do {
int readBytes = inputStream.read(buffer);
if (readBytes < 1) {
// end of file
break;
} else {
outputStream.write(buffer, 0, readBytes);
}
} while (true);
}
// Open result
Desktop.getDesktop().open(output);
} catch (Exception e) {
e.printStackTrace();
}
}
}
pre Java 7 you need to use try-finally:
public static void copyFile(File input, File output) {
try {
FileInputStream inputStream = new FileInputStream(input);
try {
OutputStream outputStream = new FileOutputStream(output);
try {
byte[] buffer = new byte[4096];
do {
int readBytes = inputStream.read(buffer);
if (readBytes < 1) {
// end of file
break;
} else {
outputStream.write(buffer, 0, readBytes);
}
} while (true);
} finally {
outputStream.close();
}
} finally {
inputStream.close();
}
// Open result
Desktop.getDesktop().open(output);
} catch (Exception e) {
e.printStackTrace();
}
}
Related
This is code that deletes the content of the file then writes on it
I want to write in the file without deleting the content and write on the last line
import java.io.*;
import java.util.Scanner;
public class SetValues {
public void setNumberPhone(String numberPhone) throws UnsupportedEncodingException {
Scanner input = new Scanner(System.in);
PrintWriter pr = null;
try {
input = new Scanner("C:/Users/Abdalrahman/Desktop/PhoneNumber.txt");
pr = new PrintWriter("C:/Users/Abdalrahman/Desktop/PhoneNumber.txt", "UTF-8");
} catch (FileNotFoundException e) {
System.out.println("Not Open" + e.getMessage());
System.exit(0);
}
if (input.hasNext()) {
pr.println(numberPhone);
}
pr.close();
}
}
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.*;
OutputStream os = Files.newOutputStream(Paths.get("C:/Users/Abdalrahman/Desktop/PhoneNumber.txt"), APPEND);
PrintWriter pr = new PrintWriter(os);
pr.println("TEXT");
This will create an output stream wherein any output text will be appended to the current contents of the file. You can use the OutputStream to create a PrintWriter. More information can be found at the Java documentation
I'm trying to develop a simple Java file transfer application using TCP.
My current server code is as follows:
package tcp.ftp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class FTPServer {
public static void main(String[] args) {
new FTPServer().go();
}
void go() {
try {
ServerSocket server = new ServerSocket(2015);
System.out.println("server is running ....!");
while (true) {
Socket socket = server.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String file = reader.readLine();
System.out.println("file to be downloaded is : " + file);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
//bos.close();
}
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
Using my current server code above, the downlloding does not work as expected. the above code sends part of the file to the client , not the entire file. Note that I used the flush method to flush the buffer. but when I replace the flush () method by the close () method, the file is fully sent to the client whithout any loss. Could anyone please explain this behavior!
UPDATE: Here is the code of my client:
package tcp.ftp;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
/**
*
* #author aaa
*/
public class FTPClient {
public static void main(String[] args) {
String file = "JasperReports-Ultimate-Guide-3.pdf";
try {
InetAddress address = InetAddress.getLocalHost();
Socket socket = new Socket(address, 2015);
System.out.println("connection successfully established ....!");
PrintWriter pw = new PrintWriter(socket.getOutputStream());
pw.println(file);
pw.flush();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy" + file));
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
System.out.println("file download is complete ...!");
} catch (UnknownHostException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
}
Another behavior without the use of Socket. take the following code that copy a file from a source to a destination:
public class CopieFile {
static void fastCopy(String source, String destination) {
try {
FileInputStream fis = new FileInputStream(source);
BufferedInputStream bis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream(destination);
BufferedOutputStream bos = new BufferedOutputStream(fos);
while (true) {
int octet = bis.read();
if (octet == -1) {
break;
}
bos.write(octet);
}
bos.flush();
} catch (FileNotFoundException ex) {
System.out.println(ex.getMessage());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
public static void main(String[] args) throws IOException {
String source = "...";
String destination = "...";
fastCopy(source, destination);
}// end main
}// end class
the above code to copy a file from one location to another without any loss. Note well that I did not close the stream.
If you never close the stream the client wil never get end of stream so it will never exit the read loop.
In any case the stream and the socket are about to go out of scope, so if you don't close them you have a resource leak.
I try to create my own class to output system out stream to console and to the file at the same time using BufferedStream. But data doesn't appear from the BufferedOutputStream. How should I fix this problem?
package com.library.stream;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class DoubleEndedStream {
InputStream theInput;
OutputStream theOutput;
public static void main(String[] args) throws IOException, FileNotFoundException {
DoubleEndedStream sr = new DoubleEndedStream(System.in, System.out);
sr.doublingTheStream();
}
public DoubleEndedStream(InputStream in, OutputStream out) {
theInput = in;
theOutput = out;
}
public void doublingTheStream() throws IOException, FileNotFoundException {
try {
FileOutputStream fos = new FileOutputStream("C:\\log.txt");
BufferedOutputStream bout1 = new BufferedOutputStream(fos);
BufferedOutputStream bout2 = new BufferedOutputStream(theOutput);
try {
while (true) {
int datum = theInput.read();
if (datum == -1) break;
bout1.write(datum);
bout2.write(datum);
}
bout1.flush();
bout2.flush();
} catch (IOException e) {
System.err.println("Couldn't read from System.in!");
}
bout1.close();
bout2.close();
fos.close();
} catch (FileNotFoundException e) {
System.err.println("Couldn't find log.txt");
}
}
}
Since theInput is System.in, as long as you don't close it, (ctrl-d in unix), it will not return -1, but hang and wait for input. Since you perform flush() only when received -1, you never get to this point. Try flushing after the write() instead.
I am reading a video file data in bytes and sending to another file but the received video file is not playing properly and is chattered.
Can anyone explain me why this is happening and a solution is appreciated.
My code is as follows
import java.io.*;
public class convert {
public static void main(String[] args) {
//create file object
File file = new File("B:/music/Billa.mp4");
try
{
//create FileInputStream object
FileInputStream fin = new FileInputStream(file);
byte fileContent[] = new byte[(int)file.length()];
fin.read(fileContent);
//create string from byte array
String strFileContent = new String(fileContent);
System.out.println("File content : ");
System.out.println(strFileContent);
File dest=new File("B://music//a.mp4");
BufferedWriter bw=new BufferedWriter(new FileWriter(dest));
bw.write(strFileContent+"\n");
bw.flush();
}
catch(FileNotFoundException e)
{
System.out.println("File not found" + e);
}
catch(IOException ioe)
{
System.out.println("Exception while reading the file " + ioe);
}
}
}
This question might be dead but someone might find this useful.
You can't handle video as string. This is the correct way to read and write (copy) any file using Java 7 or higher.
Please note that size of buffer is processor-dependent and usually should be a power of 2. See this answer for more details.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class FileCopy {
public static void main(String args[]) {
final int BUFFERSIZE = 4 * 1024;
String sourceFilePath = "D:\\MyFolder\\MyVideo.avi";
String outputFilePath = "D:\\OtherFolder\\MyVideo.avi";
try(
FileInputStream fin = new FileInputStream(new File(sourceFilePath));
FileOutputStream fout = new FileOutputStream(new File(outputFilePath));
){
byte[] buffer = new byte[BUFFERSIZE];
while(fin.available() != 0) {
bytesRead = fin.read(buffer);
fout.write(buffer, 0, bytesRead);
}
}
catch(Exception e) {
System.out.println("Something went wrong! Reason: " + e.getMessage());
}
}
}
Hope this also helpful for you - This can read and write a file into another file (You can use any file type to do that)
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class Copy {
public static void main(String[] args) throws Exception {
FileInputStream input = new FileInputStream("input.mp4"); //input file
byte[] data = input.readAllBytes();
FileOutputStream output = new FileOutputStream("output.mp4"); //output file
output.write(data);
output.close();
}
}
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import javax.imageio.ImageIO;
public class Reader {
public Reader() throws Exception{
File file = new File("C:/Users/Digilog/Downloads/Test.mp4");
FileInputStream fin = new FileInputStream(file);
byte b[] = new byte[(int)file.length()];
fin.read(b);
File nf = new File("D:/K.mp4");
FileOutputStream fw = new FileOutputStream(nf);
fw.write(b);
fw.flush();
fw.close();
}
}
In addition to Jakub Orsula's answer, one needs to check the result of read operation to prevent garbage being written to end of file in last iteration.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class FileCopy {
public static void main(String args[]) {
final int BUFFERSIZE = 4 * 1024;
String sourceFilePath = "D:\\MyFolder\\MyVideo.avi";
String outputFilePath = "D:\\OtherFolder\\MyVideo.avi";
try(
FileInputStream fin = new FileInputStream(new File(sourceFilePath));
FileOutputStream fout = new FileOutputStream(new File(outputFilePath));
){
byte[] buffer = new byte[BUFFERSIZE];
int bytesRead;
while(fin.available() != 0) {
bytesRead = fin.read(buffer);
fout.write(buffer, 0, bytesRead);
}
}
catch(Exception e) {
System.out.println("Something went wrong! Reason: " + e.getMessage());
}
}
}
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
public class Audio_to_bytes {
public static void main(String args[]) throws IOException
{
File WAV_FILE = new File("/home/cybersecurity/Desktop/scream.wav");
ByteArrayOutputStream out = new ByteArrayOutputStream();
AudioInputStream in = null;
try {
in = AudioSystem.getAudioInputStream(WAV_FILE);
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
int read,i;
byte[] buff = new byte[1024];
while ((read = in.read(buff)) > 0)
{
out.write(buff, 0, read);
}
out.flush();
byte[] audioBytes = out.toByteArray();
for(i=0;i<audioBytes.length;i++)
System.out.println(audioBytes[i]);
}
}
The above code is to convert the .wav file into a byte array.When I execute the program i get get many value as -128 or -127,I want to know that whether these values are exact values or the value becomes a boundary value if it exceeds the range of byte(-128 to 128),
if so can i convert the audio file into a integer array since it has a wider range.
The raw file is irrelevant since WAVE files are constructed using chunks. I suggest understanding those chunks first, RIFF File Format, to understand WAVE files.