使用BufferedOutputStream在Java中。

huangapple go评论73阅读模式
英文:

Using BufferedOutputStream in Java

问题

最近,我一直在学习Java中的文件输入/输出(File I/O),我了解到缓冲流(Buffered Streams)通过间歇性地存储数据,只在缓冲区满时才将数据写入磁盘(或从磁盘读取),从而使整个过程更加高效。

现在,我有一个程序,其中我有一个包含256个布尔值的 ArrayList 和一个浮点数值。
我试图对这些数据进行序列化(我不希望仅以人类可读的形式写入数据)。
因此,我目前的做法是将 FileOutputStream 链接到 ObjectOutputStream,并使用其 writeObject() 方法首先写入布尔数组,然后写入浮点变量。在读取时,我使用 FileInputStreamObjectInputStream 进行类似的操作。

现在,由于我想知道如何在这里使用 BufferedOutputStream,我查阅了文档,但它的两个重载写入方法似乎对我来说不够灵活:

  1. 第一个方法接受一个字节数组以及一些用于偏移和长度的参数。
  2. 第二个方法接受一个字节。

那么,这是否意味着我必须将我的布尔数组转换为字节数组才能使用 BufferedOutputStream 对象?那么,我该如何将浮点数转换为字节呢?我还困惑于如何使用 BufferedInputStream 读取数据。
在经历了所有这些转换之后,使用缓冲是否值得呢?

以下是没有使用缓冲的原始代码:

public class MySaveListener implements ActionListener {
    public void actionPerformed(ActionEvent ev) {
        JFileChooser fileSave = new JFileChooser();
        fileSave.showSaveDialog(theFrame);
        saveFile(fileSave.getSelectedFile());
    }
}

private void saveFile(File file) {
    boolean[] checkboxState = new boolean[256];

    for(int i = 0; i < 256; i++) {
        JCheckBox check = (JCheckBox) checkboxList.get(i);
        if (check.isSelected()) {
            checkboxState[i] = true;
        }
    }

    try {
        FileOutputStream fileStream = new FileOutputStream(file);
        ObjectOutputStream os = new ObjectOutputStream(fileStream);
        os.writeObject(checkboxState);
        os.writeObject(1239.87f);
        os.close();
    } catch(Exception ex) {
        ex.printStackTrace();
    }
}

public class MyLoadListener implements ActionListener {
    public void actionPerformed(ActionEvent ev) {
        JFileChooser fileOpen = new JFileChooser();
        fileOpen.showOpenDialog(theFrame);
        loadFile(fileOpen.getSelectedFile());
    }
}

private void loadFile(File file) {
    boolean[] checkboxState = null;
    try {
        FileInputStream fileIn = new FileInputStream(file);
        ObjectInputStream is = new ObjectInputStream(fileIn);
        checkboxState = (boolean[]) is.readObject();
        float loadTempo = (float) is.readObject();
        is.close();
    } catch(Exception ex) {
        ex.printStackTrace();
    }

    for(int i = 0; i < 256; i++) {
        JCheckBox check = (JCheckBox) checkboxList.get(i);
        if (checkboxState[i]) {
            check.setSelected(true);
        } else {
            check.setSelected(false);
        }
    }
}

那么,要在这里使用 BufferedOutputStreamBufferedInputStream,我需要进行哪些更改呢?

英文:

Recently, I've been learning about File I/O in java, and I came to know that Buffered Streams make the whole process more efficient, by storing the data intermittently and only writing to the disk(or reading from it) when the buffer is full.

Now, I have a program where I have an ArrayList of 256 boolean, and a floating point value.<br>
I am trying to serialize this data(I do not wish to simply write the data in human-readable form).<br>
So what I do currently is have a FileOutputStream chained to an ObjectOutputStream and use its writeObject() method to first write the boolean array, and then the float variable. I do likewise when reading using FileInputStream and ObjectInputStream.

Now, since I'm curious how I would go about using the BufferedOutputStream in here, I went through the documentation but the two overloaded write methods it has don't seem flexible enough to me-

  1. The first, which takes a byte array and a couple more parameters for offset and length
  2. The second, which takes a byte.

So, would that mean I have to convert my boolean array to a byte array to be able to use the BufferedOutputStream object? How then would I convert my float to a byte? I'm also confused on how I would read in the data with BufferedInputStream.<br>
And would it be worth using Buffers here after all the conversion that's taking place?

Here's my original code without the buffers

public class MySaveListener implements ActionListener { //this is an inner class by the way
public void actionPerformed(ActionEvent ev) {
JFileChooser fileSave = new JFileChooser();
fileSave.showSaveDialog(theFrame);
saveFile(fileSave.getSelectedFile());
}
}
private void saveFile(File file){
boolean[] checkboxState = new boolean[256];
for(int i = 0; i &lt; 256; i++){
JCheckBox check = (JCheckBox) checkboxList.get(i);
if (check.isSelected()){
checkboxState[i] = true;
}
}
try{
FileOutputStream fileStream = new FileOutputStream(file);
ObjectOutputStream os = new ObjectOutputStream(fileStream);
os.writeObject(checkboxState);
os.writeObject(1239.87f);
os.close();
} catch(Exception ex){ex.printStackTrace();}
}
public class MyLoadListener implements ActionListener {
public void actionPerformed(ActionEvent ev) {
JFileChooser fileOpen = new JFileChooser();
fileOpen.showOpenDialog(theFrame);
loadFile(fileOpen.getSelectedFile());
}
}
private void loadFile(File file){
boolean[] checkboxState = null;
try{
FileInputStream fileIn = new FileInputStream(file);
ObjectInputStream is = new ObjectInputStream(fileIn);
checkboxState = (boolean[]) is.readObject();
float loadTempo = (float)is.readObject();
is.close();
} catch(Exception ex){ex.printStackTrace();}
for(int i = 0; i &lt; 256; i++){
JCheckBox check = (JCheckBox) checkboxList.get(i);
if (checkboxState[i]){
check.setSelected(true);
}
else{
check.setSelected(false);
}
}
}

So, what changes would I have to bring in here to make use of BufferedOutputStream and BufferedInputStream ?

答案1

得分: 2

你对缓冲的理解不正确。流(Stream)和写入器/读取器(Writer/Reader)缓冲在执行低效的写入/读取(比如逐行读取和处理)时很有用,而不仅仅是尝试尽快从流中读取。在写入方面,这意味着在发送数据之前进行一次完整的消息调用,而不是在发送数据之前进行多次写入调用。如果你在进行高效的读写操作,就不需要使用缓冲。

至于如何进行序列化的问题:对象流很容易使用,但最终可能导致数据不兼容。如果你希望序列化效率最优,我建议你将boolean[]转换为byte[],然后可以通过常规的输出流(OutputStream)进行写入。

英文:

Your understanding of Buffering is not correct. Stream and Writer/Reader buffers are useful if you are doing inefficient writing/reading, such as reading and processing line by line, rather than just trying to read from a stream as fast as you can. On the writing side, it means sending the complete message in 1 call, rather than making several write calls before sending the data. If you are doing efficient reading and writing, you don't need a buffer.

As to the question of how to serialize: The Object streams are easy to use, but end up leaving you with incompatible data eventually. If you want your serialization to be optimal, I'd advise you to convert the boolean[] to a byte[] which you can be written through a regular OutputStream

huangapple
  • 本文由 发表于 2020年6月5日 22:04:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/62217184.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定