? ? ? 文件复制的原理是通过读取一个文件的内容,然后将其写入到另一个文件中。具体步骤如下:
? ? ?代码示例? ?
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
语句块来确保程序的稳定性和可靠性。