使用 Java 写文件的 N 种方法

850 阅读5分钟
原文链接: codippa.com

Writing a new file or copying a file is a task which every developer is required to perform. Java provides many different ways to write a file according to requirements. Below are listed various methods in which a file can be written in java.

Method 1: Using java.io.FileOutputStream

	static void writeUsingStream(String outFilePath, String filePath) {
		FileOutputStream fout = null;
		FileInputStream fin = null;
		byte[] buffer = new byte[1024];
		try {
			fin=new FileInputStream(new File(filePath));
			fout = new FileOutputStream(new File(outFilePath));
			int i = 0;
			while ((i = fin.read(buffer)) != -1) {
				fout.write(buffer);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (fin != null) {
					fin.close();
				}
				if (fout != null) {
					fout.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

static void writeUsingStream(String outFilePath, String filePath) { FileOutputStream fout = null; FileInputStream fin = null; byte[] buffer = new byte[1024]; try { fin=new FileInputStream(new File(filePath)); fout = new FileOutputStream(new File(outFilePath)); int i = 0; while ((i = fin.read(buffer)) != -1) { fout.write(buffer); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fin != null) { fin.close(); } if (fout != null) { fout.close(); } } catch (IOException e) { e.printStackTrace(); } } }

Detail : Initialize a java.io.FileInputStream with the source file as argument, a java.io.FileOutputStream with the file to write as argument and a byte array which will hold all the bytes read by the stream. Iterate over read() method till it returns -1 which means that the end of file has reached. In each iteration, the stream reads the bytes from the file and writes them to the buffer. The buffer contents are then written to the output stream. At the end, do not forget to close the streams.

Method 2: Using java.io.FileWriter

	static void writeUsingFileWriter(String outFilePath, String filePath) {
		FileReader fr = null;
		FileWriter fwr = null;
		char[] buffer = new char[1024];
		try {
			fr = new FileReader(filePath);
			fwr = new FileWriter(outFilePath);
			int i = 0;
			while ((i = fr.read(buffer)) != -1) {
				fwr.write(buffer);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (fr != null) {
					fr.close();
				}
				if (fwr != null) {
					fwr.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

static void writeUsingFileWriter(String outFilePath, String filePath) { FileReader fr = null; FileWriter fwr = null; char[] buffer = new char[1024]; try { fr = new FileReader(filePath); fwr = new FileWriter(outFilePath); int i = 0; while ((i = fr.read(buffer)) != -1) { fwr.write(buffer); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fr != null) { fr.close(); } if (fwr != null) { fwr.close(); } } catch (IOException e) { e.printStackTrace(); } } }

Detail : Initialize a java.io.FileReader with the source file as argument, a java.io.FileWriter with the file to write as argument and a character array which will hold all the characters read by the stream. Iterate over read() method till it returns -1 which means that the end of file has reached. In each iteration, the file reader reads the characters from the file and writes them to the buffer. The characters from the buffer then written to the output file. At the end, do not forget to close the readers.

Method 3: Using java.io.BufferedWriter

	static void writeUsingBufferedWriter(String outFilePath,String filePath) {
		BufferedReader br = null;
		BufferedWriter bwr = null;
		try {
			br = new BufferedReader(new FileReader(filePath));
			bwr = new BufferedWriter(new FileWriter(outFilePath));
			String str = null;
			while ((str = br.readLine()) != null) {
				bwr.write(str);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (br != null) {
					br.close();
				}
				if (bwr != null) {
					bwr.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

static void writeUsingBufferedWriter(String outFilePath,String filePath) { BufferedReader br = null; BufferedWriter bwr = null; try { br = new BufferedReader(new FileReader(filePath)); bwr = new BufferedWriter(new FileWriter(outFilePath)); String str = null; while ((str = br.readLine()) != null) { bwr.write(str); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (br != null) { br.close(); } if (bwr != null) { bwr.close(); } } catch (IOException e) { e.printStackTrace(); } } }

Detail : Initialize a java.io.BufferedReader object which takes a java.io.FileReader object as argument which is linked to the original file. Iterate over readLine() method till it returns -1 which means that the end of file has reached. In each iteration the string returned is written to the output file. At the end, do not forget to close the readers.

Method 4: Using Apache Commons library

	static void usingApacheCommons(String outFilePath, String filePath) {
		FileInputStream fin = null;
		FileWriter fwr = null;
		try {
			fwr = new FileWriter(outFilePath);
			fin = new FileInputStream(new File(filePath));
			IOUtils.copy(fin, fwr);
		} catch (FileNotFoundException fne) {
			fne.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (fin != null) {
					fin.close();
				}
				if (fwr != null) {
					fwr.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

static void usingApacheCommons(String outFilePath, String filePath) { FileInputStream fin = null; FileWriter fwr = null; try { fwr = new FileWriter(outFilePath); fin = new FileInputStream(new File(filePath)); IOUtils.copy(fin, fwr); } catch (FileNotFoundException fne) { fne.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fin != null) { fin.close(); } if (fwr != null) { fwr.close(); } } catch (IOException e) { e.printStackTrace(); } } }

Detail : Initialize a java.io.FileInputStream object with the source file as argument. copy() method of IOUtils from Apache commons library takes an input stream and writes it to a writer. In this case we take a java.io.FileWriter. At the end, do not forget to close the input stream and file writer. This method requires Apache commons library to be on the classpath. Get it here

Method 5: Using java.nio.channels.FileChannel (jdk 7 & above)

      static void usingChannel(String outFilePath,String filePath){
		RandomAccessFile fileAccessForRead = null;
		RandomAccessFile fileAccessForWrite = null;
		FileChannel readChannel = null;
		try {
			fileAccessForRead = new RandomAccessFile(new File(filePath), "r");
			readChannel = fileAccessForRead.getChannel();
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			fileAccessForWrite = new RandomAccessFile(outFilePath, "rw");
			FileChannel writeChannel = fileAccessForWrite.getChannel();
			while(readChannel.read(buffer)!=-1){
				buffer.flip();
				writeChannel.write(buffer);
				buffer.clear();
			}
 
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

static void usingChannel(String outFilePath,String filePath){ RandomAccessFile fileAccessForRead = null; RandomAccessFile fileAccessForWrite = null; FileChannel readChannel = null; try { fileAccessForRead = new RandomAccessFile(new File(filePath), "r"); readChannel = fileAccessForRead.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(1024); fileAccessForWrite = new RandomAccessFile(outFilePath, "rw"); FileChannel writeChannel = fileAccessForWrite.getChannel(); while(readChannel.read(buffer)!=-1){ buffer.flip(); writeChannel.write(buffer); buffer.clear(); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }

Detail : Initialize a java.io.RandomAccessFile.RandomAccessFile with the source file as argument. RandomAccessFile can be used to both read or write to a file. It takes an operation mode along with the file path as argument during initialization. Since we want to read the file, we set the mode as “r”, which means read mode. We also need to write a file so we initialize another RandomAccessFile with write mode (“rw”).
RamdomAccessFile opens a java.nio.channels.FileChannel through its getChannel() method. Like RandomAccessFile objects, we initialize two FileChannel objects, one for reading and another for writing. FileChannel reads the data using its read() method and writes it to a java.nio.ByteBuffer. This buffer is then written to the output file channel which writes it to the file.
FileChannels act as a bridge between the file and storage buffer, both on the read as well as write side. Same buffer is used to hold the contents of file and for reading its contents. This is done using buffer’s flip() method which resets the position of the buffer to 0 in every iteration. At the end, do not forget to close the fileAccess.

Note :

  1. All the above methods write the output to a file but they may also be written to the console. Refer this post for details.
  2. If the contents to be written to a file are not required to be taken from another file or if a string is to be written to a file, then it can be easily done using slight modifications in above code. Refer this post.

Let’s tweak in :

  1. All file reader and writer classes which directly interact with a file or a java.io.File object such as java.io.FileInputStreamjava.io.FileReader, java.io.FileOutputStream throw a java.io.FileNotFoundException since there is always a risk of file location being invalid (either the file is not present or the location denotes a directory).
  2. All read() and write() methods throw a java.io.IOException since many kinds of errors may arise during both these operations such as file is corrupt, there are no write permissions, no disk space, file removed from its location etc.
  3. java.io.FileOutputStreamjava.io.FileWriter both have constructors which take a java.io.File object or a file name in String format as arguments.
  4. java.io.FileOutputStream operates over bytes and is more suitable for binary files such as images, jars etc. while java.io.FileWriter deals with characters and is more suitable for text files.
  5. java.io.BufferedWriter is faster as compared to java.io.FileOutputStream and java.io.FileWriteras it writes a complete line in one go.
  6. read() method of all reader classes returns -1 when there is nothing left to read.
  7. Closing a java.io.BufferedWriter closes the underlying java.io.Writer and there is no need to close it explicitly. Similarly, closing java.io.RandomAccessFile also closes the underlying java.nio.channels.FileChannel
  8. If you are using jdk 7 and above for development and declare the stream or reader objects as try(FileOutputStream fin = new FileOutputStream(new File(filePath))) and you don’t need to explicitly close the stream or reader. This is called try-with-resources construct.