技术标签: 文件复制 JavaIO流 输入流和输出流 Java SE
目录
数据流:数据流(data stream)是一组有序,有起点和终点的字节的数据序列。包括输入流和输出流。数据流模式中,处理系统无法控制所处理的数据的到达顺序,由于数据量的庞大,数据流中的元素被处理后将被抛弃或存档(archive)。以后再想获取这些数据将会很困难,除非将数据存储在内存中,但由于内存大小通常远远小于数据流数据的数量,因此实际上通常只能在数据第一次到达时获取数据。
缓冲流:为了提高数据的传输效率,通常使用缓冲流(Buffered Stream),即为一个流配有一个缓冲区(buffer),一个缓冲区就是专门用于传输数据的内存块。当向一个缓冲流写入数据时,系统不直接发送到外部设备,而是将数据发送到缓冲区。缓冲区自动记录数据,当缓冲区满时,系统将数据全部发送到相应的设备。
当从一个缓冲流中读取数据时,系统实际是从缓冲区中读取数据。当缓冲区空时,系统就会从相关设备自动读取数据,并读取尽可能多的数据充满缓冲区。
JavaIO流图示:
IO流分类:
按照流向数据流向可以分为输入流和输出流。
按照处理数据类型的单位不同可以分为字节流和字符流。
字节流:InputStream和OutputStream是java中可以按照最小字节单位读取的流,即每次读写一个字节,字节流是直接连接到输入源的流。
字符流:是以字符为单位进行数据处理的IO流。本质其实就是基于字节流读取时,去查找指定的码表。
区别:
1.读写单位不同:字节流式以字节(8位2进制)为单位,每次读写一个字节。字符流是以字符为单位,根据码表映射字符,一次可能读多个字节。
2.处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是纯文本数据优先使用字符流,除此之外都使用字节流。
字符流使用代码演示:
public static void main(String[] args) throws IOException {
Reader fr = new FileReader("D:\\MyFiles\\poi\\IODemo.txt");
Writer fw = new FileWriter("D:\\MyFiles\\poi\\IODemo_fw.txt");
int len;
// 一次读一个字符数组
char[] chars = new char[1024];
while ((len = fr.read(chars)) != -1) {
fw.write(chars, 0, len);
fw.flush();
}
fw.close();
fr.close();
}
代码示例:
public static void main(String[] args) throws IOException {
// 斜杠为转义字符,在Java中需使用双斜杠或者反斜杠来进行表示
File file = new File("D:\\MyFiles\\poi\\IODemo.txt");
// 使用文件流——字节流方式来读取文件里边的内容
InputStream fis = new FileInputStream(file);
int len;
// 创建缓冲区数组大小为1024个字节
byte[] bytes = new byte[1024];
StringBuilder stringBuilder = new StringBuilder();
// 读取的字节数会作为整数返回,赋值给len,当流读到文件的末尾时,会返回-1
while ((len = fis.read(bytes)) != -1) {
String str = new String(bytes, 0, len);
stringBuilder.append(str);
}
// 关闭输入流
fis.close();
System.out.println(stringBuilder.toString());
}
其中
(len = fis.read(bytes)) != -1
表示从输入流中读取一些字节数并将它们存储到缓冲区数组bytes中。读取的字节数会作为整数返回,当流读到文件的末尾时,会返回-1。其中返回值len为从输入流读取到缓冲区的字节总数。
注:
1、读取的第一个字节存储在元素bytes[0]中,下一个字节存储在元素bytes[1]中,以此类推。读取的字节数最多等于bytes数组的长度。设k为实际读取的字节数;这些字节将存储在元素bytes[0]到bytes[k-1]中,而元素bytes[k]到bytes[bytes.length-1]不受影响。
2、StringBuilder是线程不安全的,StringBuffer是线程安全的。
String str = new String(bytes, 0, len);
3、通过使用平台的默认字符集解码指定的字节子数组,构造一个新的String。
代码示例:
public static void main(String[] args) throws IOException {
// 写入文件的地址
File file = new File("D:\\MyFiles\\poi\\fos.txt");
// 没有文件会创建文件,有文件会进行内容覆盖
OutputStream fos = new FileOutputStream(file);
String str = "this is a demo. / 这是一个演示。";
// 使用默认编码方式转换成字节码
byte[] bytes = str.getBytes();
// 从指定字节数组写入bytes.length字节到这个输出流。
fos.write(bytes);
fos.close();
}
代码示例:
public static void main(String[] args) throws IOException {
// 读入文件地址
InputStream fis = new FileInputStream("D:\\MyFiles\\poi\\a.jpg");
// 写入文件地址
OutputStream fos = new FileOutputStream("D:\\MyFiles\\poi\\b.jpg");
int len;
byte[] bytes = new byte[1024];
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
fos.flush();
}
// 关闭资源
fos.close();
fis.close();
}
因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要使用flush()
方法。
flush()
这个函数是清空的意思,用于清空缓冲区的数据流,进行流的操作时,数据先被读到内存中,然后再用数据写到文件中。有时候,当数据读完时,立刻调用close()
方法关闭读写流,可能会造成数据丢失。因为,读入数据完成时不代表写入数据完成,一部分数据可能会留在缓存区中,并没有写入到文件中去。
缓冲流,也叫高效流、是对4个FileXxx
流的“增强流”。
缓冲流的基本原理:
1、使用了底层流对象从具体设备上获取数据,并将数据存储到缓冲区的数组内。
2、通过缓冲区的read()方法从缓冲区获取具体的字符数据,这样就提高了效率。
3、如果用read方法读取字符数据,并存储到另一个容器中,直到读取到了换行符时,将另一个容器临时存储的数据转成字符串返回,就形成了readLine()功能。
也就是说在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。
缓冲书写格式为BufferedXxx
,按照数据类型分类:
BufferedInputStream
,BufferedOutputStream
BufferedReader
,BufferedWriter
读取文件内容格式如下:
(1).English:this is a demo ! ! !
(2).中文:这是一个演示!!!
代码示例:
public static void main(String[] args) throws IOException {
// 读取数据
BufferedReader br = new BufferedReader(new FileReader("D:\\MyFiles\\poi\\original.txt"));
// 创建集合,保存数据
HashMap<String, String> map = new HashMap<String, String>();
String line = null;
while ((line = br.readLine()) != null) {
// 解析文本
String[] split = line.split("\\.");
// 保存到集合
map.put(split[0], split[1]);
}
br.close();
// 写入数据
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\MyFiles\\poi\\copy.txt"));
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
// 写出拼接文本
bw.write(key + "." + value);
// 写出换行
bw.newLine();
}
bw.close();
}
代码示例:
public static void main(String[] args) throws IOException {
BufferedInputStream bi = new BufferedInputStream(new FileInputStream("D:\\MyFiles\\poi\\original.txt"));
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream("D:\\MyFiles\\poi\\original_bo.txt"));
int len;
byte[] bytes = new byte[8 * 1024];
while ((len = bi.read(bytes)) != -1) {
bo.write(bytes, 0, len);
}
bo.close();
bi.close();
}
文章参考:史上最骚最全最详细的IO流教程,没有之一! - 宜春 - 博客园
java.io.File
类是专门对文件进行操作的类,只能对文件本身进行操作,不能对文件内容进行操作。java.io.File
类是文件和目录路径名的抽象表示,主要用于文件和目录的创建、查找和删除等操作。
怎么理解上面两句话?其实很简单!
第一句就是说File跟流无关,File类不能对文件进行读和写也就是输入和输出!
第二句就是说File主要表示类似 D:\\文件目录1
与D:\\文件目录1\\文件.txt ,
前者是文件夹(Directory)后者则是文件(file),而File类就是操作这两者的类。
public String getAbsolutePath()
:返回此File的绝对路径名字符串。public String getPath()
:将此File转换为路径名字符串。public String getName()
:返回由此File表示的文件或目录的名称。public long length()
:返回由此File表示的文件的长度。绝对路径和相对路径
绝对路径:一个完整的路径,以盘符开头,例如 F://aaa.txt
。
相对路径:一个简化的路径,不以盘符开头,例如 //aaa.txt//b.txt
。
public boolean exists()
:此File表示的文件或目录是否实际存在。public boolean isDirectory()
:此File表示的是否为目录。public boolean isFile()
:此File表示的是否为文件。public boolean createNewFile()
:文件不存在,创建一个新的空文件并返回true
,文件存在,不创建文件并返回 false
。public boolean delete()
:删除由此File表示的文件或目录。public boolean mkdir()
:创建由此File表示的目录。public boolean mkdirs()
:创建由此File表示的目录,包括任何必需但不存在的父目录。其中,mkdirs()
和mkdir()
方法类似,但mkdir()
,只能创建一级目录,mkdirs()
可以创建多级目录比如//a//b//c
,所以开发中一般用mkdirs()
;
public String[] list()
:返回一个String数组,表示该File目录中的所有子文件或目录。
public File[] listFiles()
:返回一个File数组,表示该File目录中的所有的子文件或目录。
listFiles在获取指定目录下的文件或者文件夹时必须满足下面两个条件:
- 指定的目录必须存在
- 指定的必须是目录。否则容易引发返回数组为null,出现NullPointerException异常
代码示例:
public class CopyFiles {
public static void main(String[] args) throws IOException {
// 将路径srcDir下的文件复制到targetDir下
String srcDir = "D:\\MyFiles\\poi";
String targetDir = "D:\\MyFiles\\poi_copy";
copyDirectiory(srcDir, targetDir);
}
/**
* 复制文件夹的递归方法
*
* @param srcDir
* @param targetDir
* @throws IOException
*/
private static void copyDirectiory(String srcDir, String targetDir) throws IOException {
// 不是文件夹不进行操作
if (!new File(srcDir).isDirectory()) {
return;
}
// 创建目的文件夹
new File(targetDir).mkdirs();
// 列举目录中的文件
File[] files = new File(srcDir).listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
// 更新路径
String newSrcDir = srcDir + "\\" + files[i].getName();
String newTargetDir = targetDir + "\\" + files[i].getName();
// 进行递归
copyDirectiory(newSrcDir, newTargetDir);
}
if (files[i].isFile()) {
// 更新路径
String newSrcDir = srcDir + File.separator + files[i].getName();
String newTargetDir = targetDir + File.separator + files[i].getName();
copyFile(new File(newSrcDir), new File(newTargetDir));
}
}
}
/**
* 文件的读和写
*
* @param srcFile
* @param targetFile
* @throws IOException
*/
private static void copyFile(File srcFile, File targetFile) throws IOException {
BufferedInputStream bi = new BufferedInputStream(new FileInputStream(srcFile));
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(targetFile));
int len;
byte[] bytes = new byte[8 * 1024];
while ((len = bi.read(bytes)) != -1) {
bo.write(bytes, 0, len);
bo.flush();
}
bo.close();
bi.close();
}
}
文章浏览阅读190次。消息提示框:有时显示时覆盖想要看的界面,可注释!_qgcpopupdialog
文章浏览阅读273次。https://blog.csdn.net/ningjiebing/article/details/90600652Ambari 是什么Ambari 跟 Hadoop 等开源软件一样,也是 Apache Software Foundation 中的一个项目,并且是顶级项目。目前最新的发布版本是 2.0.1,未来不久将发布 2.1 版本。就 Ambari 的作用来说,就是创建、管理、监视 Hadoop 的集群,但是这里的 Hadoop 是广义,指的是 Hadoop 整个生态圈(例如 Hive,Hbase_ambri支持的数据库
文章浏览阅读74次。在使用ASP.NET MVC进行项目开发时,经常会碰到从Action向视图传值的问题,今天我就把我所知道的方式总结了一下,分成了以下六种:1.使用ViewData进行传值在Action中,有如下代码:ViewData["name"] = "Vibin1";则在视图中可以这样接收:姓名:@ViewData["name"]注意:ViewData是一个简单的字典,它的生命周期和所请求的V...
文章浏览阅读46次。我是我的项目中使用了ARC,有已个scrollview上面有三个View用来展示内容,每增加已个view就会移除另外一个view,使scrollview上面始终只有三个view.但是我发现一个问题,随着我翻页,内存在不断地增加.后来我写了一段测试代码:UIView *view = nil; while (TRUE) { [view removeFromSupervi
文章浏览阅读1.8k次,点赞2次,收藏7次。思路:中间层与客户端通过三个关键的接口过程进行交互操作(GetData,SetData,GetspData)GetData:获取数据集。客户端传递数据集名称给中间层,中间层根据请求的数据集名称从数据库的配置文件中获取相关信息,与客户的的条件集合一起给合成SQL语句SetData:提交数据集。客户端传递修改后的数据集Delta与名称给中间层,中间层根据请求的数据集名称从数据库的配置文件中获取相关..._delphi midas
文章浏览阅读3.1k次,点赞3次,收藏6次。vCenter是啥不多说了,看下百度百科https://baike.baidu.com/item/Vcenter/7474684?fr=aladdinvCenter的安装还是要说一下,步骤如下:1、找到vCenter的安装软件。名称VMware-vCenter-Server-Appliance-5.5.0.5100-1312297_OVF10.ova,这里是5.5版本,你可以理解为这个是已
文章浏览阅读110次。掌握下面的对GCC会有一个比较清晰的大致的了解:不经意间,GCC已发展到了4.3的版本,尽管在软件开发社区之外乏人闻问,但因为GCC在几乎所有开源软件和自由软件中都会用到,因此它的编译性能的涨落会直接影响到Linux 、Firefox 乃至于OpenOffice.org和Apache等几千个项目的开发。因此,把GCC摆在开源软件的核心地位是一点也不为过。另一方面,GCC4.3的出现,正在牵引着..._gcc开源协议
文章浏览阅读124次。JVM架构JVM被分为三个主要的子系统:类加载器子系统、运行时数据区和执行引擎。JVM架构图一. 类加载器子系统Java的动态类加载功能是由类加载器子系统处理。当它在运行时(不是编译时)首次引用一个类时,它加载、链接并初始化该类文件。1.1 加载类由此组件加载。启动类加载器 (BootStrap class Loader)、扩展类加载器(Extension cla...
文章浏览阅读2.6k次,点赞3次,收藏5次。#include<stdio.h>#include<math.h>int main(){ int n; double pi=acos(-1.0); scanf("%d",&n);//度数 printf("%f %f\n",sin(n/180.0*pi),cos(n/180.0*pi));//sin和cos内必须使用弧度制; ..._输入边及余弦求解代码
文章浏览阅读1.3w次。API_Level Platform_Version Version_Code NDK_Version 28 Android 9.0 Pie(馅饼) 27 Android 8.1 Oreo(奥利奥) 26 Android 8.0 Oreo(奥利奥) 25 Android 7.1 Noug..._android api 12 s是哪个单词
文章浏览阅读40次。正则表达式定义 正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。 列目录时, dir *.txt或ls *.txt中的*.txt就不是一个正则表达式,因为这里*与正则式的*的含义是不同的。 正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组...
文章浏览阅读4.1k次,点赞23次,收藏26次。路由器特点,网络IP地址规划网络间的特性,基本路由思想,编辑静态路由部分,查询设备整个路由表,查看特定的路由协议时使用,查询目的地址2.2.2.2的路由条目,IP路由表代码写法,IP路由表里的信息,路由表来源,路由表的信息,路由表选路规则,缺点:缺省路由,备份路由,等价路由,做实验的步骤......_等价路由和备份路由一样吗?