java多线程读取大文件(日后还会复盘)

x33g5p2x  于2021-11-29 转载在 Java  
字(3.7k)|赞(0)|评价(0)|浏览(688)

首先讲解一下Java RandomAccessFile用法:

动态读取文件内容:所谓动态读取是指从文件的任意位置开始访问文件,而不是必须从文件开始位置读取到文件末尾。动态读取需要用到 Java 中的 RandomAccessFile 类。

  • RandomAccessFile 是 Java 输入/输出流体系中功能最丰富的文件内容访问类,它提供了众多的方法来访问文件内容,它既可以读取文件内容,也可以向文件输出数据。由于 RandomAccessFile 可以从任意位置访问文件,所以在只需要访问文件部分内容的情况下,使用 RandonAccessFile 类是一个很好的选择。

  • RandomAccessFile 对象包含了一个记录指针,用以标识当前读写处的位置,当程序新创建一个 RandomAccessFile 对象时,该对象的文件记录指针位于文件头(也就是 0 处),当读/写了 n 个字节后,文件记录指针将会向后移动 n 个字节。除此之外,RandonAccessFile 可以自由移动该记录指针,既可以向前移动,也可以向后移动。

RandomAccessFile 类中提供了一些常用读取和写入数据的方法,如表 1 所示。

RandomAccessFile 类的构造方法有如下两种重载形式。

  • RandomAccessFile(File file, String mode):访问参数 file 指定的文件,访问形式由参数 mode 指定,mode 参数有两个常用的可选值 r 和 rw,其中 r 表示只读,rw 表示读写。

  • RandomAccessFile(String name, String mode):访问参数 name 指定的文件,mode 参数的含义同上。

注意:如果使用 rw 方式声明 RandomAccessFile 对象时,要写入的文件不存在,系统将自动进行创建。

例 1

编写一个程序,使用 RandomAccessFileDemo 类创建一个 words.txt 文件,然后写入一个长中文字符串,再从第 6 个字节开始读取并输出。:

1:创建一个 RandomAccessFileDemo 类对象。在 main() 方法中创建到 D:\JavaCodes\words.txt 的 File 对象,如果该文件已经存在则先删除再创建,代码如下所示:

  1. public class RandomAccessFileDemo {
  2. public static void main(String[] args) {
  3. try {
  4. File file = new File("D:\\myJava\\words.txt"); // 指定文件路径
  5. if (file.exists()) { // 判断文件是否存在
  6. file.delete();
  7. file.createNewFile();
  8. }
  9. } catch (IOException e) {
  10. System.out.print(e);
  11. }
  12. }
  13. }

2:创建 RandomAccessFile 对象,以读写方式操作 File 对象。定义一个要写入的字符串,再将其进行格式的转换。这样是为了使其写入文件的内容不出现乱码,再将转换后的内容写入文件,代码如下所示。

  1. RandomAccessFile raf = new RandomAccessFile(file,"rw");
  2. String str1 = "晴天,阴天,多云,小雨,大风,中雨,小雪,雷阵雨"; // 要写入的字符串
  3. String str2 = new String(str1.getBytes("GBK"),"ISO-8859-1"); // 编码转换
  4. raf.writeBytes(str2); //写入文件

3)打印出当前指针的位置,然后将其移动到第 6 个字节。再定义一个长度为 2 的 byte 数组,然后开始进行内容的循环读取,将读出的内容以字符串的形式输出到控制台,代码如下所示。

  1. System.out.println("当前文件指针的位置:" + raf.getFilePointer());
  2. raf.seek(6); // 移动文件指针
  3. System.out.println("从文件头跳过6个字节,现在文件内容如下:");
  4. byte[] buffer = new byte[2];
  5. int len = 0;
  6. while ((len = raf.read(buffer, 0, 2)) != -1) {
  7. System.out.print(new String(buffer, 0, len)); // 输出文件内容
  8. }

4)运行程序,程序运行结果如下所示,显示了写入字符串后指针的位置,以及从文件开关跳过 6 个字节后读取到的字符串,图 1 为写入文件中的字符串内容:

  1. 当前文件指针的位置:48
  2. 从文件头跳过6个字节,现在文件内容如下:
  3. 阴天,多云,小雨,大风,中雨,小雪,雷阵雨

开启任务:代码实现

  1. import java.io.File;
  2. import java.io.FileNotFoundException;
  3. import java.io.IOException;
  4. import java.io.RandomAccessFile;
  5. class CopyFileThread extends Thread{
  6. private RandomAccessFile in;
  7. private RandomAccessFile out;
  8. private long start;
  9. private long end;
  10. /** * * @param in 源文件地址 * @param out 目标文件地址 * @param start 分段复制的开始位置 * @param end 分段复制的结束位置 */
  11. public CopyFileThread(String in, String out,
  12. long start, long end){
  13. this.start = start;
  14. this.end = end;
  15. try {
  16. this.in = new RandomAccessFile(in, "rw");
  17. this.out = new RandomAccessFile(out, "rw");
  18. } catch (FileNotFoundException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22. public void run(){
  23. try {
  24. in.seek(start);
  25. out.seek(start);
  26. int hasRead = 0;
  27. byte[] buff = new byte[1024*1024];
  28. while(start<end && (hasRead = in.read(buff)) != -1){
  29. start += hasRead;
  30. out.write(buff, 0, hasRead);
  31. }
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. }finally{
  35. try {
  36. in.close();
  37. out.close();
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. }
  43. }
  44. public class ThreadsCopyFile {
  45. /** * * @param sourcePath 源文件路径 * @param targetPath 目标文件路径 * @param ThreadNums 设定的线程数 * @throws IOException */
  46. public void startCopy(String sourcePath, String targetPath, int ThreadNums)
  47. throws IOException{
  48. long fileLength = new File(sourcePath).length();
  49. //很有可能文件长度线程不能均分下载,预留一个线程复制最后剩余的部分
  50. long segmentLength = fileLength/(ThreadNums-1);
  51. int i;
  52. for (i = 0; i < ThreadNums-1; i++) {
  53. new CopyFileThread(sourcePath, targetPath, i*segmentLength, (i+1)*segmentLength).start();
  54. }
  55. new CopyFileThread(sourcePath, targetPath, i*segmentLength, fileLength).start();
  56. }
  57. public static void main(String[] args) throws IOException {
  58. //demo中实现的是将e盘中这个目录下的电影复制到d盘下的tttt.rmvb
  59. ThreadsCopyFile tcf = new ThreadsCopyFile();
  60. String sourcePath = "E:\\NewFile\\AppData\\Xunlei\\[阳光电影www.ygdy8.com].金刚狼3:殊死一战.HD.720p.中英双字幕.rmvb";
  61. String targetPath = "D:\\tttt.rmvb";
  62. tcf.startCopy(sourcePath, targetPath, 3);
  63. }
  64. }

相关文章

最新文章

更多

目录