在java中永远不能通过键盘输入的字符

时间:2016-03-04 12:24:03

标签: java string

目前我正在使用java创建一个应用程序,在该应用程序中,我正在尝试添加一个代码,手动将类序列化为字符串并将其保存到文件中

例如,有这个类

public class dog{
    int age;
    int type; 
    String name;
}

我选择使用这个函数手动将这个类变成一个字符串,产生类似于xml但只是我编造的东西。

public String classToString(dog d){
    String resultString = "" ;
    resultString + "#" ; 
    resultString + d.age;
    resultString + "#" ; 
    resultString + d.type;
    resultString + "#" ; 
    resultString + d.name;
    resultString + "#" ; 
    return resultString;

}

sp此函数将返回某种字符串,如

#7#4#Rex#

然后当我读取文件时,我将使用#作为某种分隔不同数据的标记来区分不同的数据,

我想知道的是这个,

  1. 这是一个好习惯吗?我不需要隐藏将直接从文本查看器打开文件的人的数据,所以我认为这没关系。但它有效吗?有更好的方法吗?

  2. 我面临的最大问题是如果应该存储的字符串包含我选择的特殊字符('#')怎么办?

    为了解决这个问题,我想知道是否有一个特殊的保留字符不能用键盘或其他用户界面编写,所以我永远不必保存包含该字符的字符串

  3. 我也想把每个第5个字符都清空,然后我只在4个空格上写数据并将每个第5个空格都空,这样我就可以将它用于特殊标记了。例如,如果年龄是7岁,类型是10,那么狗的名字是" abcdefghijklmnopqrstuvwxyz"结果字符串是

    #0007#0010#abcd ^ efgh ^ ijkl ^ ......... ^ yz<

  4. '#'是数据分隔符

    ^只是一个字符,意味着此时数据不应该分开

    <意味着如果此标记左侧有空白字符,则不应将其视为数据的一部分,并且应将其截断

3 个答案:

答案 0 :(得分:1)

只需使用StatefulSerializable类。这是一个可序列化类的示例:

public class Dog implements Serializable {
 ...
 }

然后您可以使用ObjectOutputStreamObjectInputStream分别编写和阅读对象。

ObjectOutputStream out = new ObjectOutputStream( yourFileStream );
out.writeObject(yourDogObject);

这会将yourDogObject写到yourFileStream

答案 1 :(得分:1)

例如,创建一个名为Stateful的接口。任何实现此接口的类都将负责加载和保存。

DogTest.java

public class DogTest {
    public static void main(String[] args) {
        Dog dogA = new Dog(7, 10, "abcdefghijklmnopqrstuvwxyz");

        String state = dogA.save();
        System.out.println(state); // #0007#0010#abcd^efgh^ijkl^mnop^qrst^uvwx^yz#

        Dog dogB = new Dog().load(state);
        System.out.println(dogB); // Dog [age=7, type=10, name=abcdefghijklmnopqrstuvwxyz]
    }
}

Stateful.java

public interface Stateful<T> {
    static final String DATA_SEP = "#";
    static final String SEGMENT_SEP = "^";

    T load(String data);
    String save();
}

Dog.java

public class Dog implements Stateful<Dog> {
    private int age;
    private int type;
    private String name;

    public Dog() {
        this(0, 0, "");
    }

    public Dog(int age, int type, String name) {
        super();
        this.age = age;
        this.type = type;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dog [age=" + age + ", type=" + type + ", name=" + name + "]";
    }

    @Override
    public Dog load(String data) {
        String[] fragments = StatefulUtil.parse(data);

        this.age = Integer.parseInt(fragments[1], 10);
        this.type = Integer.parseInt(fragments[2], 10);
        this.name = StatefulUtil.decode(fragments[3]);

        return this;
    }

    @Override
    public String save() {
        StringBuffer buff = new StringBuffer(Stateful.DATA_SEP);

        buff.append(StatefulUtil.format(this.age)).append(Stateful.DATA_SEP);
        buff.append(StatefulUtil.format(this.type)).append(Stateful.DATA_SEP);
        buff.append(StatefulUtil.encode(this.name)).append(Stateful.DATA_SEP);

        return buff.toString();
    }
}

StatefulUtil.java

public class StatefulUtil {
    public static CharSequence encode(String value) {
        return separate(escape(value), Stateful.SEGMENT_SEP, 4);
    }

    public static String decode(String value) {
        return join(value.split("\\" + Stateful.SEGMENT_SEP), "").toString();
    }

    private static String escape(String value) {
        return value.replace(Stateful.DATA_SEP, "\\" + Stateful.DATA_SEP);
    }

    public static CharSequence format(int value) {
        return String.format("%04d", value);
    }

    public static CharSequence separate(String value, String separator, int offset) {
        StringBuffer buff = new StringBuffer(value);
        int n = buff.length() / offset;

        for (int i = 0; i < n; i++) {
            int index = i + ((i + 1) * offset);
            buff.insert(index, separator);
        }

        return buff;
    }

    public static CharSequence join(String[] arr, String separator) {
        StringBuffer buff = new StringBuffer();

        if (arr != null) {
            if (arr.length > 0) {
                buff.append(arr[0]);
            }

            for (int i = 1; i < arr.length; i++) {
                buff.append(separator).append(arr[i]);
            }
        }

        return buff;
    }

    // Regular expression: /^#|[^\\\\]#/ - Match beginning '#' and each non-escaped '#"
    public static String[] parse(String data) {
        return data.split("^" + Stateful.DATA_SEP + "|[^\\\\]" + Stateful.DATA_SEP);
    }
}

答案 2 :(得分:0)

由于这样的应用程序可能会增长,并且数据发生变化,我的偏好是XML,使用带注释的JAXB。至少一些人类可读的文本,可能是版本的。

Dog dog = load(Dog.class, "dog.xml");

加载/保存代码类似于:

public <T> T load(Class<T> type, String path) {
    JAXBContext jc = JAXBContext.newInstance();
    Unmarshaller u = jc.createUnmarshaller();
    return type.cast(u.unmarshal(new FileInputStream(path));
}

public <T> void save(T obj, String path) {
    JAXBContext jc = JAXBContext.newInstance();
    Marshaller m = jc.createMarshaller();
    m.unmarshal(obj, new FileOutputStream(path));
}

使用注释,您可以控制XML:

@XmlRootElement(name="dog")
public class Dog implements Stateful<Dog> {

    @XmlAttribute(name = "vs")
    private String dataVersion = "1.0";

    @XmlAttribute(name = "age")
    private int age;

    @XmlAttribute
    private int type;

    @XmlElement(name = "name")
    private String name;
}

<dog vs="1.0" age="6" type="3">
    <name>Cerberus</name>
</dog>

可以有列表等等。