如何将对象写入可读的文本文件

3

我希望将对象以人类可读的形式写入文本文件,但实际保存的文件是普通序列化对象,其中包含不需要的字符。

我该如何重写程序,以便将其保存为人类可读的文本文件?

import java.io.*;
class book implements Serializable 
{
    String name;
    String author;
    int nop;
    int price;
    int discount;

    void getDiscount()
    {
        int finalprice=price-((price/discount));
        System.out.println("Final price after discount="+finalprice);
    }

    public String toString()
    {
        return name+author+nop+price+discount;
    }
}

class fileio
{
    public static void main(String args[])
    {
        MainClass mainObject=new MainClass();
        mainObject.writeToFile();
        book javabook=new book();
        javabook.name="Java unleashed";
        javabook.author="someone";
        javabook.nop=1032;
        javabook.price=450;
        javabook.discount=10;
        javabook.getDiscount();
    }
        public void writeToFile()
        {
        try
        {
        File file=new File("JavaBook1.txt");
        FileWriter fw=new FileWriter(file.getAbsoluteFile());
        BufferedWriter bw=new BufferedWriter(fw);
        bw.write(book.toString());
        bw.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

    }
}

1
定义“可读性强”。 - Diogo Moreira
1
Java Unleashed,某人,1032,450,10 - violet kiwi
你需要将int字段更改为String字段,以便序列化后易于阅读。正如答案所述,你可以在Book类中编写一个方法,将Book的字段值以XML或文本形式写出。 - Gilbert Le Blanc
有人可以通过发布编辑后的代码来发布要进行的更改吗? - violet kiwi
请检查我的答案,它展示了如何实现 toString() 方法,以及其他内容。 - Steve P.
定义“可读性强”,我将其定义为... 可读的。哎呀! - Padronização S A
5个回答

6
你可以使用JAXBXStream将其序列化为XML。相对于二进制数据,XML更易读,所以也许XML适合你。假设你还想反序列化你的数据,这是一个不错的选择。

XML是Java中进行ASCII序列化的常规方式。 XStream使其变得非常容易。 - theglauber

5

请看下面是否解决了你的问题

重写Object类的toString()方法以返回对象的状态,然后使用文件编写器将其输出到文本文件中。

如果您想要具有XML表示形式,可以选择JAXB方法。

更新:

请忽略下面程序中的语法/编译错误,因为我没有测试过,但它将给您一个简要的想法。

class Book
{
    String name;
    String author;
    int nop;
    int price;
    int discount;

    void getDiscount()
    {
        int finalprice=price-((price/discount));
        System.out.println("Final price after discount="+finalprice);
    }

    public String toString() {
    return name + author +nop + price +discount;
    // above can be any format whatever way you want


    }
}

现在在你的主类中

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;

class Fileio
{
    public static void main(String args[])
    {
        Fileio mainObject=new Fileio();

        Book javabook=new book();
        javabook.name="Java unleashed";
        javabook.author="someone";
        javabook.nop=1032;
        javabook.price=450;
        javabook.discount=10;
        javabook.getDiscount();
        mainObject.writeToFile(javabook);
    }
        public void writeToFile(Book javabook)
        {
        try
        {
        File file=new File("JavaBook1.txt");
        FileWriter fw=new FileWriter(file.getAbsoluteFile());
        BufferedWriter bw=new BufferedWriter(fw);
        bw.write(javabook.toString());
        bw.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

谢谢您的回复。我不知道如何使用toString(),您能帮我编辑一下我的程序代码吗? - violet kiwi
编译错误:在文件file=..行中期望出现误差<identifier>。 - violet kiwi
我没有在我的系统前面。我忘了把它包在 try catch 块中。请查看更新后的代码。 - M Sach
错误:无法从静态上下文引用非静态方法toString。 - violet kiwi
1
我在这里没有看到任何真正的序列化。它只是使用了toString()方法,没有办法进行反序列化... - Agostino
显示剩余2条评论

2

两个简单的选项:

在您的代码中使用:

ReflectionToStringBuilder.toString(javabook, ToStringStyle.MULTI_LINE_STYLE);

将产生:

org.marmots.application.generator.Book@77459877[
  name=Java unleashed
  author=someone
  nop=1032
  price=450
  discount=10
]

这对于调试非常有用。如果你只有简单的字段,那就足够了;但是如果你在其中引用另一个bean(以及另一个,另一个...),它将打印出它的toString()方法,因此你可以用以下代码为所有值/传输对象覆盖toString方法,以便拥有良好的阅读方法。

通常我所做的是从一个基础bean类继承:

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

public abstract class ToStringReadable {
  @Override
  public String toString() {
    return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
  }
}

扩展ToStringReadable将使您所有的bean在调试时更易读。

在您的代码中(注意,您需要使用getter/setter发布属性,这是一个好习惯,甚至更好):

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.writeValue(new File("target/javabook.json"), javabook);

此时,它还将生成易于阅读的人类可读输出,即JSON格式:

{"name":"Java unleashed","author":"someone","nop":1032,"price":450}

使用JSON方法时,您无需覆盖toString方法,因为它会打印出所有字段,但在性能方面更重,因此对于调试,请使用第一种方法。
希望这可以帮助。

半最佳答案肯定是一个必须添加到S.O.F词汇表中的术语。这很好,但你使用外部库而不是自己创建例程。 (; - Padronização S A

1

这取决于您需要文件做什么。如果您不想使用对象的 toString() 表示,您需要提取每个对象的内容,并想出一个分隔符,并使用该分隔符来分隔数据(book(s))。请注意,您需要不同的分隔符来分隔每个对象中的数据。您可以标准化如何写入文件,以便轻松检索单个元素。如果您能想出一个分隔符,您可以将一个 book 的数据读入为一个 String,并使用 split() 将每个属性放入一个数组槽中。如果这只是给人们阅读的话,您可以做类似的事情,但要漂亮地格式化,以便人们知道他们实际上正在阅读什么。对象的 toString() 可能很好用于此:

供参考,这是您对象的 toString()

    public String toString()
    {
         return name + " " + author + " " + price; 
    }

那只是一个例子,但如果你将其放在书籍类中并尝试打印书籍对象,你将获得其“名称 作者 价格”作为输出。此外,您应该使用构造函数/方法为对象的实例成员分配值,这些成员应为“私有”。理想情况下,我认为您应该使用xml进行序列化;请参见XStream

如果你想看更多的代码,请查看M Sach的帖子。我本来想写更多,但在平板电脑上做这件事很痛苦... - Steve P.

0

您可以使用JAXB或JavaBeans将类实例序列化/反序列化为XML。在这两种情况下,您需要准备好您的类 - 使用注释或设置器/获取器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接