java文件不存在就创建_Java中创建并写文件的5种方式【转载】

本文转自:https://blog.csdn.net/weixin_39685130/article/details/113491378

在Java中有很多的方法可以创建文件写文件,你是否真的认真的总结过?下面小编就帮大家总结一下Java中创建文件的五种方法。

在java中有很多的方法可以创建文件写文件,你是否真的认真的总结过?下面笔者就帮大家总结一下java中创建文件的五种方法。

实际上不只这5种,通过管道流的排列组合,其实有更多种,但是笔者总结的这五种可以说是最常用及最佳实践,

前提小知识
以前我在写技术文章涉及到“流关闭”、“连接关闭”的时候,经常有人留言:“还写技术文章,写个流都不知道close()”,这种留言我遇到过无数回!

在本文中大量的使用到了try-with-resources语法,这个语法真的是很久的了,但是的确还有小伙伴不知道(知道的小伙伴就略过吧)。我还是说一下,下文中的管道流不是我没close,是自动关闭close的。

1. Java 8 Files.newBufferedWriter
java8 提供的newBufferedWriter可以创建文件,并向文件内写入数据。可以通过追加写模式,向文件内追加内容。

2. Java 7 Files.write
下面的这种方式 Files.write ,是笔者推荐的方式,语法简单,而且底层是使用Java NIO实现的。同样提供追加写模式向已经存在的文件种追加数据。这种方式是实现文本文件简单读写最方便快捷的方式。

3. PrintWriter
PrintWriter是一个比较古老的文件创建及写入方式,从JDK1.5就已经存在了,比较有特点的是:PrintWriter的println方法,可以实现一行一行的写文件。

4. File.createNewFile()
createNewFile()方法的功能相对就比较纯粹,只是创建文件不做文件写入操作。返回true表示文件成功,返回 false表示文件已经存在.可以配合FileWriter 来完成文件的写操作。

5.最原始的管道流方法
最原始的方式就是使用管道流嵌套的方法,但是笔者觉得这种方法历久弥新,使用起来非常灵活。你想去加上Buffer缓冲,你就嵌套一个BufferedWriter,你想去向文件中写java对象你就嵌套一个ObjectOutputStream。但归根结底要用到FileOutputStream。

的初始化,构造方法返回后,一个对象创建完毕,可以把他的引用(地址)发布到外部,在外部就可以使用这个引用操纵这个对象。
clone 在第一步是和 new 相似的,都是分配内存,调用 clone 方法是,分配的内存和原对象(即调用 clone 方法的对象)相同,然后再使用原对象中对应的各个域,填充新对象的域,填充完成之后,clone 方法返回,一个新的相同的对象被创建,同样可以把这个新对象的引用发布到外部。

3.3 clone 对象的使用3.3.1 复制对象和复制引用的区别

Person p = new Person(23, "zhang");
Person p1 = p;
System.out.println(p);
System.out.println(p1);
1234
当 Person p1 = p;执行之后, 是创建了一个新的对象吗?首先看打印结果:

1.com.itheima.Person@2f9ee1ac
2.com.itheima.Person@2f9ee1ac
12
可以看出,打印的地址值是相同的,既然地址都是相同的,那么肯定是同一个对象。p 和 p1 只是引用而已,他们都指向了一个相同的对象 Person(23, “zhang”) 。可以把这种现象叫做引用的复制。上面代码执行完成之后, 内存中的情景如下图所示:


而下面的代码是真真正正的克隆了一个对象。

Person p = new Person(23, "zhang");
Person p1 = (Person) p.clone();
System.out.println(p);
System.out.println(p1);
1234
从打印结果可以看出,两个对象的地址是不同的,也就是说创建了新的对象, 而不是把原对象的地址赋给了一个新的引用变量:

1. com.itheima.Person@2f9ee1ac
2. com.itheima.Person@67f1fba0
12
以上代码执行完成后, 内存中的情景如下图所示:

3.3.2 深拷贝和浅拷贝
上面的示例代码中,Person 中有两个成员变量,分别是 name 和 age, name 是 String 类型, age 是 int 类型。代码非常简单,如下所示:

public class Person implements Cloneable{
tprivate int age ;
tprivate String name;

public Person(int age, String name) {
ttthis.age = age;
ttthis.name = name;
t}

tpublic Person() {}

tpublic int getAge() {
ttreturn age;
t}

tpublic String getName() {
ttreturn name;
t}

t@Override
tprotected Object clone() throws CloneNotSupportedException {
ttreturn (Person)super.clone();
t}
}
123456789101112131415161718192021222324
由于 age 是基本数据类型,那么对它的拷贝没有什么异议,直接将一个 4 字节的整数值拷贝过来就行。但是 name是 String 类型的, 它只是一个引用, 指向一个真正的 String 对象,那么对它的拷贝有两种方式:直接将原对象中的 name 的引用值拷贝给新对象的 name 字段, 或者是根据原 Person 对象中的 name 指向的字符串对象创建一个新的相同的字符串对象,将这个新字符串对象的引用赋给新拷贝的 Person 对象的 name 字段。这两种拷贝方式分别叫做浅拷贝和深拷贝。

下面通过代码进行验证。如果两个 Person 对象的 name 的地址值相同, 说明两个对象的 name 都指向同一个String 对象,也就是浅拷贝, 而如果两个对象的 name 的地址值不同, 那么就说明指向不同的 String 对象, 也就是在拷贝 Person 对象的时候, 同时拷贝了 name 引用的 String 对象, 也就是深拷贝。验证代码如下:

Person p = new Person(23, "zhang");
Person p1 = (Person) p.clone();
String result = p.getName() == p1.getName() ? "clone 是浅拷贝的" : "clone 是深拷贝的";
System.out.println(result);
1234
打印结果为:

clone 是浅拷贝的
1
所以,clone 方法执行的是浅拷贝, 在编写程序时要注意这个细节。

如何进行深拷贝:
由上一节的内容可以得出如下结论:如果想要深拷贝一个对象,这个对象必须要实现 Cloneable 接口,实现 clone方法,并且在 clone 方法内部,把该对象引用的其他对象也要 clone 一份,这就要求这个被引用的对象必须也要实现Cloneable 接口并且实现 clone 方法。那么,按照上面的结论,实现以下代码 Body 类组合了 Head 类,要想深拷贝Body 类,必须在 Body 类的 clone 方法中将 Head 类也要拷贝一份。代码如下:

static class Body implements Cloneable{
tpublic Head head;
t
tpublic Body() {}
t
tpublic Body(Head head) {
ttthis.head = head;
t}
t
t@Override
tprotected Object clone() throws CloneNotSupportedException {
ttBody newBody = (Body) super.clone();
ttnewBody.head = (Head) head.clone();
ttreturn newBody;
t}
}

static class Head implements Cloneable{
tpublic Face face;
t
tpublic Head() {}
t
t@Override
tprotected Object clone() throws CloneNotSupportedException {
ttreturn super.clone();
t}
}

public static void main(String[] args) throws CloneNotSupportedException {
tBody body = new Body(new Head(new Face()));
tBody body1 = (Body) body.clone();
tSystem.out.println("body == body1 : " + (body == body1) );
tSystem.out.println("body.head == body1.head : " + (body.head == body1.head));
}
12345678910111213141516171819202122232425262728293031323334
打印结果为:

body == body1 : false
body.head == body1.head : false
————————————————
版权声明:本文为CSDN博主「weixin_39685130」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_39685130/article/details/113491378

原文地址:https://www.cnblogs.com/DylanZ/p/14537183.html