赞
踩
目录
日常生活中我们会遇到对txt、mp4等文件的读写操作,而Java中存在很多文件操作的相关类。那么先简单认识一些常用的文件操作类的特点。
File类:一般用它来表示一个文件或目录,文件操作方面只能创建文件、修改文件的属性。
FileInputStream、FileOutputStream类:通过字节流来读写文件,可以对文件中的数据进行操作,但是不能处理中文字符。
FileReader、FileWriter类:通过字符流来读写文件,可以处理中文字符。
BufferedReader、BufferedWriter类:提供通用的缓冲方式文本读取,一次性读取多个字符并缓存在内存中,以提高读取效率。
RandomAccessFile类:用于随机访问文件的类,支持对文件的任意位置进行读取和写入操作,可以提高读写效率。
PrintWriter类:用于将数据写入文件或标准输出的类,支持写入各种基本数据类型和字符串等。
MultipartFile类:Spring框架提供的一个用于处理HTTP multipart请求的接口,提供了获取文件输入流的方法,可以直接操作文件的字节流,支持流式处理,适合处理大文件,但是需要依赖Spring框架。
对于二进制文件(如图片、音频、视频等),不能像文本文件一样使用BufferedReader和BufferedWriter来读写,因为BufferedReader和BufferedWriter是面向字符的,它们会对读取的字节进行编码和解码,可能会导致读取出来的数据不正确。
正确方法是可以使用FileInputStream和FileOutputStream来进行读写,或者使用RandomAccessFile,它支持以字节为单位的随机访问,可以在文件中定位、读取或写入任意位置的数据。
类名 | 功能 | 适用对象 | 读写方式 | 异常处理 |
---|---|---|---|---|
File | 文件操作 | 任何文件 | N/A | IOException |
FileInputStream | 用于读取文件 | 二进制文件、文本文件、图片、音视频等 | 读 | FileNotFoundException、IOException |
FileOutputStream | 用于写入文件 | 二进制文件、文本文件、图片、音视频等 | 写 | FileNotFoundException、IOException |
FileReader | 用于读取文本文件 | 文本文件 | 读 | FileNotFoundException、IOException |
FileWriter | 用于写入文本文件 | 文本文件 | 写 | FileNotFoundException、IOException |
BufferedReader | 用于读取文本文件,可以按行读取,提供缓冲区 | 文本文件 | 读 | FileNotFoundException、IOException |
BufferedWriter | 用于写入文本文件,可以按行写入,提供缓冲区 | 文本文件 | 写 | FileNotFoundException、IOException |
RandomAccessFile | 用于随机访问文件,可以读写指定位置的数据,支持任何文件类型 | 二进制文件、文本文件、图片、音视频等 | 读写 | FileNotFoundException、IOException |
PrintWriter | 用于写入文本文件,可以指定编码方式,提供自动刷新功能 | 文本文件 | 写 | FileNotFoundException、IOException |
MultipartFile | 用于上传文件,常用于Web应用中 | 二进制文件、文本文件、图片、音视频等 | 读 | IOException |
了解了相关文件类特点之后,来讲讲如何实现文件的上传。
最简单的方法是使用FileInputStream、FileOutputStream类来实现文件读写。
- /**
- * 写文件,并保存到指定位置
- * @param file 文件
- */
- void uploadFile(File file) {
- // 文件保存路径
- String path = "C:\\Users\\uploadfile\\" + file.getName();
- try(// 创建一个FileInputStream对象用于读取文件
- FileInputStream fis = new FileInputStream(file);
- // 创建一个FileOutputStream对象用于写入文件
- FileOutputStream fos = new FileOutputStream(path)) {
-
- // 定义一个byte数组用于存放读取到的数据,作为缓存区
- byte[] buffer = new byte[1024];
- // 定义一个变量用于记录读取到的数据长度
- int len = -1;
- // 循环读取数据并写入到目标文件中
- while ((len = fis.read(buffer)) != -1) {
- fos.write(buffer, 0, len);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- /**
- * 读文件,并输出文件内容
- * @param file 文件
- */
- void downloadFile(File file) {
- try(FileInputStream fis = new FileInputStream(file)) {
- // 创建缓存数组
- byte[] buffer = new byte[1024];
- // 循环读取文件内容
- int len = -1;
- while ((len = fis.read(buffer)) != -1) {
- // 处理读取到的数据,例如将字节数组转换为字符串输出到控制台
- String content = new String(buffer, 0, len);
- System.out.print(content);
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
当然,如果用读文件方法去读取一个图片,则会显示乱码
在Web程序上我们就应该使用更方便的MultipartFile类来实现文件读写功能。
- /**
- * 文件上传
- * @param multipartFile 选择文件
- * @return 文件保存路径
- */
- @PostMapping("/test")
- //@ApiOperation("上传文件")
- public String uploadFile(@RequestParam("file") MultipartFile multipartFile) {
- //判断文件是否为空 isEmpty
- if (multipartFile == null || multipartFile.isEmpty()){
- return null;
- }
- //方法一:获取文件的原名称 getOriginalFilename
- String fileName = multipartFile.getOriginalFilename();
- //方法二(推荐):获取时间戳和文件的扩展名,拼接成一个全新的文件名; 用时间戳来命名是为了避免文件名冲突
- // String sourceFilename = multipartFile.getOriginalFilename();
- // String fileName = System.currentTimeMillis() + "." + sourceFilename.substring(sourceFilename.lastIndexOf(".") + 1);
- //定义文件存放路径
- String filePath = "C:\\Users\\uploadfile";
- //新建一个目录(文件夹)
- File dest = new File(filePath+ "\\" + fileName);
- //判断filePath目录是否存在,如不存在,就新建一个
- if (!dest.getParentFile().canExecute()){
- dest.getParentFile().mkdirs(); //新建一个目录
- }
- try {
- //文件输出
- multipartFile.transferTo(dest);
- }
- catch (Exception e) {
- e.printStackTrace();
- //拷贝失败要有提示
- return null;
- }
- String url = filePath + "\\" + fileName;
- return url;
- }
下载文件的的代码在Web程序上的编写就有所不同了。本地电脑访问服务器资源一般都是用域名+资源路径拼接来实现的,但是这样会出现线上访问的情况。如果我们要实现下载功能则需要修改响应头信息
- /**
- * 文件下载
- * @param fileName 文件名称
- * @return http报文,直接让浏览器下载文件
- */
- @GetMapping("/downloadfile")
- //@ApiOperation("下载文件")
- public ResponseEntity<byte[]> downloadFile(@RequestParam("filename") String fileName) {
- File file = new File("C:\\Users\\uploadfile\\" + fileName);
-
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
- headers.setContentDisposition(ContentDisposition.builder("attachment").filename(file.getName()).build());
- try {
- byte[] bytes = Files.readAllBytes(file.toPath());
- return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
- } catch(IOException e) {
- e.printStackTrace();
- return null;
- }
- }
要注意,正规流程是需要将返回值插入HashMap中或者是其Web专用的HashMap子类中来给前端传递信息的。
方法参数也应使用模板类来存储MultipartFile类和其它信息,模板类需要实现Serializable接口使其可以被序列化(好处:数据持久化、便于对象传输)。在这里就简单带过了。
Java文件读写(一)基础文件读写的详细操作:http://t.csdn.cn/yuIH1 (所在位置)
Java文件读写(二)网络传输大型文件的原理:http://t.csdn.cn/xyJpo
后面我会持续更新有关文件读写的文章。
关注作者,获取更多精彩内容!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。