文件复制的原理是通过读取一个文件的内容,然后将其写入到另一个文件中。具体步骤如下:
代码示例
package io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 文件的复制
*/
public class CopyDemo {
public static void main(String[] args) throws IOException {
//创建文件输入流读取原文件
FileInputStream fis = new FileInputStream("image.jpg");
//创建文件输出流写入复制文件
FileOutputStream fos = new FileOutputStream("image_cp.jpg");
int d;//保存每次读取到的字节
/*
原文件数据:
11000011 10101010 00001111 11001100 00110011 ...
^^^^^^^^
d = fis.read();
d:00000000 00000000 00000000 10101010
fos.write(d);
复制文件的数据:
11000011 10101010
*/
long start = System.currentTimeMillis();//获取当前系统时间的毫秒值(UTC时间)
while((d = fis.read()) != -1) {
fos.write(d);
}
long end = System.currentTimeMillis();//获取当前系统时间的毫秒值(UTC时间)
System.out.println("复制完毕!耗时:"+(end-start)+"ms");
fis.close();
fos.close();
}
}
int read(byte[] data)
一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。
返回值为实际读取到的字节量。若返回值为-1则表示读取到了文件末尾。
块写操作
void write(byte[] data)
一次性将给定的字节数组所有字节写入到文件中
void write(byte[] data,int offset,int len)
一次性将给定的字节数组从下标offset处开始的连续len个字节写入文件
package io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 通过提高每次读写的数据量,减少实际读写的次数,可以提高读写效率。
* 单字节读写是一种随机读写形式。而一组一组字节的读写是块读写形式。
*/
public class CopyDemo2 {
public static void main(String[] args) throws IOException {
//使用块读写形式完成文件复制
//创建文件输入流读取原文件
FileInputStream fis = new FileInputStream("wnwb.exe");
//创建文件输出流写复制文件
FileOutputStream fos = new FileOutputStream("wnwb_cp.exe");
/*
流提供了块读写的方法
int read(byte[] data)
一次性从文件中读取给定的字节数组总长度的字节量,并存入到该数组中。
返回值为实际读取到的字节量。若返回值为-1则表示读取到了文件末尾。
文件数据
11001100 11110000 10101010 00001111 00110011
^^^^^^^^ ^^^^^^^^ ^^^^^^^^
int d;
byte[] data = new byte[3];
[00000000 00000000 00000000]
第一次调用
d = fis.read(data);
[11001100 11110000 10101010]
d = 3 本次读取到了3个字节
文件数据
11001100 11110000 10101010 00001111 00110011
^^^^^^^^ ^^^^^^^^
第二次调用
d = fis.read(data);//仅读取了最后两个字节
[00001111 00110011 10101010]//前两个字节为本次读取的内容
^^^^^^^^ ^^^^^^^^
d = 2 本次读取到了2个字节
文件数据
11001100 11110000 10101010 00001111 00110011 文件末尾!
^^^^^^^^
第三次调用
d = fis.read(data);//一个字节都没有读取到
[00001111 00110011 10101010]数组没变化
d = -1 文件末尾
块写操作
void write(byte[] data)
一次性将给定的字节数组所有字节写入到文件中
void write(byte[] data,int offset,int len)
一次性将给定的字节数组从下标offset处开始的连续len个字节写入文件
*/
int len;//记录每次实际读取的字节量
/*
00000000 1byte 8位2进制称为1字节
1024byte 1kb
1024kb 1mb
1024mb 1gb
*/
byte[] data = new byte[1024*10];//10kb
long start = System.currentTimeMillis();
while((len = fis.read(data))!=-1){
fos.write(data,0,len);//读取多少就写多少
}
long end = System.currentTimeMillis();
System.out.println("复制完毕!耗时:"+(end-start)+"ms");
fis.close();
fos.close();
}
}
String提供方法:
byte[] getBytes(String charsetName)
将当前字符串转换为一组字节
参数为字符集的名字,常用的是UTF-8。 其中中文字3字节表示1个,英文1字节表示1个。
package io;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
* 向文件中写入文本数据
*/
public class WriteStringDemo {
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("demo.txt");
String str = "super idol的笑容都没你的甜,";
/*
支持中文的常见字符集有:
GBK:国标编码。英文每个字符占1个字节,中文每个字符占2个字节
UTF-8:内部是unicode编码,在这个基础上不同了少部分2进制信息作为长度描述
英文每个字符占1字节
中文每个字符占3字节
String提供了将字符串转换为一组字节的方法
byte[] getBytes(String charsetName)
参数为字符集的名字,名字不缺分大小写,但是拼写错误会引发异常:
UnsupportedEncodingException
不支持 字符集 异常
*/
byte[] data = str.getBytes("UTF-8");
fos.write(data);
fos.write("八月正午的阳光,都没你耀眼。".getBytes("UTF-8"));
System.out.println("写出完毕!");
fos.close();
}
}
重载的构造方法可以将文件输出流创建为追加模式
- FileOutputStream(String path,boolean append)
- FileOutputStream(File file,boolean append)
当第二个参数传入true时,文件流为追加模式,即:指定的文件若存在,则原有数据保留,新写入的数据会被顺序的追加到文件中
package io;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 文件流的追加写模式
*/
public class FileAppendDemo {
public static void main(String[] args) throws IOException {
/*
FileOutputStream默认创建方式为覆盖模式,即:如果连接的文件存在,
则会将该文件原有数据全部删除。然后将通过当前流写出的内容保存到文件中。
重载的构造方法允许我们再传入一个boolean型参数,如果这个值为true,则
文件流为追加模式,即:若连接文件时该文件存在,原有数据全部保留,通过当前
流写出的数据会顺序的追加到文件中。
*/
FileOutputStream fos = new FileOutputStream(
"demo.txt",true
);
fos.write("热爱105°的你,".getBytes("UTF-8"));
fos.write("滴滴清纯的蒸馏水。".getBytes("UTF-8"));
System.out.println("写出完毕!");
fos.close();
}
}
package io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* 从文件中读取文本数据
*/
public class ReadStringDemo {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("fos.txt");
byte[] data = new byte[1024];
int len = fis.read(data);//块读操作
System.out.println("实际读取到了"+len+"个字节");
/*
String提供了将字节数组转换为字符串的构造方法:
String(byte[]data,String charsetName)
将给定的字节数组中所有字节按照指定的字符集转换为字符串
String(byte[]data,int offset,int len,String charsetName)
将给定的字节数组从下标offset处开始的连续len个字节按照指定的字符集转换为字符串
*/
String line = new String(data,0,len,"UTF-8");
System.out.println(line);
System.out.println(line.length());
fis.close();
}
}
文件的读写操作主要是通过输入输出流(IO流)来实现的。IO流分为字节流和字符流两种类型,分别用于处理二进制文件和文本文件。
读文件操作步骤:
FileInputStream
或BufferedInputStream
来创建文件输入流对象。read()
方法读取一个字节,或者使用read(byte[] buffer)
方法读取多个字节到缓冲区。写文件操作步骤:
FileOutputStream
或BufferedOutputStream
来创建文件输出流对象。write(int b)
方法写入一个字节,或者使用write(byte[] buffer)
方法写入多个字节。 另外,为了方便处理文本文件,Java还提供了字符流用于处理字符数据,通常与字节流配合使用。常用的字符流有FileReader
和FileWriter
。
读取文本文件:
FileReader
或BufferedReader
来创建字符输入流对象。read()
方法读取一个字符,或者使用read(char[] buffer)
方法读取多个字符到缓冲区。写入文本文件:
FileWriter
或BufferedWriter
来创建字符输出流对象。write(int c)
方法写入一个字符,或者使用write(char[] buffer)
方法写入多个字符。 在进行文件读写操作时,需要注意异常处理和资源释放,可以使用try-catch-finally
语句块来确保程序的稳定性和可靠性。