【问题标题】:Read/Write from a binary file从二进制文件读/写
【发布时间】:2015-01-08 04:05:30
【问题描述】:
import java.io.*;
public class Main2 {
    public static void main(String[] args) throws Exception {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("Text.t"));
        dos.writeByte(10101010);
        DataInputStream dis = new DataInputStream(new FileInputStream("Text.t"));
        int line;
        System.out.println(dis.readByte());
        dos.close();
        dis.close();
    }
}

我正在尝试将 10101010 写入我创建并打印其内容的二进制文件中。 当我运行它时,它显示 18 .. 为什么?为什么不是 10101010?此外,当我使用 textpad 打开 Text.t 文件时 它包含这个“垃圾”而不是 10101010。

【问题讨论】:

  • 你看到的“垃圾”是什么?
  • 你知道 10 101 010 是“一千万一十万十”吗?

标签: java binaryfiles


【解决方案1】:

10101010 % 256 = 18。这是您创建的整数的低字节。文本文件被归档为“垃圾”,因为您将其保存为二进制数据而不是文本。

如果您希望将您的号码保存为二进制字符串,则应使用FileWriterFileReader 而不是DataInput/OutputStream,并使用Integer.toBinaryString(int) 和Integer.parseInt(str,2);

【讨论】:

  • 正如我对新手说的那样,我能做些什么来编写这个二进制代码并且只是这个......不是箭头......只是 10101010。所以当我打印这个是 10101010跨度>
  • 是的,但是使用 Filewriter 每个 0 和 1 将被计为字节而不是位..
  • @Panagiotis123 你不能同时拥有它。要么将其保存为二进制文件,但不能将其作为文本读取,要么将其保存为文本。顺便说一句,除非您要保存数千个数字,否则实际文件大小(即 HD 上实际占用的空间)很可能是相同的(由于文件表的工作方式)
  • 对于实际大小,是的,你是对的......两个都是 1kb ..我有一个表格,其中包含每个字母的路径..例如,对于字母 a 路径是 0101,对于 b 010000 等......所以我想以某种方式在二进制文件中写入路径(路径是一个字符串),当我读取它时(在解压缩中......)我想用字母连接二进制文件的位/路径......那里没有任何方法可以在二进制文件中写入字符串以将 0/1 作为位,当我读取它时是相同的 0/1?
  • 如果您想直接以字符串形式读取二进制文件并且不需要进行操作,请使用FileWriter。如果要写入二进制数,请在数字前加上0b 或写入等效的十进制数,以便编译器以二进制形式读取。
【解决方案2】:

这是因为您将二进制文件打印到其中,然后将二进制文件读出。该二进制代码10101010 对应于您看到的箭头,但是当它被读回时,它由 Java 处理,因此以数字形式出现,而不是 ASCII(或 Unicode,取决于它的默认编码方式)表示。

【讨论】:

  • 那么我该怎么做才能写出这个二进制代码并成为这个......不是箭头......只是10101010。所以当我打印这个是10101010
  • @Panagiotis123 我已经回答了这个问题
【解决方案3】:

以二进制形式打开文件或其他数据流并不意味着您的整数运算现在都采用二进制数字系统表示的值的输入。这只是意味着您正在使用的数据不是人类可能读取的数据。

DataOutputStream 上的 writeByte 方法接受 int 输入并将其作为字节写出。因此,您的调用dos.writeByte(10101010); 写入十进制整数值10101010 的最低有效8 位。这个值恰好是0b00010010,它是 18 的二进制值。这就是它的来源。

如果要在文件中表示二进制值0b10101010,则需要写入整数值170:dos.writeByte(170)dos.writeByte(0xaa)

您对readByte 的调用遇到了同样的问题。它读取一个字节,System.out.println 将输出表示该字节的任何字符。如果要打印出一个字节的二进制值,请参见this other SO question

【讨论】:

    【解决方案4】:

    由于您在十进制整数上调用 writeByte(),您会得到意想不到的结果。 WriteByte() 在 1 字节或 8 位空间中写入一个整数。十进制数 10101010 与二进制数 1001 1010 0010 0001 0001 0010 相同,其最后 8 位为 0001 0010,即 18 作为十进制数。

    要解决此问题,请让 java 将您的 10101010 解释为带有 0b 前缀的二进制数,以将其转换为 binary literal

    dos.writeByte(0b10101010); 
    

    然后要将这些数据作为十进制字符串读回,您可以使用

    Byte b = (dis.readByte());
    String decimalString = String.format("%8s", Integer.toBinaryString(b1 & 0xFF)).replace(' ', '0');
    System.out.println(decimalString);
    

    João Silva 为this question 提供的字符串转换

    【讨论】:

    • @Panagiotis123 哎呀。忘记将正在读回的数据更改为字符串。让我编辑我的答案。
    • 如果二进制代码以 0 开头为 false 还是有问题的。例如 01010101 显示为 1010101
    • @Panagiotis123 我认为这是一个符号问题,试试这个。我还没有测试过。
    • b1 & 0xFF 你的意思是 b & 0xFF?使用 01011010 显示 00001000
    • 是的b1。抱歉,我真的不会继续尝试解决这个问题。对不起,我的回答没有帮助。你想让我删除它吗?还是你还需要从中拿出一些东西来做参考?
    【解决方案5】:

    您正在向文件Text.t 写入一个字节。如果您在 text 编辑器中打开该文件,那么您将看到该字节的单字符表示,这取决于编辑器决定使用的任何字符编码。

    如果您想查看由 0 和 1 组成的八位字符串,那么您需要一个文本文件,而不是二进制文件,并且您应该将数据输出为 String

    此外,Java 不会将您的数字识别为二进制文字。值10101010 是一个十进制 字面量,表示一个略大于一千万的数字。当传递给dos.writeByte() 时,它将被截断为单个字节。如果你真的想输出二进制表示为10101010的单个字节,那么你可以将其表示为0b10101010,或者十六进制文字:

    dos.writeByte(0b10101010);
    

    dos.writeByte(0xAA);
    

    【讨论】:

    • 是的 10101010 只是一个例子,我正在编写霍夫曼代码,我会看到很多 01010101...而且我不想写字符串,因为每个 1 或 0 都将被计为字节而不是位
    • 谢谢@ryanyuyu,我想我一直生活在过去。已更新答案以考虑使用二进制文字的可能性。
    猜你喜欢
    • 2012-01-26
    • 2018-07-26
    • 2016-06-14
    • 2021-06-03
    • 2019-04-20
    • 2019-09-18
    • 1970-01-01
    • 2016-08-30
    相关资源
    最近更新 更多