最近在准备面试,翻了翻自己以前写的Demo,发现自己写了不少的工具包,今天整理了一下,分享给大家。

本文包含以下Demo:
1、常用方法测试
2、在文件中间插入一段新的数据
3、多线程下载文件
4、多线程复制文件
5、超大文件的读写

具体注意事项我会全部写在注释中,我就不再啰嗦介绍RandomAccessFile怎么去用,它跟普通文件读写类似,不过就是多了一个游标,可以从文件指定位置开始读取,大家可以一边参照API,一边看我的Demo执行情况,试着自己写写。
大家有好的改进意见、建议或者有什么问题欢迎留言。

RandomAccessFile常用方法

  1. /**
  2. * 这个Demo是刚开始接触RandomAccessFile从网络上找到的,如今我也不记得出处
  3. *
  4. * @author ?? 2016/11/7
  5. * @version 1.0
  6. */
  7. import java.io.RandomAccessFile;
  8. public class RandomAccessFileDemo {
  9. public static void main(String[] args) throws Exception {
  10. RandomAccessFile file = new RandomAccessFile("file", "rw");
  11. // 占4个字节
  12. file.writeInt(20);
  13. // 占8个字节
  14. file.writeDouble(8.236598);
  15. // 这个长度写在当前文件指针的前两个字节处,可用readShort()读取
  16. file.writeUTF("这是一个UTF字符串");
  17. // 占1个字节
  18. file.writeBoolean(true);
  19. // 占2个字节
  20. file.writeShort(395);
  21. // 占8个字节
  22. file.writeLong(2325451l);
  23. file.writeUTF("又是一个UTF字符串");
  24. // 占4个字节
  25. file.writeFloat(35.5f);
  26. // 占2个字节
  27. file.writeChar('a');
  28. // 把文件指针位置设置到文件起始处
  29. file.seek(0);
  30. // 以下从file文件中读数据,要注意文件指针的位置
  31. System.out.println("——————从file文件指定位置读数据——————");
  32. System.out.println(file.readInt());
  33. System.out.println(file.readDouble());
  34. System.out.println(file.readUTF());
  35. // 将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。
  36. file.skipBytes(3);
  37. System.out.println(file.readLong());
  38. // 跳过文件中“又是一个UTF字符串”所占字节,注意readShort()方法会移动文件指针,所以不用加2。
  39. file.skipBytes(file.readShort());
  40. System.out.println(file.readFloat());
  41. // 以下演示文件复制操作
  42. System.out.println("——————文件复制(从file到fileCopy)——————");
  43. file.seek(0);
  44. RandomAccessFile fileCopy = new RandomAccessFile("fileCopy", "rw");
  45. // 取得文件长度(字节数)
  46. int len = (int) file.length();
  47. byte[] b = new byte[len];
  48. file.readFully(b);
  49. fileCopy.write(b);
  50. System.out.println("复制完成!");
  51. file.close();
  52. fileCopy.close();
  53. }
  54. }

超大文件读写

  1. import java.io.RandomAccessFile;
  2. import java.nio.ByteBuffer;
  3. import java.nio.CharBuffer;
  4. import java.nio.MappedByteBuffer;
  5. import java.nio.channels.FileChannel;
  6. import java.nio.charset.Charset;
  7. import java.nio.charset.CharsetDecoder;
  8. /**
  9. * 超大文件读写
  10. *
  11. * @author ChenSS 2016/11/7
  12. * @version 1.0
  13. */
  14. public class LargeMappedFiles {
  15. static int length = 0x8000000; // 128 Mb
  16. public static void main(String[] args) throws Exception {
  17. // 为了以可读可写的方式打开文件,这里使用RandomAccessFile来创建文件。
  18. // 注意,文件通道的可读可写要建立在文件流本身可读写的基础之上
  19. RandomAccessFile accessFile = new RandomAccessFile("test.dat", "rw");
  20. FileChannel fileChannel = accessFile.getChannel();
  21. // 使用MappedByteBuffer写128M的内容
  22. MappedByteBuffer out = fileChannel.map(FileChannel.MapMode.READ_WRITE,
  23. 0, length);
  24. for (int i = 0; i < length; i++) {
  25. out.put((byte) 'x');
  26. }
  27. // 另一种写入方式,128M结尾追加一句话,待会再想办法读出来
  28. String newData = "这是最后一句话";
  29. // 分配字节缓冲区
  30. ByteBuffer buf = ByteBuffer.allocate(48);
  31. // clear方法将缓冲区清空。
  32. buf.clear();
  33. // 放入字符串
  34. buf.put(newData.getBytes());
  35. // 回到当前缓存的头部
  36. buf.flip();
  37. // hasRemaining告知在当前位置和限制之间是否有元素。
  38. while (buf.hasRemaining()) {
  39. fileChannel.write(buf);
  40. }
  41. System.out.println("========================");
  42. StringBuilder result = new StringBuilder();
  43. // 定义字节缓冲区
  44. ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
  45. // 定义解码后字符存储缓冲区
  46. CharBuffer charBuffer = CharBuffer.allocate(1024);
  47. // 定义合适的字符集解码器
  48. CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
  49. // 设置此缓冲区的位置
  50. fileChannel.position(length);
  51. while ((fileChannel.read(byteBuffer)) != -1) { // 读取字符串到缓冲区
  52. byteBuffer.flip();
  53. charBuffer.clear();
  54. // 对byteBuffer进行解码
  55. if (fileChannel.position() < fileChannel.size()) {
  56. decoder.decode(byteBuffer, charBuffer, false);
  57. } else {
  58. // 最后一次解码
  59. decoder.decode(byteBuffer, charBuffer, true);
  60. decoder.flush(charBuffer);
  61. }
  62. // 注意此处调用compact方法,而不是clear方法
  63. byteBuffer.compact();
  64. charBuffer.flip();
  65. // 将charBuffer放入返回结果中
  66. char[] chars = new char[charBuffer.remaining()];
  67. charBuffer.get(chars, 0, charBuffer.remaining());
  68. result.append(chars);
  69. }
  70. System.out.println(result);
  71. // 读取文件中间6个字节内容
  72. for (int i = length / 2; i < length / 2 + 6; i++) {
  73. System.out.print((char) out.get(i));
  74. }
  75. fileChannel.close();
  76. accessFile.close();
  77. }
  78. }

文件追加内容

  1. /**
  2. * 文件追加
  3. * @author ChenSS 2016/11/7
  4. * @version 1.0
  5. */
  6. public class FileAppend {
  7. public static void main(String[] args) {
  8. FileAppend.append(4, "zhuangjiangtao", "file.txt");
  9. }
  10. public static void append(long skip, String str, String fileName) {
  11. try {
  12. RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
  13. byte[] b = str.getBytes();
  14. long len = b.length;
  15. long start = len + skip;
  16. // 重新开辟空间
  17. raf.setLength(raf.length() + len);
  18. for (long i = raf.length() - 1; i >= start; i--) {
  19. raf.seek(i - len);
  20. byte temp = raf.readByte();
  21. raf.seek(i);
  22. raf.writeByte(temp);
  23. }
  24. raf.seek(skip);
  25. raf.write(b);
  26. raf.close();
  27. } catch (Exception e) {
  28. e.printStackTrace();
  29. }
  30. }
  31. }

多线程复制文件

  1. import java.io.File;
  2. import java.io.FileNotFoundException;
  3. import java.io.RandomAccessFile;
  4. /**
  5. * 多线程复制文件
  6. * @author ChenSS 2016/11/7
  7. * @version 1.0
  8. */
  9. public class UsingThreadRandom {
  10. public static void main(String[] args) throws Exception {
  11. File file = new File("aaa.jpg");
  12. startThread(4, file.length(), "aaa.jpg", "baabb.jpg");
  13. }
  14. /**
  15. * 开启多线程下载
  16. *
  17. * @param threadnum 线程数
  18. * @param fileLength 文件大小(用于确认每个线程下载多少东西)
  19. * @param sourseFilePath 源文件目录
  20. * @param targerFilePath 目标文件目录
  21. */
  22. public static void startThread(int threadnum, long fileLength,
  23. String sourseFilePath, String targerFilePath) {
  24. System.out.println("================");
  25. long modLength = fileLength % threadnum;
  26. long targetLength = fileLength / threadnum;
  27. for (int i = 0; i < threadnum; i++) {
  28. System.out.println((targetLength * i) + "-----"
  29. + (targetLength * (i + 1)));
  30. new FileWriteThread((targetLength * i), (targetLength * (i + 1)),
  31. sourseFilePath, targerFilePath).start();
  32. }
  33. if (modLength != 0) {
  34. new FileWriteThread((targetLength * 4), modLength, sourseFilePath,
  35. targerFilePath).start();
  36. }
  37. }
  38. /**
  39. * 写线程:指定文件开始位置、目标位置、源文件、目标文件,
  40. */
  41. static class FileWriteThread extends Thread {
  42. private long begin;
  43. private long end;
  44. private RandomAccessFile soursefile;
  45. private RandomAccessFile targerFile;
  46. public FileWriteThread(long begin, long end, String sourseFilePath,
  47. String targerFilePath) {
  48. this.begin = begin;
  49. this.end = end;
  50. try {
  51. this.soursefile = new RandomAccessFile(sourseFilePath, "rw");
  52. this.targerFile = new RandomAccessFile(targerFilePath, "rw");
  53. } catch (FileNotFoundException e) {
  54. }
  55. }
  56. public void run() {
  57. try {
  58. soursefile.seek(begin);
  59. targerFile.seek(begin);
  60. int hasRead = 0;
  61. byte[] buffer = new byte[1024];
  62. while (begin < end && -1 != (hasRead = soursefile.read(buffer))) {
  63. begin += hasRead;
  64. targerFile.write(buffer, 0, hasRead);
  65. }
  66. } catch (Exception e) {
  67. e.printStackTrace();
  68. } finally {
  69. try {
  70. soursefile.close();
  71. targerFile.close();
  72. } catch (Exception e) {
  73. }
  74. }
  75. }
  76. }
  77. }

多线程下载文件

测试方法

  1. import java.io.File;
  2. /**
  3. *
  4. * @author ChenSS 2016/11/7
  5. * @version 1.0
  6. */
  7. public class Test {
  8. private static final int NUMBER = 10;
  9. // public static final String URL_DOWNLOAD =
  10. // "http://www.swsm.net/data/attachment/forum/201506/19/171831uzzeejjxke1jkgme.jpg";
  11. public static final String URL_DOWNLOAD = "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png";
  12. public static final String PATH_TARGET = "F:/temp/download/";
  13. public static void main(String[] args) {
  14. Loader loder = new Loader();
  15. File file = loder.createFile(PATH_TARGET, URL_DOWNLOAD);
  16. loder.startLoadThread(NUMBER, file, URL_DOWNLOAD);
  17. }
  18. }

开线程,如何分线程代码逻辑

  1. import java.io.File;
  2. import java.io.IOException;
  3. import java.io.RandomAccessFile;
  4. import java.net.URL;
  5. import java.net.URLConnection;
  6. /**
  7. *
  8. * @author ChenSS 2016/11/7
  9. * @version 1.0
  10. */
  11. public class Loader {
  12. /**
  13. * 创建目标文件(希望保存的文件和下载的同名)
  14. *
  15. * @param targetPath
  16. * 目标路径
  17. * @param sourseURL
  18. * 根据源URL获取文件名
  19. * @return
  20. */
  21. public File createFile(String targetPath, String sourseURL) {
  22. return new File(targetPath
  23. + sourseURL.substring(sourseURL.lastIndexOf("/") + 1));
  24. }
  25. /**
  26. * 如果出现不整除的情况(如:11字节,4个线程,每个线程3字节,多出1字节),但是实际上RandomAccessFile的read()
  27. * 读到文件尾会返回-1,因此不考虑余数问题
  28. *
  29. * @param threadNum
  30. * 线程数量
  31. * @param targetFile
  32. * 目标文件
  33. * @param sourseURL
  34. * 源文件URL
  35. */
  36. public void startLoadThread(int threadNum, File targetFile, String sourseURL) {
  37. try {
  38. // 网络连接
  39. URLConnection connection = new URL(sourseURL).openConnection();
  40. long sourseSize = connection.getContentLengthLong();
  41. // 为目标文件分配空间
  42. this.openSpace(targetFile, sourseSize);
  43. // 分线程下载文件
  44. long avgSize = sourseSize / threadNum + 1;
  45. for (int i = 0; i < threadNum; i++) {
  46. System.out
  47. .println(avgSize * i + "------" + (avgSize * (i + 1)));
  48. new Thread(new DownloadsTask(avgSize * i, avgSize * (i + 1),
  49. targetFile, sourseURL)).start();
  50. }
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. }
  54. }
  55. /**
  56. * 为目标文件分配空间
  57. *
  58. * @param targetfile
  59. * 目标文件
  60. * @param sourseSize
  61. * 源文件大小
  62. */
  63. private void openSpace(File targetfile, Long sourseSize) {
  64. RandomAccessFile randomAccessFile = null;
  65. try {
  66. randomAccessFile = new RandomAccessFile(targetfile, "rw");
  67. randomAccessFile.setLength(sourseSize);
  68. } catch (Exception e) {
  69. e.printStackTrace();
  70. } finally {
  71. try {
  72. if (randomAccessFile != null)
  73. randomAccessFile.close();
  74. } catch (IOException e) {
  75. e.printStackTrace();
  76. }
  77. }
  78. }
  79. }

实现Runnable,线程下载逻辑

  1. import java.io.BufferedInputStream;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.RandomAccessFile;
  5. import java.net.URL;
  6. import java.net.URLConnection;
  7. /**
  8. *
  9. * @author ChenSS 2016/11/7
  10. * @version 1.0
  11. */
  12. public class DownloadsTask implements Runnable {
  13. private long start;
  14. private long end;
  15. private File file;
  16. private String loadUrl;
  17. /**
  18. * 构造函数
  19. *
  20. * @param start
  21. * 开始位置
  22. * @param end
  23. * 结束位置
  24. * @param targetFile
  25. * 目标文件
  26. * @param loadUrl
  27. * 下载网址
  28. */
  29. public DownloadsTask(long start, long end, File targetFile, String loadUrl) {
  30. this.start = start;
  31. this.end = end;
  32. this.file = targetFile;
  33. this.loadUrl = loadUrl;
  34. }
  35. @Override
  36. public void run() {
  37. BufferedInputStream bufferedInputStream = null;
  38. RandomAccessFile randomAccessFile = null;
  39. try {
  40. URL url = new URL(loadUrl);
  41. URLConnection conn = url.openConnection();
  42. bufferedInputStream = new BufferedInputStream(conn.getInputStream());
  43. randomAccessFile = new RandomAccessFile(file, "rw");
  44. // 源文件和目标文件的指针指向同一个位置
  45. bufferedInputStream.skip(start);
  46. randomAccessFile.seek(start);
  47. long readLen = end - start;
  48. // 如果比默认长度小,就没必要按照默认长度读取文件了
  49. byte[] bs = new byte[(int) (2048 < readLen ? 2048 : readLen)];
  50. while (start < end
  51. && (readLen = bufferedInputStream.read(bs)) != -1) {
  52. start += readLen;
  53. randomAccessFile.write(bs, 0, (int) readLen);
  54. }
  55. } catch (Exception e) {
  56. e.printStackTrace();
  57. } finally {
  58. //关闭流
  59. try {
  60. if (null != bufferedInputStream)
  61. bufferedInputStream.close();
  62. if (null != randomAccessFile)
  63. randomAccessFile.close();
  64. } catch (IOException e) {
  65. e.printStackTrace();
  66. }
  67. }
  68. }
  69. }

RandomAccessFile多线程下载、复制文件、超大文件读写的更多相关文章

  1. java读取大文件 超大文件的几种方法

    java 读取一个巨大的文本文件既能保证内存不溢出又能保证性能       import java.io.BufferedReader; import java.io.File; import jav ...

  2. 框架基础:ajax设计方案(三)--- 集成ajax上传技术 大文件/超大文件前端切割上传,后端进行重组

    马上要过年了,哎,回家的心情也特别的激烈.有钱没钱,回家过年,家永远是舔舐伤口最好的地方.新的一年继续加油努力. 上次做了前端的ajax的上传文件技术,支持单文件,多文件上传,并对文件的格式和大小进行 ...

  3. 前端通信:ajax设计方案(四)--- 集成ajax上传技术 大文件/超大文件前端切割上传,后端进行重组

    马上要过年了,哎,回家的心情也特别的激烈.有钱没钱,回家过年,家永远是舔舐伤口最好的地方.新的一年继续加油努力. 上次做了前端的ajax的上传文件技术,支持单文件,多文件上传,并对文件的格式和大小进行 ...

  4. RandomAccessFile多线程下载

    public class DownloadServer { ; private static String fileUrl = "https://dldir1.qq.com/qqtv/mac ...

  5. Java--使用多线程下载,断点续传技术原理(RandomAccessFile)

    一.基础知识 1.什么是线程?什么是进程?它们之间的关系? 可以参考之前的一篇文章:java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器 简 ...

  6. 图解:HTTP 范围请求,助力断点续传、多线程下载的核心原理

    题图:by Charles Loyer 一.序 Hi,大家好,我是承香墨影! HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又是由报文头(Header) ...

  7. AccessRandomFile多线程下载文件

    写一个工具类 package com.pb.thread.demo; import java.io.File; import java.io.FileNotFoundException; import ...

  8. java 网络编程基础 InetAddress类;URLDecoder和URLEncoder;URL和URLConnection;多线程下载文件示例

    什么是IPV4,什么是IPV6: IPv4使用32个二进制位在网络上创建单个唯一地址.IPv4地址由四个数字表示,用点分隔.每个数字都是十进制(以10为基底)表示的八位二进制(以2为基底)数字,例如: ...

  9. JAVA多线程下载网络文件

    JAVA多线程下载网络文件,开启多个线程,同时下载网络文件.   源码如下:(点击下载 MultiThreadDownload.java) import java.io.InputStream; im ...

随机推荐

  1. Latex 去掉行号

    本文主要讲如何去掉Latex的行号 删除\modulolinenumbers删除所有\linenumbers 删除\usepackage{lineno,hyperref} modulolinenumb ...

  2. 关于限制DHCP服务器广播的另类方法

    0. 引言 如图,家里有两台计算机,分别处于不同房间.其中一台PC1能够与光猫直连:另外一台PC2较远,考虑到光猫有WLAN功能,便使用了一个路由器无线桥接到光猫,然后有线连接到PC2(均与光猫处于同 ...

  3. 制作Windows服务项目详细攻略

    1.在windows服务下面获得根目录: string assemblyFilePath = Assembly.GetExecutingAssembly().Location; string asse ...

  4. [JAVA第二课] java命名规则

    Java良好的命名规则以及代码风格可以看出来一个程序员的功底,好多公司也会注重这方面,他们招聘员工在有些时候往往就是根据一个人的代码风格来招人,所以下面就就我知道的代码风格作简要的说明一下.Java命 ...

  5. PHP设计模式一:工厂方法设计模式

    一.什么是工厂方法模式 作为一种创建型设计模式,工厂方法模式就是要创建“某种东西”.对于工厂方法,要创建的“东西”是一个产品,这个产品与创建它的类之间不存在绑定. 实际上,为了保持这种松耦合,客户会通 ...

  6. emacs elpy代码补全功能

    emcas中使用elpy编辑python代码,经常需要格式化代码 格式化代码方法C-c C-r f (elpy-format-code) 使用这个快捷键时,需要保证两点, 1.已经安装了yapf或者a ...

  7. LaunchScreen.storyboard 换图的问题

    之前设置了`LaunchScreen.storyboard`,在这个storyboard中加了一个imageView,里面设置了一张图片launch.png,今天需要更换这个启动图片,我就直接去工程里 ...

  8. getSystemService详解

     android的后台运行在很多service,它们在系统启动时被SystemServer开启,支持系统的正常工作,比如MountService监听是否有SD卡安装及移除,ClipboardServi ...

  9. POJ3264 (RMQのST解法)

    For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One d ...

  10. 利用quartz实现定时调度

    1.Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.这里我介绍quartz的两种方式.我这里搭建 ...